
#if !defined(BETRAY_H)
#define	BETRAY_H

#include "forge.h"

/* ----------------------------------------------------------------------------------------- */



#define BETRAY_CONTEXT_OPENGL
//#define BETRAY_CONTEXT_OPENGLES

#define BETRAY_WIN32_SYSTEM_WRAPPER

/* On Windows, we also need the main platform header file. */
#if defined _WIN32
#include <windows.h>
#endif

/* We need OpenGL, which is a bit harder to locate on Macintosh systems. */
#if defined __APPLE_CC__
#include <OpenGL/gl.h>
#else
#include <GL/gl.h>
#endif


#if defined BETRAY_SDL_SYSTEM_WRAPPER
#include <SDL/SDL.h>
#ifdef _WIN32
#ifdef UNDEF_MAIN
#undef main
#endif
#endif

#elif defined BETRAY_GLUT_SYSTEM_WRAPPER
/* Get hold of glut.h include file. Need to be Mac-specific, here. */
#if defined __APPLE_CC__
#include <GLUT/glut.h>
#else
#include <GL/glut.h>
#endif

#elif defined BETRAY_GLFW_SYSTEM_WRAPPER
#include <GL/glfw.h>
#elif defined BETRAY_WIN32_SYSTEM_WRAPPER
#ifdef BETRAY_CONTEXT_OPENGL
#include <GL/gl.h>
#endif
#ifdef BETRAY_CONTEXT_OPENGLES
#include "EGL/egl.h"
#include "GLES2/gl2.h"
#endif
#define extern extern __declspec(dllexport)
#define BETRAY_AUDIO_MIXER
#else
#error "Please choose a system wrapper to use."
#endif
#include "b_keys.h"

/* ----------------------------------------------------------------------------------------- */

#define B_POINTER_BUTTONS_COUNT 16
#define B_MAX_EVENT_COUNT 64
#define B_BUTTONS_COUNT (256 + 16) 

/* structure describing a single pointer */

typedef struct{
	float	pointer_x; /* current position */
	float	pointer_y;
	float	click_pointer_x[B_POINTER_BUTTONS_COUNT]; /* position of last click event */
	float	click_pointer_y[B_POINTER_BUTTONS_COUNT];
	float	delta_pointer_x; /* delta movement */
	float	delta_pointer_y;
	boolean	button[B_POINTER_BUTTONS_COUNT]; /* current button state */
	boolean	last_button[B_POINTER_BUTTONS_COUNT]; /* button state of previous frame */
	uint	button_count; /* number of buttons on the device */
	char	name[32];
}BInputPointerState;

typedef enum{
	B_AXIS_UNDEFINED,				/* Any axis that doesnt fit any pre definds description */
	B_AXIS_STICK,					/* Joystick */
	B_AXIS_SUBSTICK,				/* Thumb joystiq on top of joystick */
	B_AXIS_BUMPER_LEFT,				/* Left analog bumper top to bottom */
	B_AXIS_BUMPER_RIGHT,			/* Right analog bumper top to bottom */
	B_AXIS_PEDAL,					/* Pedals left to right ranging form 0 to 1*/
	B_AXIS_WHEEL,					/* Wheels */
	B_AXIS_CONTROLER_FORWARD,		/* gyroscopc or other input defining forward vector of controler*/
	B_AXIS_CONTROLER_UP,			/* gyroscopc or other input defining up vector of controler*/
	B_AXIS_CONTROLER_ACCELEROMETER, /* Accelerometer of controler */
	B_AXIS_CONTROLER_POS,			/* Pos of  controler */
	B_AXIS_SCREEN_FORWARD,			/* gyroscopc or other input defining forward vector of screen*/
	B_AXIS_SCREEN_UP,				/* gyroscopc or other input defining up vector of screen*/
	B_AXIS_SCREEN_ACCELEROMETER,	/* Accelerometer of screen */
	B_AXIS_SCREEN_POS,				/* Pos of screen */
	B_AXIS_OBJECT_FORWARD,			/* gyroscopc or other input defining forward vector of object beeing manipulated on screen*/
	B_AXIS_OBJECT_UP,				/* gyroscopc or other input defining up vector of object beeing manipulated on screen*/
	B_AXIS_OBJECT_ACCELEROMETER,	/* Accelerometer of object beeing manipulated on screen*/
	B_AXIS_OBJECT_POS,				/* Pos of object of object beeing manipulated on screen*/
	B_AXIS_ZOOM,					/* ZOOM */
	B_AXIS_SCORLL					/* SCROLL */
}BAxisType;

