#pragma comment (lib, "fltk.lib")

#define _CRT_SECURE_NO_WARNINGS

#include <FL/Fl.H>
#include <FL/Fl_Double_Window.H>
#include <FL/Fl_Button.H>
#include <FL/Fl_Radio_Button.H>
#include <FL/Fl_Value_Slider.H>
#include <FL/Fl_Tabs.H>
#include <FL/Fl_Group.H>
#include <FL/fl_draw.H>

#include <iostream>
#include <fstream>
#include <string>
#include <locale.h>
#include <cmath>

#include "iface.h"

char * utf8(const char * src)
{
	char * tmp = new char[256]; // память утекает, но это не важно
	fl_utf8from_mb(tmp,-1,src,-1);
	return tmp;
}

std::string itos(int i)
{
	char tmp[32];
	sprintf(tmp, "%d", i);
	return std::string(tmp);
}



class ZWindow : public Fl_Double_Window
{
	voxel::ZGame * game;
	voxel::ZGen * gen;

	Fl_Button * gen1, * gen2, * gen3, * start, * stop;
	Fl_Group * move;
	Fl_Button * do_move;
	Fl_Value_Slider * sliders[5];
	Fl_Radio_Button * weapons[6];

	bool in_game;
	int alpha, beta;
	int mx, my;
	bool drag_mode;

	void draw()
	{
		fl_draw_image((const uchar*)game->get_pixbuf(), 0, 0, XSIZE, YSIZE, 3, XSIZE*3);
		fl_font(FL_HELVETICA_BOLD, 20);
		
		static char str[200];
		fl_color(game->pp[0].r, game->pp[0].g, game->pp[0].b);
		sprintf_s(str, "You: HP=%d/100 money=%d$", game->pp[0].hp, game->pp[0].money);
		fl_draw(str, XSIZE-300, 20);
		fl_color(game->pp[1].r, game->pp[1].g, game->pp[1].b);
		sprintf_s(str, "Enemy: HP=%d/100 money=%d$", game->pp[1].hp, game->pp[1].money);
		fl_draw(str, XSIZE-320, 40);

		if (in_game)
		{
			fl_color( 255, 255, 255 );
			if (game->pp[0].hp == 0 && game->pp[1].hp == 0)
				fl_draw( "Double kill!", 100, 20 );
			else if (game->pp[0].hp == 0)
				fl_draw( "You lose!", 100, 20 );
			else if (game->pp[1].hp == 0)
				fl_draw( "You won!", 100, 20 );
			else if (game->locked)
			{
				if (game->cur_pl == 0)
					fl_draw( "Processing your move", 80, 20 );
				else
					fl_draw( "Processing enemy move", 80, 20 );
			}
			else fl_draw( "Your move!", 100, 20 );
		}
		
		Fl_Double_Window::draw_children();
	}

	int handle(int e)
	{
		if (!game->locked)
		{
			int tmp = Fl_Double_Window::handle(e);
			if (tmp) return tmp;
		}

		if (e == FL_PUSH)
		{
			if (Fl::event_y() < YSIZE)
			{
				mx = Fl::event_x();
				my = Fl::event_y();
				drag_mode = true;
				return 1;
			}
		}
		else if (e == FL_DRAG)
		{
			if (drag_mode)
			{
				int cur_x = Fl::event_x();
				int cur_y = Fl::event_y();
				alpha -= cur_x-mx;
				beta += cur_y-my;

				while (alpha < 0) alpha += 360*2;
				while (alpha >= 360*2) alpha -= 360*2;
				beta = min( max( beta, 20 ), 120 );

				mx = cur_x;
				my = cur_y;
				return 1;
			}
		}
		else if (e == FL_RELEASE)
		{
			if (drag_mode)
			{
				drag_mode = false;
				return 1;
			}
		}
		return 0;
	}

	static void render_cb(void * wnd)
	{
		ZWindow * w = (ZWindow*)wnd;
		w->game->do_anim();
		w->render();
		Fl::repeat_timeout(DELAY, render_cb, wnd);
	}

	static void gen_cb( Fl_Widget * btn, void * p )
	{
		ZWindow * w = (ZWindow*)(btn->window());
		w->game->gen( w->gen, (int)p );
	}

