#pragma once
#include <mof/script/CommandSet.hpp>
#include <mof/script/ObjectData.hpp>
#include <mof/ResourceManager.hpp>
#include <memory>
#include <vector>
	
namespace mof
{
	class InputReceiver;
	class Texture;
	class MeshBuilder;

namespace script
{

	class Environment : public CommandSet
	{
	public:
		
		Environment
		(
			std::shared_ptr<mof::InputReceiver> input,
			const ResourceManager<Texture>::ptr& texture_manager,
			const ResourceManager<MeshBuilder>::ptr& mesh_builder_manager
		);

		virtual ~Environment();

		virtual int message_create(unsigned int thread_id, const mof::tstring& title, const GameData::entry_t& style, int priority);
		
		virtual int message_next(int id, const tstring& text);
	   
		virtual void wait_for_key(size_t id, mof::InputReceiver::Key key);
		
		virtual mof::InputReceiver::Key get_last_key();
		
		virtual void wait_frame(size_t id, size_t frame);

		virtual void routine_stop(unsigned int thread_id);

		virtual int menu_create(unsigned int thread_id, const mof::tstring& title, const std::vector<mof::tstring>& items, const GameData::entry_t& style, int priority);

		virtual int vertex_buffer_create
		(
		 	unsigned int thread_id, 
			const mof::VertexXYZRHWCUV& front,
			const mof::VertexXYZRHWCUV& back,
			const mof::Texture::ptr& texture,
			int priority
		);

		virtual int menu_move_cursor(int id, MoveDirection direction);
		
		virtual int menu_select(int id);
		
		virtual int menu_get_current(int id);
		
		virtual int sound_create(const mof::tstring& filepath);
		
		virtual void sound_play(int id);

		virtual int music_create(const mof::tstring& filepath);
		
		virtual void music_play(int id);

		virtual void music_pause(int id);
		
		virtual GameData::ptr load_game_data(const mof::tstring& resource_path);

		virtual void save_game_data(const mof::tstring& resource_path, const GameData::ptr& game_data);

		virtual void print_debug(const mof::tstring& message);

		virtual int picture_create(unsigned int thread_id, const mof::tstring& filepath, int priority);
		
		virtual int camera_create();
		
		virtual int particlegen_create(unsigned int thread_id);
		
		virtual int solid_create(unsigned int thread_id, const mof::tstring& class_path, int priority);
		
		virtual int light_create(unsigned int thread_id, const mof::tstring& class_path);
		
		virtual void set_light(int id, int light_id);

		virtual int board_create(unsigned int thread_id, const mof::tstring& filepath, const GameData::entry_t& style, int priority);
		
		// 共通のメソッド
		virtual int show(int id, const mof::tstring& class_path);
		
		virtual int hide(int id, const mof::tstring& class_path);
		
		virtual void dispose(int id, const mof::tstring& class_path);

		virtual void set_enable(int id, bool is_enable, const mof::tstring& class_path);
		
		virtual GameData::ptr get_properties(int id, const mof::tstring& class_path);

		virtual void set_color_behavior(int id, const mof::tstring& class_path, const Manipulator<Color4f>::ptr& seq, mof::FrameNumber period);
		
		virtual void set_position_behavior(int id, const mof::tstring& class_path, const Manipulator<Vector2D>::ptr& seq, mof::FrameNumber period);
		
		virtual void set_position_behavior(int id, const mof::tstring& class_path, const Manipulator<Vector3D>::ptr& seq);
		
		virtual void set_camera_behavior(int id, const mof::tstring& class_path, const Manipulator<Vector3D>::ptr& seq);
		
		virtual void set_size_behavior(int id, const mof::tstring& class_path, const Manipulator<Vector2D>::ptr& seq, mof::FrameNumber period);
		
		virtual void set_size_behavior(int id, const mof::tstring& class_path, const Manipulator<Vector3D>::ptr& seq);
		
		virtual void set_rotate_behavior(int id, const mof::tstring& class_path, const Manipulator<Vector3D>::ptr& seq);

		virtual void set_texture_coord_tween
		(
			int id,
			const mof::tstring& class_path, 
			const Manipulator<mof::Rectangle<float>>::ptr& seq
		);
		
		virtual void joint(int id1, const mof::tstring& class_name1, const mof::tstring& joint_type, int id2, const mof::tstring& class_name2);

		virtual void quit();

		void update();

		void draw() const;

		bool is_waiting(size_t id) const;

	protected:	
		virtual std::unique_ptr<MessageData> 
		create_message_data
		(
			const mof::tstring& title, const GameData::entry_t& style
		) = 0;

		virtual std::unique_ptr<MenuData> 
		create_menu_data
		(
			const mof::tstring& title, const std::vector<mof::tstring>& items, const GameData::entry_t& style
		) = 0;

		virtual GameData::ptr get_game_data(const mof::tstring& class_path) = 0;
		
		virtual void set_game_data(const mof::tstring& resource_path, const GameData::ptr& game_data) = 0;

		virtual std::shared_ptr<Graphics3D> create_solid(const mof::tstring& class_path) = 0;
		

	private:
		struct Impl;
		std::unique_ptr<Impl> impl_;
	};

}
}