typedef struct{
	float			axis[3]; /* position of axis ranged -1.0 to 1.0*/
	uint			axis_count; /* number of axis in use (1-3)*/
	BAxisType		axis_type; /* Axis description, see lis above for pre defined axis types */
	char			name[32]; /* name of axis input */
}BInputAxisState;

typedef struct{
	uint	button;
	uint	character;
	boolean state;
}BButtonEvent;

/* For each frame the main loop is usualy called at least 3 times, once for udating the screen (BAM_DRAW) once for input events (MAM_EVENT) and once for computation (BAM_MAIN).  */

typedef enum{
	BAM_DRAW, /* re draw the frame but do not advance time. can be called multiple times for multi display or sterioscopic systems */
	BAM_EVENT, /* manage input, can be called multiple times if hardware has multipl separate input devices for multiple users, like more them one joypad */
	BAM_MAIN /* main idle loop, called even if the program is iconized and doesnt redraw or has input focus. Useful for keeping things like network conecctions alive.*/
}BActionMode;

/* A pointer to the BInputState structure is given when the main loop is executed, It contains the input state and executuon mode */

#define B_EVENT_COUNT_MAX 16

typedef struct{
	BInputPointerState *pointers; /* description of state of pointers (first is mouse pointer if availabel)*/
	uint			pointer_count;
	BInputAxisState *axis; /* analog input, joysticks, wheels, pedals, tracking....*/
	uint			axis_count;
//	uint			*buttons; /* list of ids of buttons that can be read out using the button API below */
//	uint			button_count;
	BButtonEvent	button_event[B_EVENT_COUNT_MAX]; /* Button events*/
	uint			button_event_count;
	double			delta_time; /* delta time for update */
	double			minute_time; /* timer in fractions of minutes that loops every minute, not syncronized with clock */
	uint			device_id; /* DEvice id if multiple sets of controllers are connected. should be zero if only one controler connected */
	uint			device_count;
	uint			draw_id; /* current id if we have a multi dispalay output. By default zero. Useful in order to only have to render shadowmaps once for multiple displays*/
	uint			draw_count; /* The number of displays we will render */
	BActionMode		mode; /* what is the purpouse of execution */
}BInputState;

/* Defines for all buttons. Note that they are variables!*/

#ifdef BETRAY_BUTTON_BEGIN

#define BETRAY_BUTTON_CANCEL
#define BETRAY_BUTTON_BACK		
#define BETRAY_BUTTON_TAB
#define BETRAY_BUTTON_CLEAR
#define BETRAY_BUTTON_RETURN
#define BETRAY_BUTTON_SHIFT

#define BETRAY_BUTTON_MENU
#define BETRAY_BUTTON_PAUSE
#define BETRAY_BUTTON_CAPS_LOCK
#define BETRAY_BUTTON_ESCAPE

#define BETRAY_BUTTON_SPACE

#define BETRAY_BUTTON_PREV
#define BETRAY_BUTTON_NEXT

#define BETRAY_BUTTON_END
#define BETRAY_BUTTON_HOME

#define BETRAY_BUTTON_LEFT
#define BETRAY_BUTTON_UP
#define BETRAY_BUTTON_RIGHT
#define BETRAY_BUTTON_DOWN

#define BETRAY_BUTTON_SELECT
#define BETRAY_BUTTON_PRINT
#define BETRAY_BUTTON_EXECUTE
#define BETRAY_BUTTON_SCREENSHOT
#define BETRAY_BUTTON_INSERT
#define BETRAY_BUTTON_DELETE
#define BETRAY_BUTTON_BACKSPACE
#define BETRAY_BUTTON_HELP

#define BETRAY_BUTTON_0
#define BETRAY_BUTTON_1
#define BETRAY_BUTTON_2
#define BETRAY_BUTTON_3
#define BETRAY_BUTTON_4
#define BETRAY_BUTTON_5
#define BETRAY_BUTTON_6
#define BETRAY_BUTTON_7
#define BETRAY_BUTTON_8
#define BETRAY_BUTTON_9

