#pragma comment (lib, "fltk.lib")
#pragma comment (lib, "fltkgl.lib")
#pragma comment (lib, "glu32.lib")
#pragma comment (lib, "opengl32.lib")

#define _CRT_SECURE_NO_WARNINGS

#include <FL/gl.H>
#include <FL/Fl.H>
#include <FL/x.H>
#include <FL/Fl_Gl_Window.H>

#include <iostream>
#include <fstream>
#include <string>
#include <direct.h>
#include <time.h>

#include "../core/ge_iface.h"
#include "../core/ge_fl_opengl.h"
#include "../core/ie_iface.h"
#include "../core/ie_fltk_1_3.h"
#include "../core/se_iface.h"
#include "../core/se_openal.h"
#include "../core/log.h"
#include "../core/threads.h"
#include "../core/time_util.h"

#include "../xrpg/xrpg_iface.h"

#include "ge_adapter.h"
#include "ie_adapter.h"

#define DELAY (1./60.)

Fl_Thread _thread;
ge::ZGraphicEngineOpenGL * GE=0;
ge::ZGraphicEngineAdapter * GE_a=0;
ie::InputEngineFLTK13 * IE=0;
ie::ZInputEngineAdapter * IE_a = 0;
se::ZSoundEngineOpenAL * SE=0;
bool fullscreen=false;

//snake::ZSnakeGame * game = 0;
//dungeon::ZDungeonGame * game = 0;
xrpg::ZXRPG * game = 0;
int scr_x, scr_y;

void exit_cb(Fl_Widget * w, void * v)
{
	if (GE) delete GE;
	if (IE) delete IE;
	if (SE) delete SE;
	std::cout << "goodbye\n";

	exit(0);
}

void load_gfx()
{
	GE->load_texture(xrpg::TEXTURE_SYSTEM,		"../gfx/system.bmp",	"Null");
	GE->load_texture(xrpg::TEXTURE_ICONS,		"../gfx/icon.bmp",		"Auto");

	GE->load_texture_from_png( xrpg::TEXTURE_CHARS,		"../gfx/char.png" );

	GE->load_texture_from_png( xrpg::TEXTURE_TITLE,		"../gfx/title.png" );

	GE->load_texture_from_png( xrpg::TEXTURE_GRASS,		"../gfx/grass.png" );
	GE->load_texture_from_png( xrpg::TEXTURE_FOREST,	"../gfx/forest.png" );
	GE->load_texture_from_png( xrpg::TEXTURE_SNOW,		"../gfx/snow.png" );
	GE->load_texture_from_png( xrpg::TEXTURE_SWAMP,		"../gfx/swamp.png" );
	GE->load_texture_from_png( xrpg::TEXTURE_DESERT,	"../gfx/desert.png" );
	GE->load_texture_from_png( xrpg::TEXTURE_WASTELAND,	"../gfx/wasteland.png" );
	GE->load_texture_from_png( xrpg::TEXTURE_GALAXY,	"../gfx/galaxy.png" );

	/*GE->load_texture(dungeon::TEXTURE_TILES,		"../gfx/tiles.bmp",		"Auto");
	GE->load_texture(dungeon::TEXTURE_HERO,			"../gfx/hero.bmp",		"Auto");
	GE->load_texture(dungeon::TEXTURE_ITEMS,		"../gfx/items.bmp",		"Auto");
	GE->load_texture(dungeon::TEXTURE_FLOOD,		"../gfx/flood.bmp",		"Auto");
	GE->load_texture(dungeon::TEXTURE_SHOP,			"../gfx/shop.bmp",		"Auto");
	GE->load_texture(dungeon::TEXTURE_MONSTERS,		"../gfx/monsters.bmp",	"Auto");*/
}

void load_sfx()
{
	/*SE->load_sound( dungeon::SOUND_BOOM,		"../sfx/boom.wav"		);
	SE->load_sound( dungeon::SOUND_HIT,			"../sfx/hit.wav"		);
	SE->load_sound( dungeon::SOUND_GOLD,		"../sfx/gold.wav"		);
	SE->load_sound( dungeon::SOUND_POTION,		"../sfx/potion.wav"		);
	SE->load_sound( dungeon::SOUND_PUT,			"../sfx/put.wav"		);
	SE->load_sound( dungeon::SOUND_BOMB,		"../sfx/bomb.wav"		);
	SE->load_sound( dungeon::SOUND_FLOOD,		"../sfx/flood.wav"		);
	SE->load_sound( dungeon::SOUND_COMPLETE,	"../sfx/complete.wav"	);
	SE->load_sound( dungeon::SOUND_DEAD,		"../sfx/dead.wav"		);
	SE->load_sound( dungeon::SOUND_LEVELUP,		"../sfx/levelup.wav"	);
	SE->load_sound( dungeon::SOUND_GAMEOVER,	"../sfx/gameover.wav"	);
	SE->load_sound( dungeon::SOUND_HEAL,		"../sfx/heal.wav"		);
	SE->load_sound( dungeon::SOUND_EQUIP,		"../sfx/equip.wav"		);*/
}

