#ifndef COMMON_H
#define COMMON_H
#include <time.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <stdarg.h>
#include <string.h>
#include <helianthus.h>
#include <GL/gl.h>
#include "geometry.h"
// types
typedef unsigned int Flags;
// log
static inline int dummy(int x) { return x; }
#define PREQUOTE(...) #__VA_ARGS__
#define QUOTE(...) PREQUOTE(__VA_ARGS__)
#define LOG(f, r, p0, p1, ...) ( fprintf((f), "%s%s: ", (p0), (p1)), fprintf((f), __VA_ARGS__), fprintf((f), "\n"), fflush(f), dummy(r) )
#define INF(...) LOG(stdout, 1, "INFO", "", __VA_ARGS__)
#define WRN(...) LOG(stderr, 1, "WARNING", "", __VA_ARGS__)
#define ERR(...) LOG(stderr, 0, "ERROR", "", __VA_ARGS__)
#define DIE(...) (ERR(__VA_ARGS__), exit(1), dummy(0))
#ifdef NDEBUG
#define DBG(...) (dummy(1))
#else
#define DBG(...) LOG(stdout, 1, "DEBUG: " __FILE__ ":" QUOTE(__LINE__) ": ", __func__, __VA_ARGS__)
#endif
#define TRC DBG("trace")
// alloc
#define alignof __alignof__
#define ALIGN(s, a) ((((s)-1)/(a)+1)*(a))
#define ASIZEOF(t) align(sizeof(t), alignof(t))
#define COUNTOF(a) (sizeof(a)/ASIZEOF(*a))
static inline size_t align(size_t s, size_t a) { return ALIGN(s, a); }
void* alloc(size_t size);
void* alloc2d(size_t cnt, size_t size);
// str
char* vstrprintf(const char *fmt, va_list args);
char* strprintf(const char *fmt, ...);
char* unquote(char *s, char prefix, char suffix);
char* readline(FILE *f);
static inline char* trim(char *s) { return unquote(s, 0, 0); }
// arithm
static inline double mind(double a, double b) { return a < b ? a : b; }
static inline double maxd(double a, double b) { return a < b ? b : a; }
static inline double lintr(double a, double b, double k) { return a*(1-k) + b*k; }
// rand
static inline int randSign() { return rand()%2*2 - 1; }
static inline double randOne() { return rand()/(double)RAND_MAX; }
static inline double randTwo() { return randOne()*2 - 1; }
static inline Vec vrandOne() { return vec(randOne(), randOne()); }
static inline Vec vrandTwo() { return vec(randTwo(), randTwo()); }
static inline unsigned int randColor() { return colorByRGB(randOne(), randOne(), randOne()); }
static inline unsigned int randColorPtr(const void *ptr) { int s = rand(); srand((size_t)ptr); unsigned int c = randColor(); srand(s); return c; }
// spline
void cubicto(double x0, double y0, double x1, double y1, double x2, double y2, double x3, double y3, int levels);
#endif