#define BETRAY_BUTTON_A
#define BETRAY_BUTTON_B
#define BETRAY_BUTTON_C
#define BETRAY_BUTTON_D
#define BETRAY_BUTTON_E
#define BETRAY_BUTTON_F
#define BETRAY_BUTTON_G
#define BETRAY_BUTTON_H
#define BETRAY_BUTTON_I
#define BETRAY_BUTTON_J
#define BETRAY_BUTTON_K
#define BETRAY_BUTTON_L
#define BETRAY_BUTTON_M
#define BETRAY_BUTTON_N
#define BETRAY_BUTTON_O
#define BETRAY_BUTTON_P
#define BETRAY_BUTTON_Q
#define BETRAY_BUTTON_R	
#define BETRAY_BUTTON_S
#define BETRAY_BUTTON_T
#define BETRAY_BUTTON_U
#define BETRAY_BUTTON_V
#define BETRAY_BUTTON_W
#define BETRAY_BUTTON_X
#define BETRAY_BUTTON_Y
#define BETRAY_BUTTON_Z

#define BETRAY_BUTTON_NUM_0
#define BETRAY_BUTTON_NUM_1
#define BETRAY_BUTTON_NUM_2
#define BETRAY_BUTTON_NUM_3
#define BETRAY_BUTTON_NUM_4
#define BETRAY_BUTTON_NUM_5
#define BETRAY_BUTTON_NUM_6
#define BETRAY_BUTTON_NUM_7
#define BETRAY_BUTTON_NUM_8
#define BETRAY_BUTTON_NUM_9

#define BETRAY_BUTTON_MULTIPLY
#define BETRAY_BUTTON_ADD
#define BETRAY_BUTTON_SUBTRACT
#define BETRAY_BUTTON_DIVIDED

#define BETRAY_BUTTON_F1
#define BETRAY_BUTTON_F2
#define BETRAY_BUTTON_F3
#define BETRAY_BUTTON_F4
#define BETRAY_BUTTON_F5
#define BETRAY_BUTTON_F6
#define BETRAY_BUTTON_F7
#define BETRAY_BUTTON_F8
#define BETRAY_BUTTON_F9
#define BETRAY_BUTTON_F10
#define BETRAY_BUTTON_F11
#define BETRAY_BUTTON_F12
#define BETRAY_BUTTON_F13
#define BETRAY_BUTTON_F14
#define BETRAY_BUTTON_F15
#define BETRAY_BUTTON_F16
#define BETRAY_BUTTON_F17
#define BETRAY_BUTTON_F18
#define BETRAY_BUTTON_F19
#define BETRAY_BUTTON_F20
#define BETRAY_BUTTON_F21
#define BETRAY_BUTTON_F22
#define BETRAY_BUTTON_F23
#define BETRAY_BUTTON_F24

#define BETRAY_BUTTON_VOLUME_DOWN
#define BETRAY_BUTTON_VOLUME_UP
#define BETRAY_BUTTON_NEXT_TRACK
#define BETRAY_BUTTON_PREVIOUS_TRACK
#define BETRAY_BUTTON_STOP
#define BETRAY_BUTTON_PLAY_PAUSE

/* first row of face buttons */
#define BETRAY_BUTTON_FACE_A
#define BETRAY_BUTTON_FACE_B
#define BETRAY_BUTTON_FACE_C
#define BETRAY_BUTTON_FACE_D

/* second row of face buttons */
#define BETRAY_BUTTON_FACE_X
#define BETRAY_BUTTON_FACE_Y
#define BETRAY_BUTTON_FACE_Z
#define BETRAY_BUTTON_FACE_W