void reset_mode(Fl_Window * wnd)
{
	if (GE) delete GE;
	if (GE_a) delete GE_a;
	
	wnd->resize( (scr_x-320*2)/2, (scr_y-240*2)/2, 320*2, 240*2 );
	GE = new ge::ZGraphicEngineOpenGL( wnd->w(), wnd->h() );

	GE_a = new ge::ZGraphicEngineAdapter( GE, 0, 0, 320*2, 240*2 );
	IE_a->set_state( 0, 0, 320*2, 240*2, false );
	GE->load_texture(xrpg::TEXTURE_FONT,	"../gfx/font.bmp",		"Auto");

	GE_a->begin_scene();
	GE_a->clear_scene();
	GE_a->write(40,220,"Loading...", 0.5f, 0.5f, 0.5f);
	GE_a->render_scene();

	load_gfx();
}

class Fl_GameWindow : public Fl_Gl_Window
{
	int _launch;
	fps_counter _fps_cntr;

	void init_ie()
	{
		HWND main_hWnd = fl_xid(this);
		IE = new ie::InputEngineFLTK13();
		IE_a = new ie::ZInputEngineAdapter(IE);
	}

	void init_se()
	{
		HWND main_hWnd = fl_xid(this);
		SE = new se::ZSoundEngineOpenAL();

		load_sfx();

		//SE->load_music( 1, "../sfx/music.mp3" );
	}

	void init_game()
	{
		srand( (unsigned int)time(0) );
		game = new xrpg::ZXRPG();
	}

	void draw()
	{
		if (_launch==0)
		{
			init_ie();
			reset_mode( this );
			_launch = 1;
		}
		else if (_launch==1)
		{
			init_se();
			init_game();
			valid(1);
			_launch = 2;
		}
		else
		{
			if (!valid()) {
				reset_mode(this);
				valid(1);
			}

			//_fps_cntr.tick_frame();
			GE_a->begin_scene();
			GE_a->clear_scene();
			if (game)
				game->draw_frame( IE_a, GE_a );
			//GE_a->write( 160.f, 10.f, ("fps="+time_util::get_really_fps_s()).c_str(), 0.f, 1.f, 0.f, 0.8f );
			//GE_a->write( 200.f, 0.f, ("draw_fps="+_fps_cntr.get_really_fps_s()).c_str(), 0.f, 1.f, 0.f, 0.3f );
			GE_a->render_scene();
		}
	}

	int handle( int e )
	{
		if (IE) IE->outer_handle( this, e );
		return Fl_Gl_Window::handle( e );
	}

	static void render_cb(void * wnd)
	{
		Fl_GameWindow * w = (Fl_GameWindow*)wnd;
		w->do_frame();
		w->redraw();
		//Fl::repeat_timeout(DELAY, render_cb, wnd);
	}
public:
	Fl_GameWindow( int x, int y, int w, int h, const char * title=0 ) : Fl_Gl_Window(x,y,w,h,title)
	{
		_launch = 0;
		//Fl::add_timeout(DELAY, render_cb, (void*)this);
	}

	void do_frame()
	{
		if (_launch == 2)
		{
			time_util::tick_frame();
			//SE->check_time();
			//if (SE->get_cur_music() == -1)
			//	SE->run_music( 1, 1.0f, true );
			IE_a->read_states();

			if (!game->do_frame( IE_a, SE ))
				exit_cb(0,0);
		}
	}
};

void * render_scene(void * p)
{
	Fl_GameWindow * wnd = (Fl_GameWindow *)p;

	time_util::set_fps(60);

	while(1)
	{
		time_util::wait_next_frame();

		Fl::lock();

		wnd->do_frame();

		wnd->redraw();
		Fl::unlock();
		Fl::awake(wnd);
	}
}

int main(int argc, char **argv)
{
	std::cout << "Tiny RPG\n";
	std::cout << "Ripatti software (c) 2014\n";
	std::cout << "specially for IGDC-104\n";

	//Fl::scheme("plastic");

	scr_x = GetSystemMetrics(SM_CXSCREEN);
	scr_y = GetSystemMetrics(SM_CYSCREEN);

	//if (fl_ask("Fullscreen?")) fullscreen = true;

	Fl_GameWindow * window = new Fl_GameWindow((scr_x-640)/2,(scr_y-480)/2,640,480,"IGDC-104 TINYRPG!");

	window->box(FL_NO_BOX);
	window->end();
	window->show(argc, argv);
	window->callback(exit_cb, 0);
	//window->cursor(FL_CURSOR_NONE);

	Fl::lock();

	fl_create_thread(_thread, render_scene, window);

	Fl::run();

	exit_cb(0,0);

	return 0;
}