#ifndef __SFJP_MYU__AGH_EffectControl_H__
#define __SFJP_MYU__AGH_EffectControl_H__

namespace math{

	//	線・波の基底クラス
	template <typename Ty>
	class TLineBase
	{
	protected:
		Ty m_rangeMin, m_rangeMax;

		inline Ty _Sub(){
			return m_rangeMax - m_rangeMin; }
	public:
		//	コンストラクタ・デストラクタ
		TLineBase(){
			m_rangeMin = m_rangeMax = 0;
		}
		virtual ~TLineBase(){}

		//	最小値と最大値を設定する。
		void SetRange(Ty rangeMin, Ty rangeMax){
			m_rangeMin = rangeMin;
			m_rangeMax = rangeMax;
		}

		//	0.0f〜1.0fの間で指定する事により中間値を取得する。・・・まぁマイナスとか1.0f以上の指定も可能だけれど・・・
		virtual Ty Get(float fIntermediate)=0;
	};

	typedef TLineBase<int> CIntLineBase;
	typedef TLineBase<float> CFloatLineBase;

	//typedef CLineBase CWaveBase;

	//////////////////////////////////////////////////

	//	直線クラス
	template <typename Ty>
	class TStraightLine : public TLineBase<Ty>
	{
	public:
		TStraightLine(){}
		virtual ~TStraightLine(){}

		Ty Get(float fIntermediate){
			return (Ty)(m_rangeMin + _Sub() * fIntermediate);
		}
	};
	typedef TStraightLine<int> CStraightLine, CStraight, CLinear, CLine;
	typedef TStraightLine<int> CIntStraightLine, CIntStraight, CIntLinear, CIntLine;
	typedef TStraightLine<float> CFloatStraightLine, CFloatStraight, CFloatLinear, CFloatLine;

	//typedef CStraightLine CStraight, CLinear, CLine;

}//end of math namespace



/*
class CEffectControlBase : public CControlBase {
protected
	int m_frameCounter;
	int m_nowTimeMs;

_AGH_EVENT_ACCESS_MODIFIER:
	virtual bool OnFrame(){
		m_frameCounter++;
		return true;
	}

public:
	CEffectControlBase(){
		//ResetTime();
	}
	virtual ~CEffectControlBase(){}

	void ResetTime(){
		if ( m_nowTimeMs == -1 )
			SetTimeUnitInFrame();
		else
			SetTimeUnitInMs();
	}

	void SetTimeUnitInFrame(){ m_frameCounter=0; m_nowTimeMs=-1; }
	void SetTimeUnitInMs(){ m_frameCounter=-1; m_nowTimeMs=0; }
};*/

#define AGH_EFFECT_MODE_TIME	(1)
#define AGH_EFFECT_MODE_FRAME	(2)

class CEffectControlBase : public CControlBase {
private:
	bool m_bAvailable;
protected:
	int m_nCounter;
	int m_mode;

_AGH_EVENT_ACCESS_MODIFIER:
	virtual bool OnFrame(){
		if ( m_bAvailable ){
			if ( m_mode == AGH_EFFECT_MODE_FRAME )
				m_nCounter++;
			else
				throw 0;//	TODO: とりあえず時間取得は環境依存の部分が面倒なので後回し（多分MXPとか使う・・・）
		}
		return true;
	}

public:
	CEffectControlBase(){
		ResetTime();
		SetCountInFrame();
		//m_bAvailable = false;
		Stop();
	}
	virtual ~CEffectControlBase(){}

	void ResetTime(){ m_nCounter = 0; }

	void Start(){ m_bAvailable = true; }
	void Stop(){ m_bAvailable = false; ResetTime(); }
	void Pause(){ m_bAvailable = m_bAvailable ? false : true; }
	bool IsAvailable(){ return m_bAvailable; }

	void SetCountInFrame(){ m_mode = AGH_EFFECT_MODE_FRAME; }
	void SetCountInTime(){ m_mode = AGH_EFFECT_MODE_TIME; }
};

////////////////////////////////////////////////////////////////////////////////////////////////////

