/*
	This file is part of Hikari, a library that allows developers
	to use Flash in their Ogre3D applications.

	Copyright (C) 2008 Adam J. Simmons

	This library is free software; you can redistribute it and/or
	modify it under the terms of the GNU Lesser General Public
	License as published by the Free Software Foundation; either
	version 2.1 of the License, or (at your option) any later version.

	This library is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
	Lesser General Public License for more details.

	You should have received a copy of the GNU Lesser General Public
	License along with this library; if not, write to the Free Software
	Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
*/
/*********************************************************************************************
   ___ ___ .__ __                 .__ 
 /   |   \|__|  | _______ _______|__|
/    ~    \  |  |/ /\__  \\_  __ \  |
\    Y    /  |    <  / __ \|  | \/  |
 \___|_  /|__|__|_ \(____  /__|  |__|  v0.4
       \/         \/     \/          


* Zed Games PC Development Team - Jaime Crespillo Vilchez (jcrespillo@zed.com)
* Build: 0.1 - Date: 13/10/2008
* Undocked version of Hikari Lib
* Brief: main demo Ogre application using undocked FlashControls 
**********************************************************************************************/
#include "HikariOgreDemo.h"
#include "FlashControl.h"
#include "Hikari.h"
#include <conio.h>

using namespace Ogre;
using namespace Hikari;

HikariOgreDemo::HikariOgreDemo() : root(0), shouldQuit(false), renderWin(0), viewport(0), sceneMgr(0), hikariMgr(0), inputMgr(0), fps(0)
{
	lastTime = timer.getMilliseconds();

	root = new Root();
	shouldQuit = !root->showConfigDialog();
	if(shouldQuit) return;

	renderWin = root->initialise(true, "HikariOgreDemo");
	sceneMgr = root->createSceneManager("DefaultSceneManager");
	WindowEventUtilities::addWindowEventListener(renderWin, this);

	createScene();

	setupHikari();

	loadInputSystem();
}

HikariOgreDemo::~HikariOgreDemo()
{

	WindowEventUtilities::removeWindowEventListener(renderWin, this);

	if(inputMgr)
		delete inputMgr;
	
	delete fps;
	fps = 0;
	controls.clear();
	paths.clear();
	names.clear();
	
	if(hikariMgr){
		delete hikariMgr;
	}

	root = 0;
	hikariMgr = 0;
	inputMgr = 0;
}

void HikariOgreDemo::createScene()
{
	sceneMgr->setAmbientLight(ColourValue::White);
	sceneMgr->setShadowTechnique(SHADOWTYPE_TEXTURE_ADDITIVE);

	Camera* camera = sceneMgr->createCamera("MainCam");
	viewport = renderWin->addViewport(camera);
	viewport->setBackgroundColour(ColourValue(0.0, 0.0, 0.0));
	camera->setAspectRatio((float)viewport->getActualWidth() / (float)viewport->getActualHeight());
}

void HikariOgreDemo::setupHikari()
{
	//Init Hikari
	hikariMgr = new HikariManager();
	hikariMgr->setPath("..\\media");
	//Config FlashControls creation
	int x=3;
	int y=4;
	int counter=0;

	int W=180;
	int H=180;
	int offsetW=W+15;
	int offsetH=W+15;
	int initX =100;
	int initY=100;

	names[0] = "control0";
	names[1] = "control1";
	names[2] = "control2";
	names[3] = "control3";
	names[4] = "control4";
	names[5] = "control5";
	names[6] = "control6";
	names[7] = "control7";
	names[8] = "control8";
	names[9] = "control9";
	names[10] = "control10";
	names[11] = "control11";
	names[12] = "control12";
	names[13] = "control13";
	names[14] = "control14";

	paths[0] = "prueba2.swf";
	paths[1] = "prueba2.swf";
	paths[2] = "prueba2.swf";
	paths[3] = "prueba2.swf";
	paths[4] = "prueba2.swf";
	paths[5] = "prueba2.swf";
	paths[6] = "prueba2.swf";
	paths[7] = "prueba2.swf";
	paths[8] = "prueba2.swf";
	paths[9] = "prueba2.swf";
	paths[10] = "prueba2.swf";
	paths[11] = "prueba2.swf";
	paths[12] = "prueba2.swf";
	paths[13] = "prueba2.swf";

	//set a custom row/colum structure of (x*y) FlashControls for testing purpouses
	for(int i=0;i<x;i++){
		for(int j=0;j<y;j++){
			std::string s = "c"+counter;
			controls[counter] = new FlashControl(names[counter], viewport, W, H, Hikari::Position(initX+offsetW*j,initY+offsetH*i),counter+1);
			controls[counter]->load(paths[counter], hikariMgr);
			controls[counter]->setTransparent(true,true);	
			hikariMgr->setFlashControl(controls[counter]);
			counter++;
		}
	}

	//FPS
	fps = new FlashControl("FPS", viewport, 130, 91, Position(TopLeft),0);
	fps->load("fps.swf", hikariMgr);
	fps->setTransparent(true);
	fps->setDraggable(false);
	//set our FlashControl to Hikari
	hikariMgr->setFlashControl(fps);
}

