#pragma once
#include <Multimedia/SDX.h>
#include <Multimedia/Image.h>
#include <Framework/ImagePack.h>

namespace SDX
{
/** 次コマの移動先.*/
/// 0以上の場合は、そのコマにジャンプする
enum class NextFrame
{
	Normal  = -10000,//次のコマに進む
	ToFront ,//コマの進む向きをプラスにしてから進む
	ToBack  ,//コマの進む向きをマイナスにしてから進む
	End     ,//このコマでアニメーションを停止する
};

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

/** Imageをまとめてコマ送りアニメとして表すクラス.*/
///	\include AnimeSample.h
class Anime : public ImagePack
{
private:
	std::vector<unsigned int> times;//コマのフレーム数
	std::vector<int> nexts;//各コマの次フレーム
public:
	/** Animeの再生情報を管理するクラス.*/
	class Player
	{
	private:
		const Anime* anime;//対応アニメ
		int direct = 1;//進行方向
		int frameNumber = 0;//現在のコマ
		double timer = 0;//経過時間
	public:
		
		Player(const Anime* 親アニメ) :
			anime(親アニメ)
		{}

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

			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;
		}
		
		/** 現在のコマ番号を取得.*/
		Image* GetFrame()
		{
			return anime[0][frameNumber];
		}
		
		/** コマの位置を設定.*/
		void SetFrame(int コマ数 )
		{
			this->frameNumber = コマ数;
			timer = 0;
		}
	};
	
	Anime(){};

	Anime(const char *ファイル名, int 総コマ数, int コマ割り横, int コマ割り縦, int 再生フレーム数 = 1) :
		ImagePack( ファイル名 , 総コマ数 ,コマ割り横 , コマ割り縦)
	{
		for( unsigned int i=0; i<times.size() ; ++i )
		{
			times.push_back(再生フレーム数);
			nexts.push_back((int)NextFrame::Normal);
		}
	}
	
	/** 画像ファイルを分割してメモリへ読み込む.*/
	bool Load(const char *ファイル名, int 総コマ数, int コマ割り横, int コマ割り縦, int 再生フレーム数 = 1)
	{
		ImagePack::Load(ファイル名, 総コマ数, コマ割り横, コマ割り縦);
		
		for(int i=0;i<総コマ数;++i)
		{
			times.push_back(再生フレーム数);
			nexts.push_back((int)NextFrame::Normal);
		}
		
		return true;
	}
			
	/** 連番ファイルを一括して読み込む.*/
	bool Load(const char* ファイル名, const char *拡張子, int 総コマ数, int 再生フレーム数 = 1)
	{
		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;
	}

	/** 末尾にImageを追加する。.*/
	void Add(Image *追加イメージ , int 再生フレーム数 = 1)
	{
		ImagePack::Add( 追加イメージ );
		times.push_back(再生フレーム数);
		nexts.push_back( (int)NextFrame::Normal);
	}
	void Add(const char *ファイル名, int 再生フレーム数 = 1)
	{
		Add(new Image(ファイル名), 再生フレーム数);
	}

	/** Imageを開放し初期化する.*/
	void Release()
	{
		ImagePack::Release();
		times.clear();
		nexts.clear();
	}

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

	/** アニメの再生方法を指定する.*/
	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;
		}
	}
	
	/** 指定コマの次フレームを設定する.*/
	void SetType( int コマ番号 , int 次フレーム )
	{
		nexts[コマ番号] = 次フレーム;
	}
	void SetType( int コマ番号 , NextFrame 次フレーム )
	{
		nexts[コマ番号] = (int)次フレーム;
	}

	/** 全コマの合計フレーム時間を返す.*/
	int GetAnimeTime() const
	{
		int totalTime = 0;

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

		return totalTime;
	}

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