	static void start_cb( Fl_Widget * btn, void * p )
	{
		ZWindow * w = (ZWindow*)(btn->window());
		w->gen1->deactivate();
		w->gen2->deactivate();
		w->gen3->deactivate();
		w->start->deactivate();
		w->stop->activate();
		w->move->activate();

		w->in_game = true;

		w->reset_move();
	}

	void reset_move()
	{
		for (int a=0; a<5; a++)
			sliders[a]->deactivate();
		do_move->deactivate();

		for (int a=0; a<6; a++)
			weapons[a]->value( 0 );
	}

	static void stop_cb( Fl_Widget * btn, void * p )
	{
		ZWindow * w = (ZWindow*)(btn->window());
		w->gen1->activate();
		w->gen2->activate();
		w->gen3->activate();
		w->start->activate();
		w->stop->deactivate();
		w->move->deactivate();

		w->reset_move();

		w->in_game = false;

		w->game->gen( w->gen, 2 );
		w->game->pp[0] = voxel::ZPlayer( FIELD_N/4, FIELD_N/4, 255, 0, 0 );
		w->game->pp[1] = voxel::ZPlayer( FIELD_N*3/4, FIELD_N*3/4, 0, 0, 255 );
	}

	static void weapon_cb( Fl_Widget * btn, void * p )
	{
		ZWindow * w = (ZWindow*)(btn->window());
		int tp = (int)p;
		//std::cout << tp << "\n";

		if (tp==1 || tp==2 || tp==3 || tp==4)
		{
			w->sliders[0]->activate();
			w->sliders[1]->activate();
		}
		else
		{
			w->sliders[0]->deactivate();
			w->sliders[1]->deactivate();
		}

		if (tp==1 || tp==2 || tp==3)
			w->sliders[2]->activate();
		else w->sliders[2]->deactivate();

		if (tp==5)
		{
			w->sliders[3]->activate();
			w->sliders[4]->activate();
		}
		else
		{
			w->sliders[3]->deactivate();
			w->sliders[4]->deactivate();
		}

		static int cost[] = { 0, 50, 80, 120, 250, 500 };
		if (w->game->pp[0].money >= cost[tp])
			w->do_move->activate();
		else w->do_move->deactivate();

		w->game->pp[0].weapon = tp;
		slider_cb( btn, 0 );
	}

	static void slider_cb( Fl_Widget * btn, void * p )
	{
		ZWindow * w = (ZWindow*)(btn->window());

		w->game->pp[0].alpha = (int)w->sliders[0]->value();
		w->game->pp[0].beta = (int)w->sliders[1]->value();
		w->game->pp[0].power = (int)w->sliders[2]->value();
		w->game->pp[0].X = (int)w->sliders[3]->value();
		w->game->pp[0].Y = (int)w->sliders[4]->value();
	}

