#pragma once
#include <mof/script/ObjectData.hpp>
#include <boost/intrusive/set.hpp>
#include <boost/intrusive/list.hpp>

namespace mof
{
	class Drawable;

namespace script
{
//{{{
	// renderable
	class rendering_packet
	{
		const mof::Drawable* drawable_;
		//boost::function<void (void)>& draw_func_;

		std::shared_ptr<mof::Light> light_;
		int priority_;     // 小さい程先に描画される
		int sub_priority_;// priorityが等しければ、こちらで判定する
		float z_order_;   // 小さい程先に描画される
		bool z_buffer_;   // Zバッファを使うかどうか
		bool is_enable_;//!< オブジェクトが更新されるかどうか

	public:
		typedef boost::intrusive::set_member_hook<boost::intrusive::link_mode<boost::intrusive::auto_unlink>> queue_hook_t;
		typedef boost::intrusive::list_member_hook<boost::intrusive::link_mode<boost::intrusive::auto_unlink>> dead_hook_t;
		queue_hook_t queue_hook_;
		dead_hook_t dead_hook_;

		rendering_packet
		(
			const mof::Drawable* drawable,
			int priority,
			bool z_buffer,
			float z_order = 0
		)
			: drawable_(drawable), priority_(priority), sub_priority_(0),
			  z_buffer_(z_buffer), z_order_(z_order), is_enable_(true)
		{
			// sub priority計算
			if (!z_buffer_) {
				// Zソートのオブジェクトは後で描画
				sub_priority_ += 1000;
			}
		}

		inline bool operator <(const rendering_packet& packet) const
		{
			if (priority_ < packet.priority_) return true;
			else if (priority_ > packet.priority_) return false;

			// 優先度が同じ場合
			if (sub_priority_ < packet.sub_priority_) return true;
			else if (sub_priority_ > packet.sub_priority_) return false;

			// Zソート
			return z_order_ < packet.z_order_;
		}

		inline bool& enable() 
		{
			return is_enable_;
		}
			
		inline const bool& enable() const
		{
			return is_enable_;
		}

		inline void draw() const
		{
			if(!is_enable_)
			{
				// 有効でないオブジェクトは描画されない
				return;
			}

			// Zバッファを使うかどうか
			if (z_buffer_) GraphicsDevice::setZBuffer(true);
			else GraphicsDevice::setZBuffer(false);

			if (light_) {
				// ライトが設定されていれば、それを使う
				mof::GraphicsDevice::lightEnable(true);
				light_->setEnable(true);
			}
			else {
				mof::GraphicsDevice::lightEnable(false);
			}
			
			drawable_->draw();
		}

		inline std::shared_ptr<mof::Light>& light()
		{
			return light_;
		}

		// TODO z_oerder_

	};
//}}}
}
}
