/* date = January 22nd 2021 3:51 pm */

#ifndef BASE_TYPES_H
#define BASE_TYPES_H

////////////////////////////////
// NOTE(allen): Variadic Functions

#include <stdarg.h>

////////////////////////////////
// NOTE(allen): Basic Constants

global S8  min_S8  = (S8) 0x80;
global S16 min_S16 = (S16)0x8000;
global S32 min_S32 = (S32)0x80000000;
global S64 min_S64 = (S64)0x8000000000000000llu;

global S8  max_S8  = (S8) 0x7f;
global S16 max_S16 = (S16)0x7fff;
global S32 max_S32 = (S32)0x7fffffff;
global S64 max_S64 = (S64)0x7fffffffffffffffllu;

global U8  max_U8  = 0xff;
global U16 max_U16 = 0xffff;
global U32 max_U32 = 0xffffffff;
global U64 max_U64 = 0xffffffffffffffffllu;

global F32 machine_epsilon_F32 = 1.1920929e-7f;
global F32 pi_F32  = 3.14159265359f;
global F32 tau_F32 = 6.28318530718f;
global F32 e_F32 = 2.71828182846f;
global F32 gold_big_F32 = 1.61803398875f;
global F32 gold_small_F32 = 0.61803398875f;

global F64 machine_epsilon_F64 = 2.220446e-16;
global F64 pi_F64  = 3.14159265359;
global F64 tau_F64 = 6.28318530718;
global F64 e_F64 = 2.71828182846;
global F64 gold_big_F64 = 1.61803398875;
global F64 gold_small_F64 = 0.61803398875;

////////////////////////////////
// NOTE(allen): Symbolic Constants

typedef enum Axis{
  Axis_X,
  Axis_Y,
  Axis_Z,
  Axis_W
} Axis;

typedef enum Side{
  Side_Min,
  Side_Max
} Side;

typedef enum OperatingSystem{
  OperatingSystem_Null,
  OperatingSystem_Windows,
  OperatingSystem_Linux,
  OperatingSystem_Mac,
  OperatingSystem_COUNT
} OperatingSystem;

typedef enum Architecture{
  Architecture_Null,
  Architecture_X64,
  Architecture_X86,
  Architecture_Arm,
  Architecture_Arm64,
  Architecture_COUNT
} Architecture;

typedef enum Month{
  Month_Jan,
  Month_Feb,
  Month_Mar,
  Month_Apr,
  Month_May,
  Month_Jun,
  Month_Jul,
  Month_Aug,
  Month_Sep,
  Month_Oct,
  Month_Nov,
  Month_Dec
} Month;

typedef enum DayOfWeek{
  DayOfWeek_Sunday,
  DayOfWeek_Monday,
  DayOfWeek_Tuesday,
  DayOfWeek_Wednesday,
  DayOfWeek_Thursday,
  DayOfWeek_Friday,
  DayOfWeek_Saturday
} DayOfWeek;

////////////////////////////////
// NOTE(allen): Compound Types

typedef struct V2S32{
  S32 x;
  S32 y;
} V2S32;

typedef struct V2F32{
  F32 x;
  F32 y;
} V2F32;

typedef struct V3F32{
  F32 x;
  F32 y;
  F32 z;
} V3F32;

typedef struct V4F32{
  F32 x;
  F32 y;
  F32 z;
  F32 w;
} V4F32;

#define V2_EXPANDED(v) ((v).x), ((v).y)
#define V3_EXPANDED(v) ((v).x), ((v).y), ((v).z)
#define V4_EXPANDED(v) ((v).x), ((v).y), ((v).z), ((v).w)

typedef struct RangeF32{
  F32 min;
  F32 max;
} RangeF32;

typedef struct RectS32{
  S32 x0;
  S32 y0;
  S32 x1;
  S32 y1;
} RectS32;

typedef struct RectF32{
  F32 x0;
  F32 y0;
  F32 x1;
  F32 y1;
} RectF32;

////////////////////////////////
// NOTE(allen): Basic Compound Types

typedef struct Array_U32{
  U32 *vals;
  U64 count;
} Array_U32;

typedef struct Array_F32{
  F32 *vals;
  U64 count;
} Array_F32;

typedef struct Array_V2F32{
  V2F32 *vals;
  U64 count;
} Array_V2F32;

////////////////////////////////
// NOTE(allen): Data Access Flags

typedef U32 DataAccessFlags;
enum{
  DataAccessFlag_Read    = (1 << 0),
  DataAccessFlag_Write   = (1 << 1),
  DataAccessFlag_Execute = (1 << 2),
};

////////////////////////////////
// NOTE(allen): Time

typedef U64 DenseTime;

typedef struct DateTime{
  U16 msec; // [0,999]
  U8 sec;   // [0,60]
  U8 min;   // [0,59]
  U8 hour;  // [0,23]
  U8 day;   // [1,31]
  U8 mon;   // [1,12]
  S16 year; // 1 = 1 CE; 2020 = 2020 CE; 0 = 1 BCE; -100 = 101 BCE; etc.
} DateTime;

////////////////////////////////
// NOTE(allen): File Properties

typedef U32 FilePropertyFlags;
enum{
  FilePropertyFlag_IsFolder = (1 << 0),
};

typedef struct FileProperties{
  U64 size;
  FilePropertyFlags flags;
  DenseTime create_time;
  DenseTime modify_time;
  DataAccessFlags access;
} FileProperties;

////////////////////////////////
// NOTE(allen): Base Pre-Requisites

#if !defined(mem_reserve)
# error missing definition for 'mem_reserve' type: (U64)->void* 
#endif
#if !defined(mem_commit)
# error missing definition for 'mem_commit' type: (void*,U64)->B32
#endif
#if !defined(mem_decommit)
# error missing definition for 'mem_decommit' type: (void*,U64)->void
#endif
#if !defined(mem_release)
# error missing definition for 'mem_release' type: (void*,U64)->void
#endif

////////////////////////////////
// NOTE(allen): Arena Types

typedef struct Arena{
  struct Arena *current;
  struct Arena *prev;
  U64 alignment;
  B8  growing;
  U8  filler[7];
  U64 base_pos;
  U64 chunk_cap;
  U64 chunk_pos;
  U64 chunk_commit_pos;
} Arena;

typedef struct ArenaTemp{
  Arena *arena;
  U64 pos;
} ArenaTemp;

////////////////////////////////
// NOTE(allen): String Types

typedef struct String8{
  U8 *str;
  U64 size;
} String8;

typedef struct String8Node{
  struct String8Node *next;
  String8 string;
} String8Node;

typedef struct String8List{
  String8Node *first;
  String8Node *last;
  U64 node_count;
  U64 total_size;
} String8List;

typedef struct StringJoin{
  String8 pre;
  String8 mid;
  String8 post;
} StringJoin;

typedef U32 StringMatchFlags;
enum{
  StringMatchFlag_NoCase = 1 << 0,
};

typedef struct String16{
  U16 *str;
  U64 size;
} String16;

typedef struct String32{
  U32 *str;
  U64 size;
} String32;

#define str8_expand(s) (int)((s).size), ((s).str)

////////////////////////////////
// NOTE(allen): Unicode Helper Types

typedef struct StringDecode{
  U32 codepoint;
  U32 size;
} StringDecode;

////////////////////////////////
// NOTE(allen): PRNG Types

#include "pcg/pcg_basic.h"

typedef struct PRNG{
  pcg32_random_t gen[2];
} PRNG;

typedef struct PRNG_Seed{
  union{
    U8 v[32];
    U64 u64[4];
  };
} PRNG_Seed;


#endif //BASE_H