	static void do_move_cb( Fl_Widget * btn, void * p )
	{
		ZWindow * w = (ZWindow*)(btn->window());

		w->game->do_move( 0 );

		w->reset_move();
	}

public:
	ZWindow(int w, int h, const char *name=0) : Fl_Double_Window(w,h,name)
	{
		Fl_Tabs * tab = new Fl_Tabs(0,YSIZE-20,XSIZE,PANEL_H+20);
		{
			Fl_Group * g = new Fl_Group(0,YSIZE,YSIZE,PANEL_H,utf8("Меню"));
			gen1 = new Fl_Button(10,YSIZE+10,100,25,"Gen1");
			gen1->callback( &ZWindow::gen_cb, (void*)1 );
			gen2 = new Fl_Button(10,YSIZE+40,100,25,"Gen2");
			gen2->callback( &ZWindow::gen_cb, (void*)2 );
			gen3 = new Fl_Button(10,YSIZE+70,100,25,"Gen3");
			gen3->callback( &ZWindow::gen_cb, (void*)3 );
			start = new Fl_Button(180,YSIZE+10,200,25,utf8("Начать игру"));
			start->callback( &ZWindow::start_cb, 0 );
			stop = new Fl_Button(180,YSIZE+70,200,25,utf8("Закончить игру"));
			stop->deactivate();
			stop->callback( &ZWindow::stop_cb, 0 );
			g->end();
		}
		{
			move = new Fl_Group(0,YSIZE,XSIZE,PANEL_H,utf8("Ход"));
			move->deactivate();

			weapons[0] = new Fl_Radio_Button(10,YSIZE+10,100,60,utf8("Обычный\nснаряд\n50$"));
			weapons[0]->callback( &ZWindow::weapon_cb, (void *)1 );
			weapons[1] = new Fl_Radio_Button(120,YSIZE+10,100,60,utf8("Разрывной\nснаряд\n80$"));
			weapons[1]->callback( &ZWindow::weapon_cb, (void *)2 );
			weapons[2] = new Fl_Radio_Button(230,YSIZE+10,100,60,utf8("Очередь\n\n120$"));
			weapons[2]->callback( &ZWindow::weapon_cb, (void *)3 );
			weapons[3] = new Fl_Radio_Button(10,YSIZE+80,100,60,utf8("Лазер\n\n250$"));
			weapons[3]->callback( &ZWindow::weapon_cb, (void *)4 );
			weapons[4] = new Fl_Radio_Button(120,YSIZE+80,100,60,utf8("Удар\nс воздуха\n500$"));
			weapons[4]->callback( &ZWindow::weapon_cb, (void *)5 );
			weapons[5] = new Fl_Radio_Button(230,YSIZE+80,100,60,utf8("Пропустить\nход"));
			weapons[5]->callback( &ZWindow::weapon_cb, (void *)0 );

			sliders[0] = new Fl_Value_Slider(380,YSIZE+15,250,20,utf8("Альфа"));
			sliders[0]->range( 0., 359. );
			sliders[0]->value( 0. );
			sliders[1] = new Fl_Value_Slider(380,YSIZE+40,120,20,utf8("Бета"));
			sliders[1]->range( -80., 80. );
			sliders[1]->value( 0. );
			sliders[2] = new Fl_Value_Slider(380,YSIZE+65,120,20,utf8("Сила"));
			sliders[2]->range( 10., 100. );
			sliders[2]->value( 50. );
			sliders[3] = new Fl_Value_Slider(380,YSIZE+90,120,20,"X");
			sliders[3]->range( 0., (double)(FIELD_N-1) );
			sliders[3]->value( (double)(FIELD_N/2) );
			sliders[4] = new Fl_Value_Slider(380,YSIZE+115,120,20,"Y");
			sliders[4]->range( 0., (double)(FIELD_N-1) );
			sliders[4]->value( (double)(FIELD_N/2) );

			for (int a=0; a<5; a++)
			{
				sliders[a]->type(1);
				sliders[a]->align( FL_ALIGN_LEFT );
				sliders[a]->step( 1. );
				sliders[a]->deactivate();
				sliders[a]->callback( &ZWindow::slider_cb, 0 );
			}

			do_move = new Fl_Button(510,YSIZE+50,120,50,utf8("Подтверждение\nхода"));
			do_move->callback( &ZWindow::do_move_cb, 0 );
			do_move->deactivate();

			move->end();
		}
		tab->end();

		in_game = false;
		alpha = 0;
		beta = 80;
		drag_mode = false;

		game = new voxel::ZGame();
		gen = new voxel::ZGen();
		game->gen( gen, 3 );
		render();
		Fl::add_timeout(DELAY, render_cb, (void*)this);
	}

	void render()
	{
		game->set_cam( alpha/2, beta/2 );
		game->render();
		redraw();
	}
};

int main(int argc, char **argv)
{
	setlocale(LC_ALL, "rus");
	setlocale(LC_NUMERIC, "eng");
	system("color 0A");
	system("title Console");

	std::cout << "Scorched Voxel\n";
	std::cout << "Ripatti software (c) 2012\n";
	std::cout << "Специально для igdc.ru\n";

	Fl::scheme("gtk+");
	Fl::visual(FL_RGB);

	ZWindow * window = new ZWindow(XSIZE,YSIZE+PANEL_H,"Scorched Voxel");
	window->end();
	window->show(argc, argv);
	window->position(20, 20);

	return Fl::run();
}