//	Tone.h - Base class for all Tone types.
//  ----------------------------------------------------------------------------
//	This file is part of 'GameTemplate', template code for a game.
//	Copyright (C) 2011  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 TONE_H_
#define TONE_H_

#include "TwoFloats.h"
#include "c0xHeaders.h"
#include "ThreeFloats.h"
#include "drawing/TextLayout.h"

#include <string>
#include <vector>
#include <fstream>
#include <stdint.h>

class Drawer;
class OverrideBehaviour;

typedef shared_ptr<Drawer> DrawerPtr;

//------------------------------------------------------------------------------
class Tone;
class Pickup;
class GameCounter;
class TonesSounder;
typedef shared_ptr<Tone> TonePtr;
typedef shared_ptr<Pickup> PickupPtr;
typedef shared_ptr<TonesSounder> TonesSounderPtr;

//------------------------------------------------------------------------------
///	Base class for all Tone types.
class Tone
{
  public:
	///	Constructor.
	/*!
		\param rail The rail this tone starts on.
		\param numRails The number of rails currently available.
		\param col This tone's colour.
		\param speed This tone's speed.
		\param sound The Sounder the tone can use.
	 */
	Tone(int startRail,
		 float startNumRails,
		 const ThreeFloats& col,
		 float speed,
		 TonesSounderPtr& sound);
	///	Copy Constructor.
	Tone(const Tone& other);
	///	Destructor.
	virtual ~Tone();

	///	Moves the tone dot.
	/*!
		This can be overridden via an OverrideBehaviour.
	 */
	void move(float globalSpeed,
			  std::vector<TonePtr>& allTones,
			  bool ignoreOverride = false);
	///	Draws the Tone dot.
	/*!
		\param d The Drawer to draw with.
		\param playerPos The position of the mouse. Used to draw the dot
		brighter when the mouse is over it.
	 */
	void draw(DrawerPtr& d, float timestepInterp, const TwoFloats& playerPos);

	///	Sets an override behaviour for this tone.
	/*!
		\param behave This will be deleted in the destructor. If you want it
		deleted before then, delete it yourself then call
		setOverrideBehaviour(0).

		Pickups override tones' default behaviour.
	 */
	void setOverrideBehaviour(shared_ptr<OverrideBehaviour>& behave);
	///	Sets the Pickup this Tone is carrying.
	/*!
		Only used by DropperTone.
	 */
	virtual void setPickup(PickupPtr p) {};

	///	Sets the GameCounter instance we're using.
	void setGameCounter(shared_ptr<GameCounter>& counter);
	///	Returns the GameCounter instance.
	shared_ptr<GameCounter>& getGameCounter() {return gameCounter;};

	///	Sets any text to be displayed above the tone.
	void triggerTextAbove(const std::wstring& text);
	///	Sets any text to be displayed below the tone.
	void triggerTextBelow(const std::wstring& text);

	///	Returns the name of this tone type.
	virtual std::wstring getName() const = 0;
	///	Returns the score you get if this dot makes it to the opposite side of the screen.
	virtual int getScore() const = 0;
	///	Returns the Tone's position.
	const TwoFloats& getPosition() const {return position;};
	///	Returns the Tone's colour.
	const ThreeFloats& getColour() const {return colour;};
	///	Returns which rail this Tone is on.
	int getRail() const {return rail;};
	///	Returns the rail this Tone is moving towards.
	/*!
		\return Will be equal to getRail() if the Tone is not in the process of
		switching rails.
	 */
	int getNewRail() const {return newRail;};
	///	Returns the Tone's speed.
	float getSpeed() const {return speed;};
	///	Returns true if the Tone's in a warning state.
	bool getWarning() const {return warning;};

	///	Updates the number of rails.
	void setNumRails(float val);
	///	Sets the new number of rails pending.
	void setNumRailsPending(int val);

	///	Sets this Tone's colour.
	void setColour(const ThreeFloats& col);
	///	Sets this Tone's speed.
	/*!
		Can be negative to move the tone left->right.
	 */
	void setSpeed(float val);
	///	Informs the Tone whether or not it's in warning state for the current frame.
	/*!
		This will get updated for every frame.
	 */
	void setWarning(bool val, TonePtr otherTone);

	///	Tells the dot to stop moving.
	void pause(bool val = true);
	///	Tells the dot to kill its synth voice.
	void killTone();

