#include <time.h>
#include "GUIApp.h"
#include "GUIPackage.h"
#ifdef G3D_WIN32
// For chdir
#	include <direct.h>
#endif

enum {
	JOINT_SELECTOR,
	X_SLIDER,
	Y_SLIDER,
	Z_SLIDER,

	SELECT_MOVE,
	ADD_MOVE_NAME,
	ADD_MOVE_BUTTON,
	DELETE_MOVE_BUTTON,
	PLAY_MOVE_BUTTON,

	SELECT_POSE,
	ADD_POSE_BUTTON,
	SET_POSE_BUTTON,
	DELETE_POSE_BUTTON,

	ATTACK_SELECTOR,
	TARGET_SELECTOR,

	NEW_PLAYER_BUTTON,
	SAVE_PLAYERS_BUTTON,
	RESET_BUTTON,
	PLAYER_SELECTOR
};

IMPLEMENT_APP(GUIApp)

BEGIN_EVENT_TABLE(GUIFrame, wxFrame)
    EVT_CLOSE( GUIFrame::OnClose )
    EVT_SIZE( GUIFrame::OnSize )
    EVT_MENU(FILEMENU_EXIT,  GUIFrame::OnFileMenuExit)

	EVT_CHOICE(JOINT_SELECTOR, GUIFrame::OnJointSelect)

	EVT_CHOICE(ATTACK_SELECTOR, GUIFrame::selectAttack)
	EVT_CHOICE(TARGET_SELECTOR, GUIFrame::selectTarget)

	EVT_COMMAND_SCROLL(X_SLIDER, GUIFrame::OnXSlider)
	EVT_COMMAND_SCROLL(Y_SLIDER, GUIFrame::OnYSlider)
	EVT_COMMAND_SCROLL(Z_SLIDER, GUIFrame::OnZSlider)

	EVT_LISTBOX(SELECT_MOVE, GUIFrame::selectMove)
	EVT_LISTBOX(SELECT_POSE, GUIFrame::selectPose)

	EVT_BUTTON(ADD_MOVE_BUTTON, GUIFrame::addNewMove)
	EVT_BUTTON(DELETE_MOVE_BUTTON, GUIFrame::deleteMove)
	EVT_BUTTON(PLAY_MOVE_BUTTON, GUIFrame::playMove)

	EVT_BUTTON(ADD_POSE_BUTTON, GUIFrame::addNewPose)
	EVT_BUTTON(DELETE_POSE_BUTTON, GUIFrame::deletePose)
	EVT_BUTTON(SET_POSE_BUTTON, GUIFrame::setPose)

	EVT_BUTTON(RESET_BUTTON, GUIFrame::OnReset)
	EVT_LISTBOX(PLAYER_SELECTOR, GUIFrame::OnSelectPlayer)
	EVT_BUTTON(SAVE_PLAYERS_BUTTON, GUIFrame::OnSavePlayers)
	EVT_BUTTON(NEW_PLAYER_BUTTON, GUIFrame::OnNewPlayer)

END_EVENT_TABLE()

bool GUIApp::OnInit(void) {
	srand(time(NULL));
    
	if (! fileExists("grid.png")) {
		// For running under visual studio
		_chdir("../../build");
	}

    alwaysAssertM(fileExists("grid.png"),
        "Project cannot find its data files.");

    // Create the main frame window
    frame = new GUIFrame(NULL,
        "KungFu Tamagatchi!",
        wxPoint(50, 50),
       // wxSize(820, 690));
	   wxSize(1020, 700)); // <- These values fit the G3D window exactly


    GAppSettings settings;
    
    settings.useNetwork = false;
    settings.window.stencilBits = 8;
    settings.window.alphaBits = 0;
    settings.window.fsaaSamples = 4;    

    // Show the frame
    frame->Show(true);

	GUIPackage *pack = new GUIPackage();
	pack->g3dPanel = frame->g3dPanel;
	pack->jointList = frame->jointList;
	
	pack->xaxis = frame->xaxis;
	pack->yaxis = frame->yaxis;
	pack->zaxis = frame->zaxis;

	pack->playerList = frame->playerList;
	pack->playerName = frame->playerName;

	pack->movesBox = frame->moveList;

	pack->posesBox = frame->poseList;

	app = new App(settings, frame->gwindow, pack); //frame->gwindow, frame->moveList, frame->poseList);

	dojo::app = app;

	frame->applet = app->applet;
	debugAssert(dojo::app->debugFont.notNull());
    dojo::app->run();

    return true;
}

