#pragma once
#include"Sprite.h"
#include"Figure.h"
#include"Camera.h"
#include"Sprite派生.h"
#include<memory>

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 Model
{
private:
	double zoomX;
	double zoomY;
	double angle;
	double shadowSize;
	bool isCamera;
public:
	std::vector<std::shared_ptr<Sprite>> sprites;			
	std::unique_ptr<Figure> figure;

	Model( Figure *figure , Sprite *sprite ):				
		zoomX(1),
		zoomY(1),
		angle(0),
		isCamera(true),
		shadowSize(1),
		figure(figure)
	{
		if( sprite )sprites.emplace_back(sprite);
	}

	virtual void Draw() const
	{
		for( auto it : sprites )
		{
			if( !it->isVisible ) continue;
			if( !it->isAllway && it->isActive ) continue;

			if( it->GetAlpha() >= 255 )
			{
				it->Draw( GetX() , GetY() , isCamera && Camera::Now() ); 
			}
			else if( it->GetAlpha() > 0 )
			{
				Screen::SetBlendMode( BlendMode::Alpha , it->GetAlpha() );
				it->Draw( GetX() , GetY() , isCamera && Camera::Now() );
				Screen::SetBlendMode( BlendMode::NoBlend , 0 );
			}
		}
	}

	void DrawShadow( double X座標ずれ , double Y座標ずれ )
	{
		if( shadowSize <= 0 ) return;

		X座標ずれ *= shadowSize;
		Y座標ずれ *= shadowSize;

		for( auto it : sprites )
		{
			if( !it->isVisible ) continue;
			if( !it->isAllway && it->isActive ) continue;

			if( it->GetAlpha() >= 255 )
			{
				double zoomX = it->zoomX;
				double zoomY = it->zoomY;
				it->zoomX *= shadowSize;
				it->zoomY *= shadowSize;
				it->Draw( GetX() + X座標ずれ , GetY() + Y座標ずれ , isCamera && Camera::Now() ); 
				it->zoomX = zoomX;
				it->zoomY = zoomY;
			}
		}

	}

	void AnimeUpdate()
	{
		for(auto it: sprites )
		{
			it->AnimeUpdate();
		}
	}

	void Move(double x , double y)
	{
		figure->Move( x , y );
	}
			
	void MovePolar(double distance , double angle)
	{
		figure->Move( distance * cos(angle) , distance * sin(angle) );
	}

	void SetPos(double x , double y)
	{				
		figure->SetPos( x , y );
	}

	void SetZoom(double rate )
	{
		zoomX *= rate;
		zoomY = rate;
	}

	void SetZoom(double rateX , double rateY)
	{
		figure->MultiZoom( rateX / zoomX , rateY / zoomY );

		for( auto it : sprites )
		{
			//it->SetZoom( rateX , rateY );
		}

		zoomX = rateX;
		zoomY = rateY;
	}

	void MultiZoom(double rate )
	{
		zoomX *= rate;
		zoomY *= rate;
	}

	void MultiZoom(double rateX , double rateY)
	{
		zoomX *= rateX;
		zoomY *= rateY;
	}

	void Rotate( double angle )
	{
		this->angle += angle;

		for( auto it : sprites )
		{
			it->Rotate( angle );
		}
	}

	double GetAngle()
	{
		return angle;
	}

	void SetAngle( double angle )
	{
		for( auto it : sprites )
		{
			it->Rotate( angle - this->angle );
		}
		this->angle = angle;
	}

	void SetActive(int index)
	{
		for(unsigned int i=0; i<sprites.size() ;i++)
		{
			sprites[i]->isActive = ( i == index );
		}
	}

	double GetZoomX()
	{
		return this->zoomX;
	}

	double GetZoomY()
	{
		return this->zoomY;
	}

	double GetX() const
	{
		return figure->GetX();
	}

	double GetY() const
	{
		return figure->GetY();
	}

	bool Hit( Model *model)
	{
		return figure->Hit( model->figure.get() );
	}

	bool Hit( Figure *figure)
	{
		return figure->Hit( figure );
	}

	bool Hit( Mouse &mouse , Camera *camera = nullptr)
	{
		Point pt;

		if( camera )
		{
			pt.x = camera->TranX( Input::mouse.x + camera->GetCenterX() );
			pt.y = camera->TranY( Input::mouse.y + camera->GetCenterY() );
		}else{
			pt.x = mouse.x;
			pt.y = mouse.y;

		}

		return figure->Hit( &pt );	
	}

	double GetDirect(Model* model)
	{
		return atan2( figure->GetY() -  this->GetY(), figure->GetX() - this->GetX() );
	}
	double GetDirect(Figure* figure)
	{
		return atan2( figure->GetY() -  this->GetY(), figure->GetX() - this->GetX() );
	}

	double GetDistance(Figure* figure)
	{
		const double xd = this->GetX() - figure->GetX();
		const double yd = this->GetY() - figure->GetY();

		return sqrt( xd * xd + yd * yd );
	}
	double GetDistance(Model* figure)
	{
		const double xd = this->GetX() - figure->GetX();
		const double yd = this->GetY() - figure->GetY();

		return sqrt( xd * xd + yd * yd );
	}
};
}