#include "PFrameListener.h"

PFrameListener::PFrameListener( RenderWindow * p_Window, Camera * p_Camera, SceneManager * p_SceneMgr ) {
	m_Window = p_Window;
	m_Camera = p_Camera;
	m_Camera->setFOVy( Degree( 80 ) );
	m_SceneMgr = p_SceneMgr;
	continueRendering = true;

	LogManager::getSingletonPtr()->logMessage( "***  OIS: Initializing... ***" );
	OIS::ParamList pl;
	size_t windowHnd = 0;
	std::ostringstream windowHndStr;

	m_Window->getCustomAttribute( "WINDOW", &windowHnd );
	windowHndStr << windowHnd;
	pl.insert( std::make_pair( std::string( "WINDOW"), windowHndStr.str() ) );

	m_InputManager = OIS::InputManager::createInputSystem( pl );

	//Crea i dispositivi
	m_Keyboard = static_cast<OIS::Keyboard*>( m_InputManager->createInputObject( OIS::OISKeyboard, false ) );
	m_Mouse = static_cast<OIS::Mouse*>( m_InputManager->createInputObject( OIS::OISMouse, false ) );

	LogManager::getSingletonPtr()->logMessage( "*** OIS: Working ***" );

	//Configura la dimensione iniziale di clipping del mouse
	windowResized( m_Window );

	//Registra la finestra come un WindowListener
	WindowEventUtilities::addWindowEventListener( m_Window, this );

	// fai partire prima l'animazione
	m_GiocoInizio = true;
	m_OverlayToggle = 0.0;
	
	m_ScenaFinale = false;
	m_Vittoria = false;

	// il timer parte
	m_Timer = new Timer();

	// GUIstate indica che tipo di overlay devo visualizzare e SE devo
	m_GUIstate = GUI_RIEPILOGO;
	m_GUIToggle = 0.0;
	m_OverGUI = OverlayManager::getSingleton().getByName("Asteroid_Cargo_GUI"); 
	// inizia dal riepilogo
}

PFrameListener::~PFrameListener() {
	//Elimina la finestra come WindowListener
	WindowEventUtilities::removeWindowEventListener( m_Window, this );
	windowClosed( m_Window );
}

void PFrameListener::windowResized( RenderWindow* rw ) {
	unsigned int width, height, depth;
	int left, top;
	rw->getMetrics( width, height, depth, left, top );

	const OIS::MouseState &ms = m_Mouse->getMouseState();
	ms.width = width;
	ms.height = height;
}

void PFrameListener::windowClosed( RenderWindow* rw ) {
	m_InputManager->destroyInputObject( m_Mouse );
	m_InputManager->destroyInputObject( m_Keyboard );

	OIS::InputManager::destroyInputSystem(m_InputManager);
	m_InputManager = 0;
}

bool PFrameListener::frameStarted( const FrameEvent& evt ) {
	
	m_OverlayToggle -= evt.timeSinceLastFrame;
	m_GUIToggle		-= evt.timeSinceLastFrame;
	
	m_Mouse->capture();
	m_Keyboard->capture();

	processUnbufferedKeyInput( evt );
	processUnbufferedMouseInput( evt );

	if (m_GUIstate == GUI_RIEPILOGO) {
		// visualizza la finestra di riepilogo missione
		m_OverGUI->show();
	}
	
	if ( m_GUIstate == GUI_CONTROLLI ) {
		// visualizza la finestra di riepilogo controlli
		m_OverGUI->show();
		
	}
	
	if ( m_GUIstate == GUI_GAME ) {
		// gioca

		if ( m_Navicella ) {
			if( !m_Vittoria ) {
				m_Vittoria = m_Navicella->update( evt.timeSinceLastFrame, m_Keyboard, m_Mouse );
			}
			m_ExCamera->update( evt.timeSinceLastFrame, m_Navicella->getCameraNode()->getWorldPosition(), m_Navicella->getNaviDir()->getWorldPosition() );
		}

			// lo stargate ruota
			m_SceneMgr->getSceneNode( "Stargate" )->rotate(Vector3(0, 0, 1), Radian( Degree( 10 * evt.timeSinceLastFrame )) ); 
			
			// timer
			if( !m_Vittoria ) OverlayManager::getSingleton().getOverlayElement("Timer")->setCaption( "Secondi: " + StringConverter::toString( m_Timer->getMilliseconds() / 1000 ) );
			
			AnimationState * m_AnimFinale = m_SceneMgr->getAnimationState( "FinePartita" );
				
			if( m_Vittoria ) {
				if( !m_ScenaFinale ) {

					m_Camera->getParentSceneNode()->detachAllObjects();
					m_SceneMgr->getSceneNode( "CameraFinale" )->attachObject( m_Camera );
					m_Camera->lookAt( Vector3( 0, 250, 0 ) );

					SceneNode * node = m_SceneMgr->getSceneNode( "NodoNavicella" );

					m_SceneMgr->getRootSceneNode()->removeChild( node );


					m_SceneMgr->getSceneNode( "NodoAnimazioneFinale" )->addChild( node );
					node->setPosition( Vector3( 0, 0, 0 ) );
					node->resetOrientation();
		
					m_SceneMgr->getSceneNode( "NodoPortale" )->setVisible( true );

					SceneNode * NodoVittoria = m_SceneMgr->getRootSceneNode()->createChildSceneNode( Vector3(800, 1200, -400) );
					ParticleSystem * ParticleVittoria = m_SceneMgr->createParticleSystem( "vittoria", "win" );
					NodoVittoria->attachObject( ParticleVittoria );
					NodoVittoria->scale( 5, 5, 5);
					
					m_AnimFinale->setEnabled( true );
					m_ScenaFinale = true;
				}
				m_AnimFinale->setLoop( false );
				m_AnimFinale->addTime( evt.timeSinceLastFrame );

				if( m_AnimFinale->hasEnded() ) 
					continueRendering = false;
			}
	}

	
	return continueRendering;
}

bool PFrameListener::processUnbufferedKeyInput( const FrameEvent& evt ) {
	using namespace OIS;

	if( m_Keyboard->isKeyDown( KC_ESCAPE ) )
		continueRendering = false;

	if( m_GUIToggle<0 && m_Keyboard->isKeyDown( KC_RETURN ) && m_GUIstate<= GUI_GAME ) {
		
		m_GUIToggle = 2;
		
		if( m_GUIstate == GUI_CONTROLLI ) {
			m_GUIstate = GUI_GAME;
			m_OverGUI->clear();
			// fai partire il timer
			m_Timer->reset();
		}
		
		if( m_GUIstate == GUI_RIEPILOGO ) {
			m_OverGUI->clear();
			m_OverGUI = OverlayManager::getSingleton().getByName("Asteroid_Cargo_GUIControls");
			m_GUIstate = GUI_CONTROLLI;
		}
		
	}
	
	return true;
}

bool PFrameListener::processUnbufferedMouseInput( const FrameEvent& evt ) {
	using namespace OIS;

	return true;
}

void PFrameListener::setSceneObject ( SceneObject * so ) {
	m_Navicella = so;
}

void PFrameListener::setExtendedCamera ( ExtendedCamera * cam ) {
	m_ExCamera = cam;
}

bool PFrameListener::frameEnded( const FrameEvent& evt ) {
	return continueRendering;
}

void PFrameListener::SetOverlayMalusPanel( String s, Real r ) {
	OverlayManager::getSingleton().getOverlayElement("MalusPanel")->setCaption(s);
	m_OverlayToggle = r;
}