#pragma once
#include "Sprite.h"

namespace DXFW
{
/// <summary>説明</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 SpImage : public Sprite
{
private:
	const Image *image;

	SpImage(const SpImage* prototype):
		Sprite( prototype ),
		image(prototype->image)
	{}

public:
	SpImage(const Image &image ):
		image(&image)
	{}
		
	SpImage(const Image *image ):
		image(image)
	{}
	
	Sprite* Clone() const
	{
		return new SpImage( this );
	}

	void Draw( double x , double y , bool isCamera)
	{
		if( isCamera )
		{
			image->DrawRotateAxis( (int)GetX( x , Camera::Now() ) , (int)GetY( y , Camera::Now() ) ,
										(int)(axisX * Camera::Now()->GetZoom() ) + image->GetHeight() / 2, 
										(int)(axisY * Camera::Now()->GetZoom() ) + image->GetHeight() / 2, 
										zoomX * Camera::Now()->GetZoom() ,
										zoomY * Camera::Now()->GetZoom() ,
										angle , isTurn);
		}else{
			image->DrawRotateAxis( (int)GetX( x ) , (int)GetY( y ) ,
										(int)axisX + image->GetHeight() / 2, 
										(int)axisY + image->GetHeight() / 2, 
										zoomX ,
										zoomY ,
										angle , isTurn);
		}
	}
		
};
	
/// <summary>説明</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 SpAnime : public Sprite
{
private:
	Anime &anime;
	Anime::Counter counter;
	double aniSpeed;

	SpAnime(const SpAnime* prototype) :
		Sprite( prototype ),
		anime( prototype->anime ),
		counter( prototype->counter ),
		aniSpeed( prototype->aniSpeed )
	{}
public:

	SpAnime(Anime &anime , double aniSpeed = 1) :
			anime( anime ),
			counter( anime ),
			aniSpeed( aniSpeed )
	{}

	void AnimeUpdate()
	{
		counter.UpDate( aniSpeed );
	};

	Sprite* Clone() const
	{
		return new SpAnime( this );
	}

	void Draw( double x , double y ,bool isCamera)
	{
		if( isCamera )
		{
			anime[counter.GetFrame()]->DrawRotateAxis( (int)GetX( x , Camera::Now()) , (int)GetY( y , Camera::Now()) ,
										(int)(axisX * Camera::Now()->GetZoom()) + anime.GetWidth() / 2, 
										(int)(axisY * Camera::Now()->GetZoom()) + anime.GetHeight() / 2,
										zoomX * Camera::Now()->GetZoom() ,
										zoomY * Camera::Now()->GetZoom(),
										angle ,
										isTurn);
		}
		else
		{
			anime[counter.GetFrame()]->DrawRotateAxis( (int)GetX(x) , (int)GetY(y) ,
										(int)axisX + anime.GetWidth() / 2, 
										(int)axisY + anime.GetHeight() / 2,
										zoomX ,
										zoomY ,
										angle , isTurn);
		}
	}
};
	
/// <summary>説明</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 SpFont : public Sprite
{
private:
	const IFont &font;
	std::string str;
	int rgb;

	SpFont(const SpFont *prototype ):
		Sprite( prototype ),
		font( prototype->font),
		rgb( prototype->rgb ),
		str( prototype->str )
	{}
public:
	SpFont(const IFont &font ,  int rgb  , const char *str ):
		Sprite( ),
		font(font),
		rgb(rgb),
		str(str)
	{}

	Sprite* Clone() const
	{
		return new SpFont( this );
	}
			
	void Draw( double x , double y  ,bool isCamera)
	{
		if( isCamera )
		{
			font.DrawExtend( (int)GetX( x , Camera::Now() ) , (int)GetY( y , Camera::Now() ) , zoomX * Camera::Now()->GetZoom() , zoomY * Camera::Now()->GetZoom() , rgb , str.c_str() );
		}
		else
		{
			font.DrawExtend( (int)GetX( x ) , (int)GetY( y ) , zoomX , zoomY , rgb , str.c_str() );
		}
	}
};

/// <summary>説明</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 SpBmpFrame : public Sprite
{
private:
	const BmpFrame &bmpFrame;
	double width;
	double height;
			
	SpBmpFrame(const SpBmpFrame *prototype ):
		Sprite( prototype ),
		bmpFrame( prototype->bmpFrame),
		width( prototype->width),
		height( prototype->height)
	{}

public:
	SpBmpFrame(const BmpFrame &bmpFrame , double width , double height ):
		Sprite(),
		bmpFrame(bmpFrame),
		width(width),
		height(height)
	{}

	Sprite* Clone() const
	{
		return new SpBmpFrame( this );
	}

	void Draw( double x , double y ,bool isCamera)
	{
		if( isCamera )
		{
			bmpFrame.Draw(	(int)GetX( x , Camera::Now() ) , (int)GetY( y , Camera::Now() ) ,
							(int)(width * zoomX * Camera::Now()->GetZoom()) ,
							(int)(height * zoomY * Camera::Now()->GetZoom()));
		}
		else
		{
			bmpFrame.Draw(	(int)GetX( x ) , (int)GetY( y ) ,
							(int)(width * zoomX) ,
							(int)(height * zoomY) );
		}
	}
};


///<summary>説明</summary>
///拡大縮小に対応可能なマップチップ
class SpMap : public Sprite
{
private:
	ImagePack &chip;
	int width;
	int height;
	int rotate;
	std::vector< std::vector<int> > data;

public:

