#include <mof/particlegen.hpp>
#include <mof/Board.hpp>
#include <mof/utilities.hpp>
#include <mof/streams.hpp>
#include <mof/ConsoleIO.hpp>
#include <list>


namespace mof
{
//{{{ impl
	struct particlegen::impl
	{
		Texture::ptr texture_;
		Matrix3DStream world_transform_;
		Manipulator<Matrix3D>::ptr particle_transform_;
		Manipulator<Color4f>::ptr particle_color_;
		std::list<Board*> particles_;
		frame_t frame_;///< パーティクルの生成寿命管理

		impl()
			: texture_(std::make_shared<Texture>("image/light.dds")), frame_(0)
		{
		}

		~impl()
		{
			foreach (auto particle, particles_) {
				delete particle;
			}
		}
//{{{ add_particle
		void add_particle()
		{
			auto p = std::unique_ptr<Board>(new Board());
			p->setTexture(texture_);
			
			// 初期位置をgeneratorの位置とする
			auto pos = world_transform_.value();
			Manipulator<Matrix3D>::ptr tweens[] = {particle_transform_, makeConstantHandler(pos)};
			auto t = makeCascadeHandler<Matrix3D>(tweens[0], lastOf(tweens));
			p->world_transform() << t;
			
			p->getColorStream() << particle_color_;
			particles_.push_back(p.release());
		}
//}}}
	};
//}}}
//{{{ constructor
	particlegen::particlegen()
		: pimpl_(new impl())
	{
		{
			Scaling3D::keyframe_t keyframes1[] = 
				{
					makeKeyFrame(0, Vector3D(0, 0, 0)),
					makeKeyFrame(50, Vector3D(0.25f, 0.25f, 0.25f)),
					makeKeyFrame(200, Vector3D(0.5f, 0.5f, 0.5f)),
				};
			auto tw1 = std::make_shared<Scaling3D>(keyframes1[0], lastOf(keyframes1));

			Translation3D::keyframe_t keyframes2[] = 
				{
					makeKeyFrame(0, Vector3D(0, 0, 0)),
					makeKeyFrame(500, Vector3D(0, 1.5, 0)),
				};
			auto tw2 = std::make_shared<Translation3D>(keyframes2[0], lastOf(keyframes2));

			Manipulator<Matrix3D>::ptr tweens[] = {tw1, tw2};
			pimpl_->particle_transform_ = makeCascadeHandler<Matrix3D>(tweens[0], lastOf(tweens));
		}
		
		{
			KeyFrameAnimation<Color4f>::KeyFrame keyframes[] = 
				{
					makeKeyFrame(0, Color4f(0, 1, 1, 0)),
					makeKeyFrame(200, Color4f(1, 0, 1, 0)),
					makeKeyFrame(400, Color4f(0, 0, 1, 0)),
				};
			pimpl_->particle_color_ = 
				makeKeyFrameAnimationHandler<Color4f>(keyframes[0], lastOf(keyframes));
		}

	}
//}}}
//{{{ destructor
	particlegen::~particlegen()
	{
	}
//}}}
//{{{ world_transform
	const Matrix3DStream& particlegen::world_transform() const
	{
		return pimpl_->world_transform_;
	}
//}}}
//{{{ world_transform
	Matrix3DStream& particlegen::world_transform()
	{
		return pimpl_->world_transform_;
	}
//}}}
//{{{ update
	void particlegen::update()
	{
		if (pimpl_->frame_++ % 20 == 0) {
			pimpl_->add_particle();
			if (pimpl_->frame_ > 500) {
				delete pimpl_->particles_.front();
				pimpl_->particles_.pop_front();// 寿命は500
			}
		}

		pimpl_->world_transform_.update();
		foreach (auto p, pimpl_->particles_) p->update();
	}
//}}}
//{{{ drawables
	const std::list<Board*>& particlegen::drawables() const
	{
		return pimpl_->particles_;
	}
//}}}
}// namespace mof