GUIFrame::GUIFrame(wxFrame *frame, const wxString& title, const wxPoint& pos,
                 const wxSize& size, long style) :
         wxFrame(frame, -1, title, pos, size, style),
         gwindow(NULL),
         statusBar(NULL),
         timeSlider(NULL) {

	wxPanel* inputPanel = new wxPanel(this, 1, wxPoint(0, 0), wxSize(200, 600), wxSIMPLE_BORDER, wxString("inputPanel"));
	g3dPanel = new wxPanel(this, 2, wxPoint(0, 0), wxSize(800, 600), wxSIMPLE_BORDER, wxString("g3dPanel"));

	inputPanel->Show(true);
	g3dPanel->Show(true);

	wxBoxSizer* topLevelLayout = new wxBoxSizer( wxHORIZONTAL );
	topLevelLayout->Add(inputPanel);
	topLevelLayout->Add(g3dPanel);

	//Add all user input stuff to inputPanel here

		//First we show the joint selection/manipulation controls
		wxPanel* manipulationPanel = new wxPanel(inputPanel, -1, wxPoint(0, 0), wxSize(200, 190));

			//The label
			wxStaticBox* manipulationControls = new wxStaticBox( manipulationPanel, -1, wxString("Pull Point Manipulation"), wxPoint(0, 0), wxSize(200, 175));

			//Joint chooser pulldown menu
			wxString choices[] = {"Right Hand", "Right Radius", "Left Hand", "Left Radius", "Left Foot", "Right Foot", "Pelvis", "Left Femur", "Right Femur", "Left Tibia", "Right Tibia"};
			jointList = new wxChoice(manipulationPanel, JOINT_SELECTOR, wxPoint(5, 20), wxSize(190, 0), 11, choices);

			//X slider
			wxStaticText* xLabel = new wxStaticText(manipulationPanel, -1, wxString("X Axis:"), wxPoint(5, 50));
			xaxis = new wxSlider(manipulationPanel, X_SLIDER, 50, 0, 100, wxPoint(0, 65), wxSize(190, 25));

			//Y slider
			wxStaticText* yLabel = new wxStaticText(manipulationPanel, -1, wxString("Y Axis:"), wxPoint(5, 90));
			yaxis = new wxSlider(manipulationPanel, Y_SLIDER, 50, 0, 100, wxPoint(0, 105), wxSize(190, 25));

			//Z slider
			wxStaticText* zLabel = new wxStaticText(manipulationPanel, -1, wxString("Z Axis:"), wxPoint(5, 130));
			zaxis = new wxSlider(manipulationPanel, Z_SLIDER, 50, 0, 100, wxPoint(0, 145), wxSize(190, 25));


		//Next have the move editor
		wxPanel* movePanel = new wxPanel(inputPanel, -1, wxPoint(0, 190), wxSize(200, 190));

			//The label
			wxStaticBox* moveControls = new wxStaticBox( movePanel, -1, wxString("Move Editor"), wxPoint(0, 0), wxSize(200, 175));
	
			//List of moves
			moveList = new wxListBox( movePanel, SELECT_MOVE, wxPoint(5, 20), wxSize(190, 100), 0, NULL, wxLB_SINGLE | wxLB_NEEDED_SB);

			//Add new move text box
			moveName = new wxTextCtrl( movePanel, ADD_MOVE_NAME, wxString(""), wxPoint(5, 120), wxSize(145, 20));

			//Add new move button
			addMoveButton = new wxButton(movePanel, ADD_MOVE_BUTTON, wxString("Add"), wxPoint(150, 120), wxSize(45, 20));

			//Delete button
			deleteMoveButton = new wxButton(movePanel, DELETE_MOVE_BUTTON, wxString("Delete"), wxPoint(150, 140), wxSize(45, 20));
	
			//Play button
			playMoveButton = new wxButton(movePanel, PLAY_MOVE_BUTTON, wxString("Play"), wxPoint(5, 140), wxSize(145, 20));

		//Poses control
		wxPanel* posePanel = new wxPanel(inputPanel, -1, wxPoint(0, 380), wxSize(200, 140));

			//The label
			wxStaticBox* poseControls = new wxStaticBox( posePanel, -1, wxString("Pose Editor"), wxPoint(0, 0), wxSize(200, 135));
	
			//List of poses
			poseList = new wxListBox( posePanel, SELECT_POSE, wxPoint(5, 20), wxSize(130, 100), 0, NULL, wxLB_SINGLE | wxLB_NEEDED_SB);

			//Add button
			addPoseButton = new wxButton(posePanel, ADD_POSE_BUTTON, wxString("Add"), wxPoint(140, 30), wxSize(50, 20));

			//Set button
			setPoseButton = new wxButton(posePanel, SET_POSE_BUTTON, wxString("Set"), wxPoint(140, 60), wxSize(50,20));

			//Delete button
			deletePoseButton = new wxButton(posePanel, DELETE_POSE_BUTTON, wxString("Delete"), wxPoint(140, 90), wxSize(50,20));

			//Copy button

			//Paste button

		wxPanel* attackPanel = new wxPanel(inputPanel, -1, wxPoint(0, 520), wxSize(200, 130));

			wxStaticBox* attackSelection = new wxStaticBox( attackPanel, -1, wxString("Attack Selection"), wxPoint(0, 0), wxSize(200, 115));

			wxStaticText* attackLabel = new wxStaticText(attackPanel, -1, wxString("Attacking Limb:"), wxPoint(5, 20));
			limbList = new wxChoice(attackPanel, ATTACK_SELECTOR, wxPoint(5, 35), wxSize(190, 25), 11, choices);

			wxString ochoices[] = {"None", "Right Hand", "Right Radius", "Left Hand", "Left Radius", "Left Foot", "Right Foot", "Pelvis", "Left Femur", "Right Femur", "Left Tibia", "Right Tibia", "Head", "Chest"};

			wxStaticText* targetLabel = new wxStaticText(attackPanel, -1, wxString("Attack Target:"), wxPoint(5, 65));
			targetList = new wxChoice(attackPanel, TARGET_SELECTOR, wxPoint(5, 80), wxSize(190, 25), 14, ochoices);

		wxPanel* playerPanel = new wxPanel(g3dPanel, -1, wxPoint(0, 600), wxSize(800, 50));
			wxStaticBox* playerLabel = new wxStaticBox(playerPanel, -1, wxString("Player Selection"), wxPoint(0, 0), wxSize(800, 70));
			playerList = new wxListBox(playerPanel, PLAYER_SELECTOR, wxPoint(5, 22), wxSize(190, 25), NULL, wxLB_SINGLE | wxLB_NEEDED_SB);
			newPlayerButton = new wxButton(playerPanel, NEW_PLAYER_BUTTON, "New Player" , wxPoint(660, 22), wxSize(100, 25));
			savePlayersButton = new wxButton(playerPanel, SAVE_PLAYERS_BUTTON, "Save Players" , wxPoint(210, 22), wxSize(100, 25));
			resetButton = new wxButton(playerPanel, RESET_BUTTON, "Reset" , wxPoint(330, 22), wxSize(100, 25));
			playerName = new wxTextCtrl(playerPanel, -1, "", wxPoint(450, 22), wxSize(190, 25));

		gwindow = new wxGWindow(GWindowSettings(), g3dPanel, -1);

	topLevelLayout->Show(true);
	topLevelLayout->Layout();

	
}