	SpMap( ImagePack& マップチップ , const char* ディレクトリ名 , const char* ファイル名 , int 幅 , int 高さ , int 角度):
		width(幅),
		height(高さ),
		rotate(角度),
		chip(マップチップ)
	{
		File::SetDirectory( ディレクトリ名  );
		File csvFile( ファイル名 , FileMode::Read );

		data.resize( 幅 );

		for(int i=0 ; i<幅 ;i++)
		{
			data[i].resize( 高さ );
		}

		std::vector<std::string> lineBuf;

		for(int i = 0 ; i < 高さ ; i++ )
		{
			csvFile.GetLineCSV( lineBuf );
			for( int j = 0 ; j < 幅 ; j++)
			{
				data[j][i] = atoi( lineBuf[j].c_str() );
			}
			lineBuf.clear();
		}
	}

	void Draw( double X座標 , double Y座標 ,bool カメラ有りフラグ)
	{
		const int chipW = chip.GetWidth();
		const int chipH = chip.GetHeight();

		if( カメラ有りフラグ )
		{
			const int baseY = int(Camera::Now()->TranY( Y座標 ));
			const int baseX = int(Camera::Now()->TranX( X座標 ));
			
			int posXA;
			int posYA;
			int posXB;
			int posYB;

			for(int i=0 ; i<width ; ++i )
			{
				posXA = int( baseX + chipW * i * Camera::Now()->GetZoom() );
				posXB = int( baseX + chipW * (i+1) * Camera::Now()->GetZoom() );

				for(int j=0 ; j<height ; ++j )
				{
					posYA = int( baseY + chipH * j * Camera::Now()->GetZoom() );
					posYB = int( baseY + chipH * (j+1) * Camera::Now()->GetZoom() );
					const int no = data[i][j];
					if( no == 0 ) continue;
					chip[no]->DrawExtend( posXA , posYA , posXB , posYB );
				}
			}
		}else{
			for(int i=0 ; i<width ; ++i )
			{
				for(int j=0 ; j<height ; ++j )
				{
					const int no = data[i][j];
					if( no == 0 ) continue;
					chip[no]->Draw( int(X座標 + i*chipW) , int(Y座標 + j*chipH) );
				}
			}
		}
	}

};

}