//	SDL2.0Application.h - An implementation of Application for SDL 2.0.
//  ----------------------------------------------------------------------------
//	This file is part of 'NiallsAVLib', base code for any kind of audiovisual
//	apps.
//	Copyright (C) 2012  Niall Moody
//	
//	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 3 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, see <http://www.gnu.org/licenses/>.
//	----------------------------------------------------------------------------

#ifndef SDL2_0APPLICATION_H_
#define SDL2_0APPLICATION_H_

#include "SDL2.0KeyManager.h"

#include "sound/AudioDevice.h"
#include "CmdLineParams.h"
#include "Application.h"
#include "AppSettings.h"
#include "GameState.h"

#include "SDL.h"

#include <stdint.h>
#include <map>

class Sounder;
class Drawer;

typedef shared_ptr<Drawer> DrawerPtr;
typedef shared_ptr<Sounder> SounderPtr;

///	An implementation of Application for SDL 2.0.
class SDL2_0Application : public Application,
						  public CmdLineCallback,
						  public AudioDeviceCallback
{
  public:
	///	Constructor.
	SDL2_0Application();
	///	Destructor.
	~SDL2_0Application();

	///	Initialises the application.
	void initialise(CmdLineParams& cmdLine);

	///	Where the sound is generated and sent to the soundcard.
	void getAudio(float *input, float *output, int numSamples);

	///	The main event loop occurs inside this method.
	void eventLoop();

	///	Quits the game.
	void quit();
	
	///	Sets the mouse position.
	void setMousePos(const TwoFloats& pos);
	///	Grabs mouse focus (useful for playing in a window).
	void grabMouse(bool val);

	///	Moves to the next game state.
	void nextState(const std::wstring newState, const std::wstring extra);
	///	Registers a game state with the application.
	void registerGameState(const std::wstring& stateName,
						   const GameStateCreatorBase *stateCreator,
						   bool isStartState = false);

	///	Returns the number of milliseconds since the app was started.
	uint32_t getTimeSinceStart() const;

	///	Returns this application's AppSettings instance.
	const AppSettings& getAppSettings() const {return appSettings;};
	///	Returns this application's ResourceManager instance.
	const ResourceManager& getResourceManager() const {return resourceManager;};
	///	Returns this application's GlobalData instance.
	GlobalDataPtr& getGlobalData() {return globalData;};
	///	Returns this application's drawing area size.
	const TwoFloats& getDrawingAreaSize() const {return drawingSize;};
	///	Returns this application's audio device.
	AudioDevicePtr& getAudioDevice() {return audioDevice;};

	///	Sets the audio device to use.
	void setAudioDevice(AudioDevice *newDevice);

	///	Used to handle command line options.
	void cmdLineParameterFound(const std::wstring& name,
							   const std::wstring& value);
  private:
	///	Helper method. Converts mouse coordinates to drawing area coordinates.
	TwoFloats mouseToDrawer(const TwoFloats& pos);

	///	Helper method. Checks if we're running on a 16-bit display.
	bool is16Bit();

	///	Our SDL window.
	SDL_Window *window;
	///	The OpenGL context.
	SDL_GLContext openglContext;

	///	The app settings for this game.
	AppSettings appSettings;
	///	The resource manager for this game.
	ResourceManager resourceManager;
	///	The global data for this game.
	GlobalDataPtr globalData;
	///	The drawing area size for this game.
	TwoFloats drawingSize;

	///	The audio device for this game.
	AudioDevicePtr audioDevice;

	///	The Drawer for this game.
	DrawerPtr drawer;
	///	The Sounder for this game.
	SounderPtr sounder;

	///	Handles the mappings between keys/joysticks and actions.
	SDL2_0KeyManager keyManager;
	///	A temporary vector we keep on hand for the keyManager mappings.
	std::vector<std::wstring> mappingsVector;
	///	For playing with a joystick instead of the keyboard.
	std::vector<SDL_Joystick *> joysticks;

	///	Creators for all the possible states in the game.
	std::map<std::wstring, const GameStateCreatorBase *> stateCreators;
	///	The current state in the game.
	GameStatePtr currentState;
	///	Name of the start state.
	std::wstring startState;

	///	Used to quit out of the eventLoop.
	bool timeToQuit;
	///	We use this to determine if we need to repaint the screen immediately.
	uint32_t lastRepaint;
	///	Used to provide a fixed timestep.
	float timeAccumulator;
	///	Used to help smooth the timeAccumulator.
	float lastFrameTime;

	///	Additional command line help text.
	std::wstring helpText;

	///	Command line parameter.
	int cmdWidth;
	///	Command line parameter.
	int cmdHeight;
	///	Command line parameter.
	bool cmdWindow;
	///	Command line parameter.
	bool cmdMute;
	///	Command line parameter.
	std::wstring cmdDrawer;
	///	Command line parameter.
	std::wstring cmdAudioAPI;
	///	Command line parameter.
	bool cmdDebug;
	///	Command line parameter.
	bool cmdHelp;

	///	Whether or not VSync is on.
	bool vSync;
};

#endif