void GUIFrame::selectAttack(wxCommandEvent &evt)
{
	applet->setAttackLimb(limbList->GetSelection());
}

void GUIFrame::selectTarget(wxCommandEvent &evt)
{
	std::string thisIsRetarded(targetList->GetString(targetList->GetSelection()).ToAscii());
	applet->setTarget(thisIsRetarded);
}

void GUIFrame::OnSize(wxSizeEvent& event) {

    // Layout code
    wxSize size = GetClientSize();

    if (gwindow) {
        double y0 = 0;
        double y1 = size.y;

        if (statusBar) {
            y1 = statusBar->GetPosition().y;
        }

        // gwindow->setDimensions(Rect2D::xyxy(0, y0, size.x, y1));
		/*
        if (app) {
            int h = y1 - y0 + 1;
            app->renderDevice->notifyResize(size.x, h);
            app->renderDevice->setViewport(Rect2D::xywh(0, 0, size.x, h));
        }
		*/
    }


    event.Skip();
}


void GUIFrame::OnFileMenuExit(wxCommandEvent& WXUNUSED(event)) {
    app->endProgram = true;
}


void GUIFrame::OnClose(wxCloseEvent& event) {
	delete dojo::app;
    dojo::app = NULL;
    Destroy();
}

void GUIFrame::OnJointSelect(wxCommandEvent& evt)
{
	applet->selectJoint(evt.GetSelection());
}

