/*
    Copyright (C) 2004  Miguel Guzman (Aglanor)

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program 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 General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#ifndef GUIMANAGER_H
#define GUIMANAGER_H


#include "EmberOgrePrerequisites.h"

#include <CEGUIBase.h>
#include <OgreCEGUIRenderer.h>

#include <sigc++/trackable.h>

#include <OgreKeyEvent.h> 
#include "framework/Singleton.h"

#include <SDL.h>
#include <stack>

#include "framework/ConsoleObject.h"

#include "input/Input.h"
#include "input/InputCommandMapper.h"

namespace Ember {
class IScriptingProvider;
}

namespace EmberOgre {

class EmberEntity;
class TerrainGenerator;
class CEGUI::Window;
class Widget;
class ConsoleWidget;
class MousePicker;
class Input;
class AvatarEmberEntity;
class GUICEGUIAdapter;
class EntityWorldPickListener;
class AvatarController;

/**
 * This class will be responsible for all the GUI related things
 */
class GUIManager : 
public Ember::Singleton<GUIManager>, 
Ogre::FrameListener,
public sigc::trackable,
public Ember::ConsoleObject
{
public:

	typedef std::vector<Widget*> WidgetStore;

	static const std::string SCREENSHOT;
	static const std::string TOGGLEINPUTMODE;


	GUIManager(Ogre::RenderWindow* window, Ogre::SceneManager* sceneMgr);
	virtual ~GUIManager();
	
	sigc::signal<void, const std::string&, EmberEntity*> AppendIGChatLine;
	sigc::signal<void, const std::string&, EmberEntity*> AppendOOGChatLine;
	
	sigc::signal<void, const std::string&, EmberEntity*> EventEntityAction;
	
	/**
	Emitted every frame.
	*/
	sigc::signal<void, float> EventFrameStarted;
	
	/**
	 *    Emits an action for a certain entity.
	 *    An action could be something like "touch" or "inspect".
	 * @param action 
	 */
	void EmitEntityAction(const std::string& action, EmberEntity* entity);
	
	/**
	 *    Removed a widget from the system.
	 * @param widget 
	 */
	void removeWidget(Widget* widget);
	
	/**
	 *    Adds a new widget to the system. This means it will recieve FrameStarted events.
	 * @param widget 
	 */
	void addWidget(Widget* widget);

	/**
	 *    Called by Ogre each frame.
	 * @param evt 
	 * @return 
	 */
	bool frameStarted(const Ogre::FrameEvent& evt);

	/**
	 *    Gets the root sheet of the CEGUI windowing system.
	 * @return 
	 */
	CEGUI::Window* getMainSheet() const;
	
	
	/**
	 *    Called by EmberOgre at initialization.
	 */
	void initialize();
	
	
	/**
	 *    sets a text to be shown somewhere on the screen, used for debugging purposes
	 * @param text 
	 */
	void setDebugText(const std::string& text);

	/**
	 *    true if we're in GUI mode, which means that input events will be sent to the CEGUI system instead of the "world"
	 * @return 
	 */
	const bool isInGUIMode() const;
	
	
	/**
	 *    true if keyboard input should make the avatar move
	 *    this happens when wither 1) we're not in gui mode 2) the background sheet has the input control (thus, when something else, like an edit box has input control, that edit box will recieve key strokes
	 * @return 
	 */
	const bool isInMovementKeysMode() const;
	
	/**
	 *    Gets the currently active MousePicker instance.
	 * @return 
	 */
	inline MousePicker* getMousePicker() { return  mMousePickers.top(); }
	
	
	/**
	 *    accessor for the Input instance object
	 * @return 
	 */
	Input& getInput() const;
	
	/**
	 *    Pushes a new mouse picker onto the stack, "pushing down" the current mouse picker.
	 * @param mousePicker 
	 */
// 	void pushMousePicker(MousePicker* mousePicker);
	
	/**
	 *    Pops the current mouse picker from the stack and returns the next in line.
	 *    It's not possible to empty the stack. If there's only one picker left, no popping will be done, and the last picker will be returned.
	 * @return 
	 */
// 	MousePicker* popMousePicker();
	
	inline CEGUI::OgreCEGUIRenderer* getGuiRenderer() const {return mGuiRenderer;}

	/**
	 *    Reimplements the ConsoleObject::runCommand method
	 * @param command 
	 * @param args 
	 */
	virtual	void runCommand(const std::string &command, const std::string &args);


	/**
	 *    returns the path to the directory where all layouts are stored
	 * @return 
	 */
	const std::string& getLayoutDir() const;
	
	/**
	 *    Creates a new Widget
	 * @return 
	 */
	Widget* createWidget();
	
	/**
	 *    creates a widget 
	 *    @see WidgetLoader
	 * @param name the type of widget to create
	 * @return 
	 */
	Widget* createWidget(const std::string& name);

	/**
	 *    Gets the name of the default scheme used (such as "EmberLook" or "WindowsLook")
	 * @return 
	 */
	const std::string& getDefaultScheme() const;
	
	EntityWorldPickListener* getEntityPickListener() const;
	
	const Ember::ConsoleCommandWrapper ToggleInputMode;
	const Ember::ConsoleCommandWrapper ReloadGui;
	
protected:

	InputCommandMapper mGuiCommandMapper;

	MousePicker* mPicker;

	EntityWorldPickListener* mEntityWorldPickListener;

	CEGUI::Window* mSheet;
	CEGUI::WindowManager* mWindowManager;
	CEGUI::StaticText* mDebugText;
	
	ConsoleWidget* mConsoleWidget;
	
	Ogre::RenderWindow* mWindow;
	CEGUI::System* mGuiSystem;
	CEGUI::OgreCEGUIRenderer* mGuiRenderer;
	
	std::string mDefaultScheme;

	
	/**
	all loaded widgets are stored here
	*/
	WidgetStore mWidgets;
	
	std::vector<Ember::IScriptingProvider*> mScriptingProviders;

	

	/**
	A stack of the mouse pickers used. This allows for a component to "push down" the current mouse picker in favor of its own
	*/
	std::stack<MousePicker*> mMousePickers;
		

	//events
	bool mSheet_MouseButtonDown(const CEGUI::EventArgs& args);
	bool mSheet_CaptureLost(const CEGUI::EventArgs& args);
	
	

	
	/**
	 *    hooked to EmberOgre::EventCreatedAvatarEntity, switches the input mode to movement mode
	 * @param entity 
	 */
	void EmberOgre_CreatedAvatarEntity(AvatarEmberEntity* entity);
	
	
	/**
	 *    hooked to EmberOgre::EventAvatarControllerCreated, connects the mEntityWorldPickListener to the main AvatarCamera
	 * @param controller 
	 */
	void EmberOgre_AvatarControllerCreated(AvatarController& controller);

// 	InputMode mPreviousInputMode;
	void pressedKey(const SDL_keysym& key, Input::InputMode inputMode);
	
	/**
	Adapter for CEGUI which will send input events to CEGUI
	*/
	GUICEGUIAdapter* mCEGUIAdapter;
	
// 	GUIScriptManager* mScriptManager;

};
}


#endif 
