#pragma once
#include "Image.h"

namespace DXFW
{
/// <summary>次コマの移動先</summary>
/// 詳細説明
enum class NextFrame
{
	Normal  = -10000,///次のコマに進む
	ToFront ,///コマの進む向きをプラスにしてから進む
	ToBack  ,///コマの進む向きをマイナスにしてから進む
	End     ,///このコマでアニメーションを停止する
};

enum class AnimeType
{
	Normal,///最後まで再生するとまた最初から再生
	Reverse,///最後まで再生すると、再生方向を反転する
	End///最終フレームで再生を停止する
};

///	<summary>
/// まとめたImageをコマ送りアニメーションとして扱うクラス
///	</summary>
///	<example>
///	[サンプルコード:未完成]<br/>
/// サンプル説明<br/>
///	<code>
///	int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow )<br/>
///	{<br/>
///		if( !Dx::Initialise() ) return -1;<br/>
///		Dx::End();<br/>
///		return 0;<br/>
/// }<br/>
/// </code>	
/// </example>
class Anime : public ImagePack
{
private:
	std::vector<unsigned int> times;//コマのフレーム数
	std::vector<int> nexts;//各コマの次フレーム
public:
	///<summary>コマの管理</summary>
	///詳細説明<br/>
	class Counter
	{
	private:
		Anime& anime;//対応アニメ
		int direct;//進行方向
		int frameNumber;//現在のコマ
		double timer;//経過時間
	public:
		
		///<summary>カウンタを作成</summary>
		Counter(Anime& 親アニメ):
			anime(親アニメ),
			direct(1),
			frameNumber(0),
			timer(0)
		{}

		///<summary>カウンタの更新</summary>
		bool UpDate( double 経過フレーム)
		{
			timer += 経過フレーム;

			double totalTime = 0;

			if( timer > anime.times[frameNumber] )
			{
				timer -= anime.times[frameNumber];
				switch ( anime.nexts[frameNumber] )
				{
					case (int)NextFrame::Normal:
						frameNumber += direct;
					break;
					case (int)NextFrame::ToFront:
						direct = 1;
						frameNumber += direct;
					break;
					case (int)NextFrame::ToBack:
						direct = -1;
						frameNumber += direct;
					break;
					case (int)NextFrame::End:
						return false;
					break;
					default:
						frameNumber = anime.nexts[frameNumber];
					break;
				}

				if( (unsigned int)frameNumber >= anime.images.size() ) frameNumber = 0;
				if( frameNumber < 0									  )	frameNumber = anime.images.size()-1;
			}

			return true;
		}
		
		///<summary>現在のコマ番号を取得</summary>
		int GetFrame()
		{
			return frameNumber;
		}
		
		///<summary>コマの位置を設定</summary>
		void SetFrame(int コマ数 )
		{
			this->frameNumber = コマ数;
			timer = 0;
		}
	};
		
	Anime(){}

	/// <summary>画像ファイルを分割読込</summary>
	/// 画像ファイルを分割してメモリへ読み込む。<br/>
	/// 各コマのフレーム数は初期で1になります。
	Anime( const char *ファイル名 , int 総コマ数 ,int コマ割り横,int コマ割り縦,int コマ幅 ,int コマ高さ ):
		ImagePack( ファイル名 , 総コマ数 ,コマ割り横 , コマ割り縦 , コマ幅 , コマ高さ)
	{
		for( unsigned int i=0; i<times.size() ; i++ )
		{
			times[i] = 1;
			nexts[i] = (int)NextFrame::Normal;
		}
	}
	
	///<summary>１つの画像を分割して読み込む</summary>
	///各コマのフレーム時間は初期で1になります。
	bool Load(const char *ファイル名 , int 総コマ数,int コマ割り横, int コマ割り縦 ,int コマ横幅,int コマ縦幅 )
	{
		std::vector<int> buf(総コマ数);

		if( DxLib::LoadDivGraph(ファイル名,総コマ数,コマ割り横,コマ割り縦,コマ横幅,コマ縦幅, &buf.front() ) == 0 )
		{
			for(int i=0;i<総コマ数;i++)
			{
				this->Add( new Image(buf[i]) );
			}
		}			

		return true;
	}
			
	/// <summary>連番ファイルを一括して読み込む</summary>
	bool Load(const char* ファイル名 , const char *拡張子 , int 総コマ数 )
	{
		for(int i=0 ; i<総コマ数 ; i++)
		{ 
			char fileBuf[8];
			sprintf_s( fileBuf , 8 , "%03d." , i );
			std::string fileName = ファイル名;
			fileName += fileBuf;
			fileName += 拡張子;

			this->Add( new Image( fileName.c_str() ) );
		}
		return true;
	}

	/// <summary>イメージを追加</summary>
	/// 末尾に新しいイメージを追加する。
	void Add(Image *追加イメージ)
	{
		ImagePack::Add( 追加イメージ );
		times.push_back( 1 );
		nexts.push_back( (int)NextFrame::Normal);
	}
	void Add(const char *ファイル名)
	{
		Add( new Image( ファイル名 ) );
	}

	/// <summary>イメージをメモリから開放</summary>
	/// メモリから全てのイメージを開放する
	void Release()
	{
		ImagePack::Release();

		times.clear();
		nexts.clear();
	}

	///<summary>各コマのフレーム数を設定</summary>
	///先頭コマからフレーム再生時間を設定する
	void SetFrameTime( int* フレーム時間 )
	{
		for(unsigned int i=0 ; i< times.size() ; ++i )
		{
			times[i] = フレーム時間[i];
		}
	}

	///<summary>各コマのフレーム数を設定</summary>
	///最終コマの次フレームを指定する
	void SetType( AnimeType 再生方法 )
	{
		switch(再生方法)
		{
			case AnimeType::Normal:
				nexts[nexts.size()-1] =(int)NextFrame::Normal;
			break;
			case AnimeType::Reverse:
				nexts[0] =(int)NextFrame::ToFront;
				nexts[nexts.size()-1] =(int)NextFrame::ToBack;
			break;
			case AnimeType::End:
				nexts[nexts.size()-1] =(int)NextFrame::End;
			break;
		}
	}
	
	///<summary>各コマのフレーム数を設定</summary>
	///指定したコマの次フレームを設定する
	void SetType( int コマ番号 , int 次フレーム )
	{
		nexts[コマ番号] = 次フレーム;
	}
	void SetType( int コマ番号 , NextFrame 次フレーム )
	{
		nexts[コマ番号] = (int)次フレーム;
	}

	/// <summary>合計フレーム時間を返す</summary>
	/// 全てのフレーム再生時間の和を返す
	int GetAnimeTime() const
	{
		int totalTime = 0;

		for( auto it : times )
		{
			totalTime += it;
		}

		return totalTime;
	}

	Image* operator[](int index)
	{
		return images[index];
	}
};
}