void GUIFrame::OnXSlider(wxScrollEvent& evt) {

	for(int i = 0; i < applet->strings.size(); i++)
	{
		if(applet->selected[i])
		{
			/*
			Vector3 newPosition(evt.GetPosition()/50.0, applet->strings[i]->frame().translation.y,
				applet->strings[i]->frame().translation.z);
			*/
			Vector3 newPosition(applet->relativeCenter[i].x + (evt.GetPosition()-50.0)/50.0, 
				applet->strings[i]->frame().translation.y,
				applet->strings[i]->frame().translation.z);

			CoordinateFrame absolute(newPosition);

			applet->strings[i]->setFrame(absolute);
		}
	}
}

void GUIFrame::OnYSlider(wxScrollEvent& evt) {

	for(int i = 0; i < applet->strings.size(); i++)
	{
		if(applet->selected[i])
		{
			//This is the OLD vector. When multiple strings are selected, they all clump together, so I'm going to 
			//implement a relative vector
			
			/*
			Vector3 newPosition(applet->strings[i]->frame().translation.x, (evt.GetPosition()/50.0) - 1.5,
				applet->strings[i]->frame().translation.z);
				*/

			Vector3 newPosition(applet->strings[i]->frame().translation.x, 
				applet->relativeCenter[i].y + (evt.GetPosition()-50.0)/50.0,
				applet->strings[i]->frame().translation.z);
			
		
			CoordinateFrame absolute(newPosition);

			applet->strings[i]->setFrame(absolute);
		}
	}
}

void GUIFrame::OnZSlider(wxScrollEvent& evt) {

	for(int i = 0; i < applet->strings.size(); i++)
	{
		if(applet->selected[i])
		{
			/*
			Vector3 newPosition(applet->strings[i]->frame().translation.x, applet->strings[i]->frame().translation.y,
				(evt.GetPosition()/50.0) + 4.0);
			*/

			Vector3 newPosition(applet->strings[i]->frame().translation.x, 
				applet->strings[i]->frame().translation.y,
				applet->relativeCenter[i].z + (evt.GetPosition()-50.0)/50.0);

			CoordinateFrame absolute(newPosition);

			applet->strings[i]->setFrame(absolute);
		}
	}
}

void GUIFrame::selectMove(wxCommandEvent& evt)
{
	int selectedItem = evt.GetSelection();
	
	applet->setMove(selectedItem);
}


void GUIFrame::addItem(char* item)
{


}

void GUIFrame::addNewMove(wxCommandEvent& evt)
{
	//Log::common()->printf("Add item: %s\n", moveName->GetValue().c_str());
	char tempString[256];
	sprintf(tempString, "%s", moveName->GetValue().c_str());
	applet->addMove(tempString);

	moveName->Clear();
}

void GUIFrame::deleteMove(wxCommandEvent& evt)
{
	int selection = moveList->GetSelection();
	
	if(selection >= 0)
	{
		moveList->Delete(selection);
		applet->deleteMove(selection);
	}
}

void GUIFrame::selectPose(wxCommandEvent& evt)
{
	int selectedItem = evt.GetSelection();
	
	applet->selectPose(selectedItem);
}

void GUIFrame::playMove(wxCommandEvent& evt)
{
	applet->playMove();
}

void GUIFrame::setPose(wxCommandEvent& evt)
{
	int selectedItem = evt.GetSelection();
	
	if(selectedItem >= 0)
	{
		applet->setPose();
	}
}


void GUIFrame::addNewPose(wxCommandEvent& evt)
{
	applet->addPose();
}

void GUIFrame::deletePose(wxCommandEvent& evt)
{
	int selection = poseList->GetSelection();
	poseList->Delete(selection);

	poseList->SetSelection(0, false);

	applet->deletePose();
}

void GUIFrame::OnReset(wxCommandEvent& evt)
{
	applet->reload();
}

void GUIFrame::OnSelectPlayer(wxCommandEvent &evt)
{
	applet->selectPlayer(evt.GetSelection());
}

void GUIFrame::OnNewPlayer(wxCommandEvent &evt)
{
	applet->newPlayer();
}

void GUIFrame::OnSavePlayers(wxCommandEvent &evt)
{
	applet->savePlayers();
}