/*
//	色のフェード
class CColorFadeController : public CEffectControlBase
{
protected:
	AGHCOLOR m_startColor;
	AGHCOLOR m_endColor;
	int m_nTargetTime;
	AGHCOLOR *m_pTarget;

	//	イベントハンドラ
_AGH_EVENT_ACCESS_MODIFIER:
	virtual bool OnFrame(){
		if ( m_timeInFrame != 0 ){
			if ( m_timeInFrame <= m_frameCounter ){
				if ( pTargetColor == NULL )
					throw CAghException("CColorFadeController::OnFrame()  Target color not setted. "
						"Please call SetParentControl() or SetTargetColorPtr()");

				CEffectControlBase::OnFrame();
			}
			else
				m_timeInFrame = 0;
		}
		return true;
	}

public:
	//	コンストラクタ
	CColorFadeController(){
		m_startColor = 0xffffffff;
		m_endColor = 0xffffffff;
		m_nTargetTime = 0;
		m_pTarget = NULL;
	}

	void Fade(AGHCOLOR startColor, AGHCOLOR endColor, int nTime){
		m_startColor = startColor;
		m_endColor = endColor;
		m_nTargetTime = nTime;
		ResetTime();
	}
	void FadeIn(int nTime){ Fade( 0x00ffffff, 0xffffffff, nTime); }
	void FadeOut(int nTime){ Fade( 0xffffffff, 0x00ffffff, nTime); }

	virtual void SetParentControl(CVisualControlBase* pParentControl){
		//TODO: m_pTarget = pParentControl->
		CControlBase::SetParentControl(pParentControl);
	}
	void SetTargetColorPtr(AGHCOLOR *pTargetColor){
		m_pTarget = pTargetColor;
	}
};
*/

template <typename LINE_CLASS=CIntStraightLine>
class CColorLine
{
protected:
	LINE_CLASS m_la, m_lr, m_lg, m_lb;
};

//####################

//	色のフェード
template <typename LINE_CLASS = math::CIntStraightLine>
class TColorFadeEffect : public CEffectControlBase
{
private:
	typedef CEffectControlBase _BASE;
protected:
	//AGHCOLOR m_startColor;
	//AGHCOLOR m_endColor;
	int m_nGoalTime;	//	Termなんてのも考えた
	CVisualControlBase *m_pTarget;

	//LINE_CLASS m_lineA, m_lineR, m_lineG, m_lineB;
	//LINE_CLASS _la, _lr, _lg, _lb;
	LINE_CLASS m_la, m_lr, m_lg, m_lb;

	//	イベントハンドラ
_AGH_EVENT_ACCESS_MODIFIER:
	virtual bool OnFrame(){
		_BASE::OnFrame();

		/*if ( m_timeInFrame != 0 ){
			if ( m_timeInFrame <= m_frameCounter ){
				if ( pTargetColor == NULL )
					throw CAghException("CColorFadeController::OnFrame()  Target color not setted. "
						"Please call SetParentControl() or SetTargetColorPtr()");

				CEffectControlBase::OnFrame();
			}
			else
				m_timeInFrame = 0;
		}*/
		if ( IsAvailable() ){
			float f = m_nCounter / (float)m_nGoalTime;
			m_pTarget->SetColor(AGHCOLOR_ARGB(m_la.Get(f), m_lr.Get(f), m_lg.Get(f), m_lb.Get(f)));
		}
		return true;
	}

public:
	//	コンストラクタ
	TColorFadeEffect(){
		//m_startColor = 0xffffffff;
		//m_startColor = 0;
		//m_endColor = 0xffffffff;
		m_nGoalTime = 0;
		m_pTarget = NULL;

		/*m_la.SetRange(0,255);
		m_lr.SetRange(0,255);
		m_lg.SetRange(0,255);
		m_lb.SetRange(0,255);*/
	}
	virtual ~TColorFadeEffect(){}

	///////////////////////////////////////////////////////////

	void SetTargetControl(CVisualControlBase* pControl){
		m_pTarget = pControl;
	}

	void Setup(CVisualControlBase* pControl, AGHCOLOR startColor, AGHCOLOR endColor, int nGoalTime){
		SetTargetControl(pControl);
		Fade(startColor, endColor, nGoalTime);
	}

	//////////////////////

	void Fade(AGHCOLOR startColor, AGHCOLOR endColor, int nGoalTime){
		//m_startColor = startColor;
		//m_endColor = endColor;
		m_nGoalTime = nGoalTime;

		unsigned char* pbStartColor = (unsigned char*)&startColor;
		unsigned char* pbEndColor = (unsigned char*)&endColor;
		m_lb.SetRange( pbStartColor[0], pbEndColor[0] );
		m_lg.SetRange( pbStartColor[1], pbEndColor[1] );
		m_lr.SetRange( pbStartColor[2], pbEndColor[2] );
		m_la.SetRange( pbStartColor[3], pbEndColor[3] );

		Start();
	}
	void FadeIn(int nGoalTime){ Fade( 0x00ffffff, 0xffffffff, nGoalTime); }
	void FadeOut(int nGoalTime){ Fade( 0xffffffff, 0x00ffffff, nGoalTime); }
	void FadeIn(CVisualControlBase* pControl, int nGoalTime){ Setup( pControl, 0x00ffffff, 0xffffffff, nGoalTime); }
	void FadeOut(CVisualControlBase* pControl, int nGoalTime){ Setup( pControl, 0xffffffff, 0x00ffffff, nGoalTime); }

};
typedef TColorFadeEffect<> CColorFadeEffect, CFadeEffect;

//	点滅
class CBlinkController : public CEffectControlBase {
};

#endif//__SFJP_MYU__AGH_EffectControl_H__