#ifndef app_hpp
#define app_hpp

#define app_memory_size (1024 * 1024 * 512)

#include <new>
#include <stdint.h>

struct Arena;

#define key_xmacro() \
	x(key_unknown) \
	x(key_A) \
	x(key_B) \
	x(key_C) \
	x(key_D) \
	x(key_E) \
	x(key_F) \
	x(key_G) \
	x(key_H) \
	x(key_I) \
	x(key_J) \
	x(key_K) \
	x(key_L) \
	x(key_M) \
	x(key_N) \
	x(key_O) \
	x(key_P) \
	x(key_Q) \
	x(key_R) \
	x(key_S) \
	x(key_T) \
	x(key_U) \
	x(key_V) \
	x(key_W) \
	x(key_X) \
	x(key_Y) \
	x(key_Z) \
	x(key_f1) \
	x(key_f2) \
	x(key_f3) \
	x(key_f4) \
	x(key_f5) \
	x(key_f6) \
	x(key_f7) \
	x(key_f8) \
	x(key_f9) \
	x(key_f10) \
	x(key_f11) \
	x(key_f12) \
	x(key_down) \
	x(key_left) \
	x(key_right) \
	x(key_up) \
	x(key_escape) \
	x(key_return) \
	x(key_backspace) \
	x(key_tab) \
	x(key_delete) \
	x(key_home) \
	x(key_end) \
	x(key_page_up) \
	x(key_page_down) \
	x(key_insert) \
	x(key_shift) \
	x(key_control) \
	x(key_super) \
	x(key_alt) \
	x(key_space) \
	x(key_period) \
	x(key_0) \
	x(key_1) \
	x(key_2) \
	x(key_3) \
	x(key_4) \
	x(key_5) \
	x(key_6) \
	x(key_7) \
	x(key_8) \
	x(key_9) \

enum Key {
#define x(name) name,
	key_xmacro()
#undef x
	key_count
};

enum Mbtn {
	mbtn_left,
	mbtn_middle,
	mbtn_right,
	mbtn_count
};

enum Key_State {
	key_state_pressed       = 1 << 0,
	key_state_just_pressed  = 1 << 1,
	key_state_just_released = 1 << 2
};

struct App_Internal;

struct App {
	Arena* arena;
	float dt;
	int running, w, h;
	int mx, my;
	int scrollx, scrolly;
	unsigned char key_states[key_count];
	unsigned char mbtn_states[mbtn_count];
	uint64_t begin_t, end_t;
	App_Internal* internal;

	void init(const char* name, Arena* a);
	void destroy();

	void begin();
	void end();

	Key_State ks(Key k) const;
	Key_State ms(Mbtn k) const;
	bool kp(Key k) const;
	bool kjp(Key k) const;
	bool kjr(Key k) const;
	bool mp(Mbtn k) const;
	bool mjp(Mbtn k) const;
	bool mjr(Mbtn k) const;

	void get_vk_exts(const char** exts, int& count);

	virtual void on_init() = 0;
	virtual void on_update() = 0;
	virtual void on_destroy() = 0;
	virtual void on_resize() = 0;
	virtual void on_text_input(const char* buf) = 0;
};

#endif