#pragma once
#include <memory>
#include <vector>
#include <list>
#include <map>
#include <mof/tstring.hpp>
#include <mof/Board.hpp>
#include <mof/VertexBuffer.hpp>
#include <mof/MeshBuilder.hpp>
#include <mof/Graphics3D.hpp>
#include <mof/particlegen.hpp>
#include <mof/stream/ReferenceWrapper.hpp>

namespace mof
{
	class Sprite;
	class particlegen;
	class Graphics3D;
	class Camera;
	class Light;
	class StaticSoundBuffer;
	class StreamSoundBuffer;

namespace widget
{
	class Pager;
	class Menu;
	class Frame;
	class WidgetView;
}
	class SoundBuffer;

namespace script
{
	class rendering_packet;

//{{{ MessageData
		struct MessageData
		{
			std::shared_ptr<mof::widget::WidgetView> view_;// Drawer
			std::shared_ptr<mof::widget::Pager> message_;
			std::shared_ptr<mof::widget::Frame> frame_;
			rendering_packet* r_packet_;
			bool is_enable_;//!< オブジェクトが有効かどうか
			unsigned int thread_id_;//!< コルーチンのID
		};
//}}}	
//{{{ MenuData
		struct MenuData
		{
			std::shared_ptr<mof::widget::WidgetView> view_;// Drawer
			std::shared_ptr<mof::widget::Menu> menu_;
			std::shared_ptr<mof::widget::Frame> frame_;
			rendering_packet* r_packet_;
			bool is_enable_;//!< オブジェクトが有効かどうか
			unsigned int thread_id_;//!< コルーチンのID
		};
//}}}
//{{{ PictureData
		struct PictureData
		{
			std::shared_ptr<mof::Sprite> sprite_;
			ReferenceWrapper<Rectangle<float>> texcoord_ref_;
			typedef std::shared_ptr<PictureData> ptr;
			rendering_packet* r_packet_;
			bool is_enable_;//!< オブジェクトが有効かどうか
			unsigned int thread_id_;//!< コルーチンのID
		};
//}}}	
//{{{ vertex_buffer_obj
		class vertex_buffer_with_texture : public Drawable
		{
		public:
			std::shared_ptr<mof::VertexBuffer<VertexXYZRHWCUV>> buffer_;
			mof::Texture::ptr texture_;

			virtual void draw() const
			{
				mof::GraphicsDevice::setTexture(texture_.get());
				buffer_->draw();
			}

			virtual void setVisible(bool) {}
		};

		struct vertex_buffer_obj
		{
			std::shared_ptr<vertex_buffer_with_texture> vb_;
			typedef std::shared_ptr<vertex_buffer_obj> ptr;
			rendering_packet* r_packet_;
			bool is_enable_;//!< オブジェクトが有効かどうか
			unsigned int thread_id_;//!< コルーチンのID
		};
//}}}
//{{{ BoardData
		struct BoardData
		{
			std::shared_ptr<mof::Board> board_;
			rendering_packet* r_packet_;
			ReferenceWrapper<Matrix3D> position_ref_;
			ReferenceWrapper<Matrix3D> size_ref_;
			ReferenceWrapper<Matrix3D> rotate_ref_;
			ReferenceWrapper<Color4f> color_ref_;
			ReferenceWrapper<Rectangle<float>> texcoord_ref_;
			typedef std::shared_ptr<BoardData> ptr;
			bool is_enable_;//!< オブジェクトが有効かどうか
			unsigned int thread_id_;//!< コルーチンのID
		};
//}}}
//{{{ ParticlegenData	
		struct ParticlegenData
		{
			mof::particlegen::ptr particlegen_;
			ReferenceWrapper<Matrix3D> position_ref_;
			typedef std::shared_ptr<ParticlegenData> ptr;
			bool is_enable_;//!< オブジェクトが有効かどうか
			unsigned int thread_id_;//!< コルーチンのID
		};
//}}}
//{{{ SolidData
		struct SolidData
		{
			std::shared_ptr<mof::Graphics3D> solid_;
			rendering_packet* r_packet_;
			ReferenceWrapper<Matrix3D> position_ref_;
			ReferenceWrapper<Matrix3D> size_ref_;
			ReferenceWrapper<Matrix3D> rotate_ref_;
			typedef std::shared_ptr<SolidData> ptr;
			bool is_enable_;//!< オブジェクトが有効かどうか
			unsigned int thread_id_;//!< コルーチンのID
		};
//}}}	
//{{{ CameraData
		struct CameraData
		{
			std::shared_ptr<Camera> camera_;
			typedef std::shared_ptr<CameraData> ptr;
		};
//}}}
//{{{ light_obj
		struct light_obj
		{
			std::shared_ptr<Light> light_;
			mof::tstring type_;
			unsigned int thread_id_;//!< コルーチンのID

			typedef std::shared_ptr<light_obj> ptr;
		};
//}}}
//{{{ StaticSoundData
		struct StaticSoundData
		{
			std::shared_ptr<mof::StaticSoundBuffer> sound_;
		};
//}}}
//{{{ StreamSoundData
		struct StreamSoundData
		{
			std::shared_ptr<mof::StreamSoundBuffer> sound_;
			// TODO tween
		};
//}}}
//{{{ SoundSourceData
		struct SoundSourceData
		{
			std::shared_ptr<mof::StaticSoundBuffer> source_;
			// TODO tween
		};
//}}}
//{{{ GameData
		struct GameData // TODO rename
		{
			std::vector<std::map<mof::tstring, mof::tstring>> data_;
			typedef std::shared_ptr<GameData> ptr;
			typedef std::map<mof::tstring, mof::tstring> entry_t;
			typedef std::pair<mof::tstring, mof::tstring> pair_t;

			friend std::ostream& operator <<(std::ostream& os , const GameData& obj);
		};
//}}}
}// namespace script
}// namespace mof