#define BETRAY_BUTTON_YES
#define BETRAY_BUTTON_NO
#define BETRAY_BUTTON_UNDO
#define BETRAY_BUTTON_REDO
#define BETRAY_BUTTON_SELECT
#define BETRAY_BUTTON_SEARCH
#define BETRAY_BUTTON_SHOLDER_LEFT_A
#define BETRAY_BUTTON_SHOLDER_LEFT_B
#define BETRAY_BUTTON_SHOLDER_LEFT_C
#define BETRAY_BUTTON_SHOLDER_LEFT_D
#define BETRAY_BUTTON_SHOLDER_RIGHT_A
#define BETRAY_BUTTON_SHOLDER_RIGHT_B
#define BETRAY_BUTTON_SHOLDER_RIGHT_C
#define BETRAY_BUTTON_SHOLDER_RIGHT_D
#define BETRAY_BUTTON_SCROLL_UP
#define BETRAY_BUTTON_SCROLL_DOWN
#define BETRAY_BUTTON_SCROLL_LEFT
#define BETRAY_BUTTON_SCROLL_RIGHT
#define BETRAY_BUTTON_INVENTORY_NEXT
#define BETRAY_BUTTON_INVENTORY_PREVIOUS

#endif

/* possible contexts that canbe opend, currently only OpenGL but others could be possible in the future */

typedef enum{
	B_CT_OPENGL,
	B_CT_OPENGLES2,
	B_CT_OPENGL_OR_ES
}BContextType;

/* find out what Betray implementation supports */
typedef enum{
	B_SF_POINTER_COUNT_MAX, /* whats the maximum number of pointers */
	B_SF_FULLSCREEN, /* Does the system support full screen */
	B_SF_WINDOWED,/* Does the system support window mode */
	B_SF_VIEW_POSITION, /* Does the system manipulate view vantage */
	B_SF_VIEW_ROTATION, /* Does the system manipulate the view direction*/
	B_SF_MOUSE_WARP, /* Does the syetem support mouse warp*/
	B_SF_EXECUTE, /* Does the system support execute */
	B_SF_REQUESTER, /* Can the system support save/load requesters */
	B_SF_CLIPBOARD, /*Does the syetem support cut and paste */
	B_SF_COUNT /*Number of members of this Enum */
}BSupportedFunctionality;

#ifndef BETRAY_PLUGGIN_DEFINES

extern uint		betray_support_context(BContextType context_type);
extern uint		betray_support_functionality(BSupportedFunctionality funtionality);

/* display, screen mode and wiev angle API (Must always be supported) */

extern void		betray_init(BContextType context_type, int argc, char **argv, uint window_size_x, uint window_size_y, uint samples, boolean window_fullscreen, char *name);
BContextType	betray_context_type_get();
extern boolean	betray_screen_mode_set(uint x_size, uint y_size, uint samples, boolean fullscreen); /* change screen mode*/
extern double	betray_screen_mode_get(uint *x_size, uint *y_size, boolean *fullscreen); /* set screen mode */
extern void		betray_view_vantage(float *pos); /* head pos, screen positioned at 0, 0, 0 with the width randing form -1.0 to 1.0 horizontaly */
extern void		betray_view_direction(float *matrix);  /* 4X4 rotation matrix */
extern BInputState *betray_get_input_state(void);



/* Action Func (must always be suported)*/

extern void		betray_action_func_set(void (*input_compute_func)(BInputState *data, void *user_pointer), void *user_pointer); /* set a function pointer that will be the main loop of the application */
extern void		betray_launch_main_loop(void); /* start the main loop */

/* Mouse Warp */

extern void		betray_set_mouse_warp(boolean warp); /* warp mouse to never hit the edges. Renders pointer_x/y void */
extern void		betray_set_mouse_move(float x, float y);

/* System Commands */

extern boolean	betray_execute(const char *command); /* execute comand on platform */

/* Save and load requesters, if the get functions return a pointer you need to free it */

extern void		betray_requester_save(char **types, uint type_count); /* lounge a requester to save something */
extern void		betray_requester_load(char **types, uint type_count); /* lounge arequester to load something*/
extern char		*betray_requester_save_get(void); /* get the pathe from the save requester */
extern char		*betray_requester_load_get(void); /* get the pathe from the load requester */

/* Cut and Paste */

extern void		betray_clipboard_set(char *text);
extern char		*betray_clipboard_get(void);

/* Timer (Must always be supported)*/

extern void		betray_get_current_time(uint32 *seconds, uint32 *fractions);
extern float	betray_time_delta_get(void); /* get delta time of current time step*/

/* OpenGL API (Must be suported if B_CT_OPENGL is suported)*/

