//  DescriptionHere - common.h
//  Created by John Ryland (jryland@xiaofrog.com), 02/11/2017
//  Copyright (c) 2017 InvertedLogic
//  All rights reserved.
#pragma once

#include <vector>
#include <sstream>
#include <string>

#if !defined(STRINGIZE)
#  define STRINGIZE_DEFINES(x)   #x
#  define STRINGIZE(x)           STRINGIZE_DEFINES(x)
#endif

#if defined(__GNUC__)
#  define COMPILER_STR           "GCC"
#  define COMPILER_VERSION       (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
#  define COMPILER_VERSION_STR   STRINGIZE(__GNUC__) "." STRINGIZE(__GNUC_MINOR__) "." STRINGIZE(__GNUC_PATCHLEVEL__)
#elif defined(__clang__)
#  define COMPILER_STR           "CLANG"
#  define COMPILER_VERSION       (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__)
#  define COMPILER_VERSION_STR   STRINGIZE(__clang_major__) "." STRINGIZE(__clang_minor__) "." STRINGIZE(__clang_patchlevel__)
#else
#  error "Unsupported compiler"
#endif

// Mainly this is just designed for using with std::vector with pre-c++11 compilers
#define foreach(item, vec) \
    for (size_t keep = 1, count = 0, size = vec.size(); keep && count != size; keep = !keep, count++) \
      for (item = vec[count]; keep; keep = !keep)

// For pre-c++ compilers
#if !USE_CPP11
#  define nullptr   NULL
#endif

template <typename T>
struct Ratio
{
  Ratio(const T& den, const T& num) : denominator(den), numerator(num) {} 
  T operator*(const T& v) { return (v*denominator)/numerator; }
  T denominator, numerator;
};

template <typename T, typename R>
T lerp(T v1, T v2, R ratio)
{
  return v1 + ratio * (v2 - v1);
}

template<typename T>
std::string asString(const T& value)  // for pre-c++11 compilers otherwise could use std::to_string
{
  std::ostringstream oss;
  oss << value;
  return oss.str();
}

struct vec2i
{
  int x, y;
};

struct vec2f
{
  float x, y;
};

vec2f operator*(const vec2f& v, float c);
vec2f operator*(float c, const vec2f& v);
vec2f operator+(const vec2f& v1, const vec2f& v2);

struct vec4f
{
  float x, y, z, w;
};

// p1 and p3 are the 2 end points the curve starts/ends at
// p2 is another control point but not a point on the curve
// t is the ratio between the two end points to interpolate a result for
vec2i bezierCurve(const vec2i& p1, const vec2i& p2, const vec2i& p3, float t);

// a_tension       -1.0 -> 1.0     Round -> Tight
// a_bias          -1.0 -> 1.0     Pre shoot -> Post shoot
// a_continuity    -1.0 -> 1.0     Box corners -> Inverted corners
vec2f kochanekBartelsSpline(const std::vector<vec2f>& a_points, float t, float a_tension = 0.0f, float a_bias = 0.0f, float a_continuity = 0.0f);
vec2f catmulRomSpline(const std::vector<vec2f>& a_points, float t);
vec2f cubicSpline(const std::vector<vec2f>& a_points, float t);
vec2f lineSpline(const std::vector<vec2f>& a_points, float t);

void startThread(void*(*func)(void*), void* user);
void sleepMilli(int milliSeconds);

/*
Opaque Object Pattern - how to do without pointers?
-- header ------
#pragma once
struct SomeClass;                   // forward declaration
bool SomeClass_Init(SomeClass&);    // constructor - but doesn't allocate
void SomeClass_Deinit(SomeClass&);  // destructor
void SomeClass_SomeFunc(SomeClass&, int args);
// ... other functions
----------------
Problem here, there isn't a way given to allocate an object, just construct/init.
If know the size then can allocate on the heap, but not on the stack.
Only way to allocate on the stack is to know the size at compile time.
Knowing the size at compile time implies either making non-opaque, or having to
do something messy to keep some const size variable in sync with the struct definition.
----------------
Perhaps the solution is to automate this as a build step? It's an extra build pass, but
there might be compiling speed ups though from using opaque objects instead.
There might be a dependancy issue though in that the size of an object which contains
another object first needs the size of the other object to work out its own size. The
extra build pass that does this would need to figure that out.
----------------
alternative c++ approach is pimpl way, but this turns everything in to pointers
and extra allocations etc. No good for tiny objects in the 1000s. Fine for small numbers
of big objects where it makes sense.
----------------
Functional ADTs:
https://en.wikipedia.org/wiki/Abstract_data_type
functional programming style ADTs can be achieved by returning the new state

struct Stack;
typedef Stack* StackRef;             // type: handle to a stack state (opaque pointer)
typedef void* StackItem;             // type: value of a stack state (arbitrary address)

StackRef Stack_Empty();
StackRef Stack_Push(StackRef s, StackItem x);
StackRef Stack_Pop(StackRef s);
StackItem Stack_Top(StackRef s);

Can chain calls together:

StackItem item = Stack_Top(Stack_Push(Stack_Push(Stack_Empty(), StackItem_Int(10)), StackItem_Int(20)));
// Word stack appears alot above, perhaps c++ can automate something here

struct StackCls // equivolent in size to a StackRef
{
  static StackCls Empty()      { return (StackCls){Stack_Empty()}; }
  StackCls Push(StackItem x)   { return (StackCls){Stack_Push(m_stack, x)}; }
  StackCls Pop()               { return (StackCls){Stack_Pop(m_stack)}; } 
  StackItem Top()              { return Stack_Top(m_stack); }
private:
  StackRef m_stack;
};

How much different is this compared with using pimpl?

Can chain calls together like this instead:

StackItem item = StackCls::Empty().Push(StackItem_Int(10)).Push(StackItem_Int(20)).Top();
// It is a bit less wordy and perhaps reads a bit better
// I'm not sure if the overhead is zero or not, it may depend on the compiler, but it is small

*/


