#ifndef _RUENTITYPAPERDOLL_H_
#define _RUENTITYPAPERDOLL_H_

#include "../../Core/Collection/RuCollectionsTree.h"

#include "../../Scene/Paperdoll/RuEntityCompositeModel.h"

#pragma unmanaged

// ************************************************************************************************************************************************************

class CRuPaperdoll;

// ************************************************************************************************************************************************************
class CRuPaperdollTemplate : public IRuObject
{
	ruRTTI_DECLARE
	ruHEAP_DECLARE
	ruCLASSGUID_DECLARE

protected:
	struct ColorCode
	{
		INT32								m_color0Code;					//!< Color 0 = skin color
		INT32								m_color1Code;					//!< Color 1 = hair color
	};

	struct Item
	{
		CRuString							m_itemPrefix;					//!< Item prefix to use when generating resource names for textures
		CRuArrayList<ColorCode>				m_validColorCodes;				//!< List of valid color codes
	};

	struct BaseItem
	{
		// Base item information
		CRuString							m_baseItemPrefix;				//!< Item prefix to use when generating resource names for part models
		CRuArrayList<const char *>			m_validBaseItemCodes;			//!< List of item codes available for this base item

		// Derived item information
		CRuBinaryTree<CRuString, Item *>	m_items;						//!< Tree of items that derive from this base item
	};

	struct Part
	{
		INT32								m_partID;						//!< Part ID
		CRuBinaryTree<CRuString, BaseItem *>m_baseItems;					//!< Tree of items belonging to this part
	};

	// Internal settings
	CRuString								m_resourceNamePrefix;			//!< Prefix to use when generating resource names for part models
	CRuString								m_resourceNamePostfix;			//!< Postfix to use when generating resource names for part models

	CRuString								m_baseItemResourcePath;			//!< Default resource path for base items
	CRuString								m_itemResourcePath;				//!< Default resource path for items

	// Template data
	CRuCompositeModelTemplate*				m_modelTemplate;				//!< Source template for the paperdoll
	CRuArrayList<Part *>					m_parts;						//!< Parts list

public:
											CRuPaperdollTemplate();
	virtual									~CRuPaperdollTemplate();

	// IRuObject serialization
	virtual BOOL							SerializeFrom(IRuStream *stream);
	virtual BOOL							SerializeTo(IRuStream *stream);

	// Initialization
	BOOL									Initialize(CRuCompositeModelTemplate *modelTemplate);

	// Template management
	const char*								GetBaseItemResourcePath() const;
	void									SetBaseItemResourcePath(const char *baseItemResourcePath);
	const char*								GetItemResourcePath() const;
	void									SetItemResourcePath(const char *itemResourcePath);

	BOOL									AddBaseItem(INT32 partID, const char *baseItemName, const char *baseItemCode, const char *baseItemPrefix);
	BOOL									AddItem(const char *partName, const char *baseItemName, const char *itemName, const char *itemPrefix, INT32 color0Code, INT32 color1Code);

	// Template query
	INT32									GetNumParts() const;
	INT32									GetPartIndex(INT32 partID) const;
	INT32									GetPartIndex(const char *partName) const;
	INT32									GetPartID(INT32 partIndex) const;
	INT32									GetPartID(const char *partName) const;
	const char*								GetPartName(INT32 partIndex) const;

	INT32									GetNumBaseItems(INT32 partIndex) const;
	const char*								GetBaseItemName(INT32 partIndex, INT32 baseItemIndex) const;
	const char*								GetBaseItemPrefix(INT32 partIndex, INT32 baseItemIndex) const;
	char*									GetBaseItemCodesAsString(INT32 partIndex, INT32 baseItemIndex) const;

	INT32									GetNumItems(INT32 partIndex, INT32 baseItemIndex) const;
	const char*								GetItemName(INT32 partIndex, INT32 baseItemIndex, INT32 itemIndex) const;
	char*									GetItemColorCodesAsString(INT32 partIndex, INT32 baseItemIndex, INT32 itemIndex) const;

	// Paperdoll interface
	CRuPaperdoll*							Construct();
	CRuEntity*								FindSuitableItem(INT32 partIndex, const char *itemName, const CRuArrayList<const char *> &acceptableItemCodeList, INT32 color0Code, INT32 color1Code, const char **itemCodeOut) const;
	CRuEntity*								FindSuitableItem(INT32 partIndex, const char *itemName, const CRuArrayList<const char *> &acceptableItemCodeList, const char *baseItemKeyOverride, INT32 color0Code, INT32 color1Code, const char **baseItemKeyOut, const char **itemCodeOut) const;
};

// ************************************************************************************************************************************************************

class CRuPaperdoll : public CRuEntity
{
	ruRTTI_DECLARE
	ruHEAP_DECLARE
	ruCLASSGUID_DECLARE

protected:
	struct ComponentDesc
	{
		BOOL								m_layerActivated[4];
		RUCOLOR								m_layerColor[4];

											ComponentDesc()
											{
												for(INT32 i = 0; i < 4; ++i)
												{
													m_layerActivated[i] = FALSE;
													m_layerColor[i] = 0xFFFFFFFF;
												}
											}
	};

	CRuPaperdollTemplate*					m_paperdollTemplate;					//!< Source paperdoll template
	CRuCompositeModel*						m_paperdollModel;						//!< Constructed paperdoll model

	INT32									m_color0Code;							//!< Color 0 code (skin color)
	INT32									m_color1Code;							//!< Color 1 code (hair color)
	CRuArrayList<CRuString>					m_components;							//!< Items worn on the paperdoll
	CRuArrayList<CRuEntity *>				m_componentEntities;					//!< Resolved item entities
	CRuArrayList<const char *>				m_componentItemCodes;					//!< Resolved item codes
	CRuArrayList<ComponentDesc *>			m_componentDescriptors;

public:
											CRuPaperdoll();
	virtual									~CRuPaperdoll();

	// Paperdoll query
	CRuPaperdollTemplate*					GetPaperdollTemplate();

	// Paperdoll composition
	void									SetColorCodes(INT32 color0Code, INT32 color1Code);
	BOOL									SetComponent(const char *partName, const char *itemName);
	BOOL									SetComponent(INT32 partIndex, const char *itemName);
	BOOL									SetComponentColors(const char *partName, const BOOL *layerActivated, const RUCOLOR *layerColor);
	BOOL									SetComponentColors(INT32 partIndex, const BOOL *layerActivated, const RUCOLOR *layerColor);
	BOOL									BuildPaperdoll();

	friend									CRuPaperdollTemplate;
};

// ************************************************************************************************************************************************************

class CRuPlayerPaperdoll : public IRuEntity_Renderable
{
	ruRTTI_DECLARE
	ruHEAP_DECLARE
	ruCLASSGUID_DECLARE

protected:
	CRuPaperdoll*							m_paperdoll;							// Original paperdoll

public:
											CRuPlayerPaperdoll();
	virtual									~CRuPlayerPaperdoll();
};

// ************************************************************************************************************************************************************

ruOBJECTMODULE_DEFINE(CRuObjectModule_PaperdollTemplate, CRuPaperdollTemplate)

// ************************************************************************************************************************************************************

#pragma managed

#endif
