/***********************************************************
 * God Mode On, Und[0]ne Devs < http://undonedevs.tk >
 * 2013 Pepe Romero < wizardpepe@gmail.com >
 * < https://bitbucket.org/undone_devs/god-mode-on >
 ***********************************************************/

#ifndef PlayState_H
#define PlayState_H

#include <Ogre.h>
#include <OgreFontManager.h>
#include <OIS.h>
#include <CEGUI.h>
#include <OgreBulletDynamicsRigidBody.h>
#include <Shapes/OgreBulletCollisionsTrimeshShape.h>
#include <Utils/OgreBulletCollisionsMeshToShapeConverter.h>
#include <Shapes/OgreBulletCollisionsBoxShape.h>
#include <Shapes/OgreBulletCollisionsSphereShape.h>

#include "GameState.h"
#include "Object.h"

class PlayState : public Ogre::Singleton<PlayState>, public GameState
{

public:
    PlayState () {}

    void enter ();
    void exit ();
    void pause ();
    void resume ();

    void keyPressed (const OIS::KeyEvent &e);
    void keyReleased (const OIS::KeyEvent &e);
    void mouseMoved (const OIS::MouseEvent &e);
    void mousePressed (const OIS::MouseEvent &e, OIS::MouseButtonID id);
    void mouseReleased (const OIS::MouseEvent &e, OIS::MouseButtonID id);

    bool frameStarted (const Ogre::FrameEvent &evt);
    bool frameEnded (const Ogre::FrameEvent &evt);

    // Heredados de Ogre::Singleton.
    static PlayState &getSingleton();
    static PlayState *getSingletonPtr();

protected:
    Ogre::Root *_root;
    Ogre::SceneManager *_sceneMgr;
    Ogre::MaterialManager *_materialMgr;
    Ogre::MeshManager *_meshMgr;
    Ogre::FontManager *_fontMgr;
    Ogre::OverlayManager *_overlayMgr;
    Ogre::Viewport *_viewport;
    Ogre::Camera *_camera;

    // Datos de motor físico
    OgreBulletDynamics::DynamicsWorld *_world;
    OgreBulletCollisions::DebugDrawer *_debugDrawer;

    // Datos de motor físico del pj
    OgreBulletCollisions::SphereCollisionShape *_pjShape;
    OgreBulletDynamics::RigidBody *_pjRigidBody;

    // Datos del motor físico de la puerta
    OgreBulletCollisions::StaticMeshToShapeConverter *_trimeshConverter;
    OgreBulletCollisions::TriangleMeshCollisionShape *_puertaTrimesh;
    OgreBulletDynamics::RigidBody *_rigidpuerta;

    // Nodos, overlays, materiales, entidades y luces
    Ogre::SceneNode *_sceneNode, *_pj1Node, *_movPJNode, *_cameraNode, *_object1Node, *_lightsNode, *_light1Node;
    Ogre::SceneNode *_boton1Node, *_trampasNode, *_bookNode, *_puertaNode;
    Ogre::Material *_objSelectedMaterial, *_objUnSelectedMaterial;
    Ogre::Entity *_esc1Entity, *_esc2Entity, *_pj1Entity, *_obj1_0Entity, *_obj1_1Entity, *_light1Entity, *_puertaEntity, *_boton1Entity, *_bookEntity;
    Ogre::Entity *_trampaF1, *_trampaF2, *_trampaF3, *_trampaF4, *_trampaF5, *_trampaF6, *_trampaF7, *_trampaF8;
    Ogre::Entity *_trampaC1, *_trampaC2, *_trampaC3, *_trampaC4, *_trampaC5, *_trampaC6, *_trampaC7, *_trampaC8;
    Ogre::Light *_light1Light;

    CEGUI::Window *_sheet, *_escenarioHUD, *_nivelHUD, *_tiempoHUD, *_objetoHUD, *_fondoHUD;

    bool _exitGame;
    bool _completado;
    bool _puertaExiste;
    Ogre::Timer *_tiempoN;
    Object *_object1;
    int _nivel;
    int _tiempoObjetivo;

    void actualizaHUD();

    // Devuelve el tiempo del nivel formateado
    Ogre::String formateaTiempo(int segundos);

    void cargaNivel1();
    void cargaNivel2();
    void cargaNivel3();

    // ------------------------ TODO: Deben ir en la clase PJ -----------------------------------------
    bool _movW;
    bool _movA;
    bool _movS;
    bool _movD;
    void movPlayer();
    void movLibro();
    void comprobacionFinPuzzle();
    void comprobacionObjetoDestruidoN2();
    void comprobacionObjetoDestruidoN3();
};

#endif