void HikariOgreDemo::update()
{
	hikariMgr->update();
	root->renderOneFrame();

	//Ogre::WindowEventUtilities::messagePump();///////////////////////////////// NO LONGER NEEDED -> delegate in HikariManager::update()
	
	inputMgr->capture();

	//FPS calc
	const RenderTarget::FrameStats& stats = renderWin->getStatistics();
	static int oldFPS = 0;

	if (oldFPS != (int)stats.lastFPS)
	{
      fps->callFunction(L"setFPS", Args((int)stats.lastFPS));
      oldFPS = (int)stats.lastFPS;
	} 
}

Hikari::FlashValue HikariOgreDemo::onOpacityChange(FlashControl* caller, const Hikari::Arguments& args)
{
	Real opacityPercent = args.at(0).getNumber();

	caller->setOpacity(opacityPercent / 100);

	return FLASH_VOID;
}

Hikari::FlashValue HikariOgreDemo::onColorChange(FlashControl* caller, const Hikari::Arguments& args)
{
	colorValueBase color = args.at(0).getNumberAsColor();
	const ColourValue* colorOgre = new ColourValue(color.r,color.g, color.b, color.a);
	viewport->setBackgroundColour(*colorOgre);

	return FLASH_VOID;
}

Hikari::FlashValue HikariOgreDemo::onExitClick(FlashControl* caller, const Hikari::Arguments& args)
{
	hikariMgr->destroyAllControls();
	shouldQuit = true;

	return FLASH_VOID;
}

void HikariOgreDemo::loadInputSystem()
{
	inputMgr = InputManager::getSingletonPtr();
    inputMgr->initialise(renderWin);
    inputMgr->addMouseListener(this, "MouseListener");
	inputMgr->addKeyListener(this, "KeyListener");
}

bool HikariOgreDemo::mouseMoved(const OIS::MouseEvent &arg)
{
	return hikariMgr->injectMouseMove(arg.state.X.abs, arg.state.Y.abs) || hikariMgr->injectMouseWheel(arg.state.Z.rel);
}

bool HikariOgreDemo::mousePressed(const OIS::MouseEvent &arg, OIS::MouseButtonID id)
{
	return hikariMgr->injectMouseDown(id);
}

bool HikariOgreDemo::mouseReleased(const OIS::MouseEvent &arg, OIS::MouseButtonID id)
{
	return hikariMgr->injectMouseUp(id);
}

bool HikariOgreDemo::keyPressed( const OIS::KeyEvent &arg )
{
	if(hikariMgr->isAnyFocused())
		return true;

	return true;
}

bool HikariOgreDemo::keyReleased( const OIS::KeyEvent &arg )
{
	switch(arg.key)
	{
	case OIS::KC_ESCAPE:
		shouldQuit = true;
		break;
	case OIS::KC_F1:
	{
		const RenderTarget::FrameStats& stats = renderWin->getStatistics();
		Ogre::LogManager::getSingleton().logMessage("Current FPS: " + StringConverter::toString(stats.lastFPS));
		Ogre::LogManager::getSingleton().logMessage("Triangle Count: " + StringConverter::toString(stats.triangleCount));
		Ogre::LogManager::getSingleton().logMessage("Batch Count: " + StringConverter::toString(stats.batchCount));
		break;
	}
	case OIS::KC_F2:
		sceneMgr->getRootSceneNode()->flipVisibility(true);
		break;
	}

	return true;
}

void HikariOgreDemo::windowMoved(RenderWindow* rw) {}

void HikariOgreDemo::windowResized(RenderWindow* rw) 
{
	inputMgr->setWindowExtents(rw->getWidth(), rw->getHeight());
}

void HikariOgreDemo::windowClosed(RenderWindow* rw) 
{
	shouldQuit = true;
}

void HikariOgreDemo::windowFocusChange(RenderWindow* rw) {}