extern void		betray_gl_context_update_func_set(void (*context_func)(void)); /* set function pointer car will be called if OpenGL context is lost */
extern void		*betray_gl_proc_address_get(void); /* get proc address for openGL extensions */
extern uint		betray_gl_screen_fbo_get(void); /* get the FBO id that should be used to draw to screen, (by default should be 0, but can be diffent to support Betray implementations that render an app to a texture.)*/

/* Button and key API (Must always be suported) */

extern boolean	betray_button_get(uint button); /* was this button pressed this time step */
extern void		betray_button_get_up_down(boolean *press, boolean *last_press, uint button); /* what is the state of a button this ad previous time step*/
extern boolean	betray_button_get_name(uint button, char *name, uint buffer_size); /* get the name of the key*/
extern void 	betray_button_keyboard(boolean show); /* Tell the system that a beyboard is needed. (god for syetms with on screen keyboards)*/

#endif

/* Sound API for 3D sound */

#define BETRAY_TYPE_INT8 0
#define BETRAY_TYPE_INT16 1
#define BETRAY_TYPE_INT32 2
#define BETRAY_TYPE_FLOAT32 3

#ifndef BETRAY_PLUGGIN_DEFINES

extern uint		betray_audio_sound_create(uint type, uint stride, uint length, uint frequency, void *data, char *name); /* load sound data in to betray*/
extern void		betray_audio_sound_destroy(uint sound); /* unload sound data */

extern uint		betray_audio_sound_play(uint sound, float *pos, float *vector, float speed, float volume, boolean loop, boolean ambient); /* play a sound (ambient equals fixed position to head)*/
extern void		betray_audio_sound_set(uint play, float *pos, float *vector, float speed, float volume, boolean loop, boolean ambient); /* change settings for an already playing sound*/
extern void		betray_audio_sound_stop(uint play); /* stop playing a sound */

extern void		betray_audio_listener(float *pos, float *vector, float *forward, float *side, float scale); /* define listener position. */
extern void		betray_audio_master_volume_set(float volume); /* set master volume */
extern float	betray_audio_master_volume_get(void); /* get current volume */
extern void		betray_audio_master_volume_silence_cutoff(float volume); /* do not play sounds with lower volume then this */

#endif

/* Settings api*/

typedef enum{
	BETRAY_ST_TOGGLE,
	BETRAY_ST_SELECT,
	BETRAY_ST_NUMBER_FLOAT,
	BETRAY_ST_NUMBER_INT,
	BETRAY_ST_SLIDER,
	BETRAY_ST_2D,
	BETRAY_ST_3D,
	BETRAY_ST_COLOR,
	BETRAY_ST_4X4_MATRIX,
}BSettingType;

#ifndef BETRAY_PLUGGIN_DEFINES

extern uint		 betray_settings_count();
extern BSettingType betray_settings_type(uint id);
extern char		*betray_settings_name(uint id);

extern boolean	betray_settings_toggle_get(uint id);
extern void		betray_settings_toggle_set(uint id, boolean	toggle);

extern uint		betray_settings_select_get(uint id);
extern void		betray_settings_select_set(uint id, uint select);
extern uint		betray_settings_select_count_get(uint id);
extern char		*betray_settings_select_name_get(uint id);

extern float	betray_settings_number_float_get(uint id);
extern void		betray_settings_number_float_set(uint id, float number);

extern int		betray_settings_number_int_get(uint id);
extern void		betray_settings_number_int_set(uint id, int number);

extern float	betray_settings_slider_get(uint id);
extern void		betray_settings_slider_set(uint id, float slider);

extern void		betray_settings_2d_get(uint id, float *x, float *y);
extern void		betray_settings_2d_set(uint id, float x, float y);

extern void		betray_settings_3d_get(uint id, float *x, float *y, float *z);
extern void		betray_settings_3d_set(uint id, float x, float y, float z);

extern void		betray_settings_color_get(uint id, float *red, float *green, float *blue);
extern void		betray_settings_color_set(uint id, float red, float green, float blue);

extern void		betray_settings_4x4_matrix_get(uint id, float *matrix);
extern void		betray_settings_4x4_matrix_set(uint id, float *matrix);

#endif

#undef extern

#endif