	///	Called when the player clicks the mouse button while this dot's selected.
	void startSwipe(const TwoFloats& mousePos);
	///	Called when the player moves the mouse while this dot's selected.
	void swipe(const TwoFloats& mousePos);
	///	Called when the player releases the mouse button while this dot's selected.
	void endSwipe(const TwoFloats& mousePos);

	///	Tells the dot it's collided with another.
	void setCollided();

	///	(Tries to) move the tone to the rail above(true) or below(false).
	void switchRail(bool direction);

	///	Returns the tone's sounder.
	TonesSounderPtr& getSounder() {return sounder;};

	///	The radius of a dot (constant).
	static const float Radius;

	friend class Behaviour2xSpeed;
	friend class BehaviourHalfSpeed;
	friend class BehaviourFreeze;
	friend class BehaviourSticky;
	friend class BehaviourReverse;
	friend class BehaviourDeflectUp;
	friend class BehaviourDeflectDown;
	friend class BehaviourPendulum;
	friend class BehaviourSplit;
	friend class BehaviourAutopilot;
	friend class BehaviourAutopilotTitle;
  protected:
	///	Sets the tone's position.
	void setPosition(const TwoFloats& newPos);
	///	Sets the tone's synth index.
	void setSynthIndex(int val);

	///	Gets called every time move() is called, in case subclasses need to update counters etc.
	virtual void tick() {};

	///	Returns whether the tone is currently paused or not.
	bool getPaused() const {return isPaused;};

	///	Returns the tone's current override behaviour if it has one.
	shared_ptr<OverrideBehaviour>& getOverrideBehaviour() {return overrideBehaviour;};

	///	Used by DropperTone.
	float getNumRails() const {return numRails;};
	///	Used by DropperTone.
	float getPrevNumRails() const {return prevNumRails;};
	///	Used by DropperTone.
	float getRailInterp() const {return railInterp;};

	///	The size of the dot's trail.
	enum
	{
		TrailSize = 64
	};
  private:
	///	The dot's current position.
	TwoFloats position;
	///	The dot's previous positions.
	std::vector<TwoFloats> prevPos;
	///	Used to draw curving lines.
	std::vector<float> lineScale;
	///	Used to draw curving lines.
	std::vector<ThreeFloats> lineColour;
	///	Used to draw curving lines.
	std::vector<float> lineAlpha;
	///	The dot's current rail.
	int rail;
	///	The number of currently-available rails.
	float numRails;
	///	The previous number of rails.
	float prevNumRails;
	///	Used to interpolate between the two numbers of rails.
	float railInterp;

	///	When numRails is about to change, this holds the new number.
	int numRailsPending;

	///	The tone's current OverrideBehaviour.
	shared_ptr<OverrideBehaviour> overrideBehaviour;

	///	The GameCounter instance used to update the score.
	shared_ptr<GameCounter> gameCounter;

	///	The rail the dot's moving towards.
	int newRail;
	///	Used to move the dot towards newRail in a cosine motion.
	float movingRail;

	///	The Tone's colour.
	ThreeFloats colour;
	///	The Tone's speed.
	float speed;

	///	Used to display text above the Tone.
	std::wstring textAbove;
	///	The TextLayout for textAbove.
	TextLayout textAboveLayout;
	///	Used to display text above the Tone.
	int textAboveCount;
	///	Used to display text below the Tone.
	std::wstring textBelow;
	///	The TextLayout for textBelow.
	TextLayout textBelowLayout;
	///	Used to display text below the Tone.
	int textBelowCount;

	///	Whether or not the Tone is currently in a warning state.
	bool warning;
	///	Used to scale the warning image.
	float warningScale;
	///	The Tone we're in danger of colliding with.
	weak_ptr<Tone> warningTone;

	///	If the dot's being swiped by the player.
	bool swiping;
	///	The swipe start position (y-axis).
	float swipeStart;
	///	Used to count to 3 (mouse move messages) before we commence the rail move.
	int swipeCount;

	///	Our index to a synth voice.
	int synthIndex;

	///	True if we've killed the synth voice already.
	bool noteOff;
	///	True if this dot collided with another.
	bool collided;

	///	True if we should be paused.
	bool isPaused;

	///	Our copy of the sounder.
	TonesSounderPtr sounder;

	///	Temp.
	//static std::ofstream logFile;
};

#endif
