/** 
 * @file llavatarappearancedefines.h
 * @brief Various LLAvatarAppearance related definitions
 * LLViewerObject
 *
 * $LicenseInfo:firstyear=2001&license=viewerlgpl$
 * Second Life Viewer Source Code
 * Copyright (C) 2010, Linden Research, Inc.
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation;
 * version 2.1 of the License only.
 * 
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 * 
 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 * $/LicenseInfo$
 */

#ifndef LL_AVATARAPPEARANCE_DEFINES_H
#define LL_AVATARAPPEARANCE_DEFINES_H

#include <vector>
#include "lljointpickname.h"
#include "lldictionary.h"
#include "llwearabletype.h"
#include "lluuid.h"

namespace LLAvatarAppearanceDefines
{

extern const S32 SCRATCH_TEX_WIDTH;
extern const S32 SCRATCH_TEX_HEIGHT;

static const U32 AVATAR_HOVER = 11001;

//--------------------------------------------------------------------
// Enums
//--------------------------------------------------------------------
enum ETextureIndex
{
	TEX_INVALID = -1,
	TEX_HEAD_BODYPAINT = 0,
	TEX_UPPER_SHIRT,
	TEX_LOWER_PANTS,
	TEX_EYES_IRIS,
	TEX_HAIR,
	TEX_UPPER_BODYPAINT,
	TEX_LOWER_BODYPAINT,
	TEX_LOWER_SHOES,
	TEX_HEAD_BAKED,		// Pre-composited
	TEX_UPPER_BAKED,	// Pre-composited
	TEX_LOWER_BAKED,	// Pre-composited
	TEX_EYES_BAKED,		// Pre-composited
	TEX_LOWER_SOCKS,
	TEX_UPPER_JACKET,
	TEX_LOWER_JACKET,
	TEX_UPPER_GLOVES,
	TEX_UPPER_UNDERSHIRT,
	TEX_LOWER_UNDERPANTS,
	TEX_SKIRT,
	TEX_SKIRT_BAKED,	// Pre-composited
	TEX_HAIR_BAKED,     // Pre-composited
	TEX_LOWER_ALPHA,
	TEX_UPPER_ALPHA,
	TEX_HEAD_ALPHA,
	TEX_EYES_ALPHA,
	TEX_HAIR_ALPHA,
	TEX_HEAD_TATTOO,
	TEX_UPPER_TATTOO,
	TEX_LOWER_TATTOO,
	TEX_HEAD_UNIVERSAL_TATTOO,
	TEX_UPPER_UNIVERSAL_TATTOO,
	TEX_LOWER_UNIVERSAL_TATTOO,
	TEX_SKIRT_TATTOO,
	TEX_HAIR_TATTOO,
	TEX_EYES_TATTOO,
	TEX_LEFT_ARM_TATTOO,
	TEX_LEFT_LEG_TATTOO,
	TEX_AUX1_TATTOO,
	TEX_AUX2_TATTOO,
	TEX_AUX3_TATTOO,
	TEX_LEFT_ARM_BAKED,		 // Pre-composited
	TEX_LEFT_LEG_BAKED,     // Pre-composited
	TEX_AUX1_BAKED,			 // Pre-composited
	TEX_AUX2_BAKED,			 // Pre-composited
	TEX_AUX3_BAKED,			 // Pre-composited
	TEX_NUM_INDICES
}; 

enum EBakedTextureIndex
{
	BAKED_HEAD = 0,
	BAKED_UPPER,
	BAKED_LOWER,
	BAKED_EYES,
	BAKED_SKIRT,
	BAKED_HAIR,
	BAKED_LEFT_ARM,
	BAKED_LEFT_LEG,
	BAKED_AUX1,
	BAKED_AUX2,
	BAKED_AUX3,
	BAKED_NUM_INDICES
};

// Reference IDs for each mesh. Used as indices for vector of joints
enum EMeshIndex
{
	MESH_ID_HAIR = 0,
	MESH_ID_HEAD,
	MESH_ID_EYELASH,
	MESH_ID_UPPER_BODY,
	MESH_ID_LOWER_BODY,
	MESH_ID_EYEBALL_LEFT,
	MESH_ID_EYEBALL_RIGHT,
	MESH_ID_SKIRT,
	MESH_ID_NUM_INDICES
};

//--------------------------------------------------------------------
// Vector Types
//--------------------------------------------------------------------
typedef std::vector<ETextureIndex> texture_vec_t;
typedef std::vector<EBakedTextureIndex> bakedtexture_vec_t;
typedef std::vector<EMeshIndex> mesh_vec_t;
typedef std::vector<LLWearableType::EType> wearables_vec_t;

//------------------------------------------------------------------------
// LLAvatarAppearanceDictionary
// 
// Holds dictionary static entries for textures, baked textures, meshes, etc.; i.e.
// information that is common to all avatars.
// 
// This holds const data - it is initialized once and the contents never change after that.
//------------------------------------------------------------------------
class LLAvatarAppearanceDictionary
{
	//--------------------------------------------------------------------
	// Constructors and Destructors
	//--------------------------------------------------------------------
public:
	LLAvatarAppearanceDictionary();
	~LLAvatarAppearanceDictionary();
private:
	void createAssociations();
	
	//--------------------------------------------------------------------
	// Local and baked textures
	//--------------------------------------------------------------------
public:
	struct TextureEntry : public LLDictionaryEntry
	{
		TextureEntry(const std::string &name, // this must match the xml name used by LLTexLayerInfo::parseXml
					 bool is_local_texture, 
					 EBakedTextureIndex baked_texture_index = BAKED_NUM_INDICES,
					 const std::string& default_image_name = "",
					 LLWearableType::EType wearable_type = LLWearableType::WT_INVALID);
		const std::string 	mDefaultImageName;
		const LLWearableType::EType mWearableType;
		// It's either a local texture xor baked
		BOOL 				mIsLocalTexture;
		BOOL 				mIsBakedTexture;
		// If it's a local texture, it may be used by a baked texture
		BOOL 				mIsUsedByBakedTexture;
		EBakedTextureIndex 	mBakedTextureIndex;
	};

	struct Textures : public LLDictionary<ETextureIndex, TextureEntry>
	{
		Textures();
	} mTextures;
	const TextureEntry*		getTexture(ETextureIndex index) const { return mTextures.lookup(index); }
	const Textures&			getTextures() const { return mTextures; }
	
	//--------------------------------------------------------------------
	// Meshes
	//--------------------------------------------------------------------
public:
	struct MeshEntry : public LLDictionaryEntry
	{
		MeshEntry(EBakedTextureIndex baked_index, 
				  const std::string &name, // names of mesh types as they are used in avatar_lad.xml
				  U8 level,
				  LLJointPickName pick);
		// Levels of Detail for each mesh.  Must match levels of detail present in avatar_lad.xml
        // Otherwise meshes will be unable to be found, or levels of detail will be ignored
		const U8 						mLOD;
		const EBakedTextureIndex 		mBakedID;
		const LLJointPickName 	mPickName;
	};

	struct MeshEntries : public LLDictionary<EMeshIndex, MeshEntry>
	{
		MeshEntries();
	} mMeshEntries;
	const MeshEntry*		getMeshEntry(EMeshIndex index) const { return mMeshEntries.lookup(index); }
	const MeshEntries&		getMeshEntries() const { return mMeshEntries; }

	//--------------------------------------------------------------------
	// Baked Textures
	//--------------------------------------------------------------------
public:
	struct BakedEntry : public LLDictionaryEntry
	{
		BakedEntry(ETextureIndex tex_index, 
				   const std::string &name, // unused, but necessary for templating.
				   const std::string &hash_name,
				   U32 num_local_textures, ... ); // # local textures, local texture list, # wearables, wearable list
		// Local Textures
		const ETextureIndex mTextureIndex;
		texture_vec_t 		mLocalTextures;
		// Wearables
		const LLUUID 		mWearablesHashID;
		wearables_vec_t 	mWearables;
	};

	struct BakedTextures: public LLDictionary<EBakedTextureIndex, BakedEntry>
	{
		BakedTextures();
	} mBakedTextures;
	const BakedEntry*		getBakedTexture(EBakedTextureIndex index) const { return mBakedTextures.lookup(index); }
	const BakedTextures&	getBakedTextures() const { return mBakedTextures; }
	
	//--------------------------------------------------------------------
	// Convenience Functions
	//--------------------------------------------------------------------
public:
	// Convert from baked texture to associated texture; e.g. BAKED_HEAD -> TEX_HEAD_BAKED
	ETextureIndex 		bakedToLocalTextureIndex(EBakedTextureIndex t) const;

	// find a baked texture index based on its name
	EBakedTextureIndex 	findBakedByRegionName(std::string name);
	EBakedTextureIndex 	findBakedByImageName(std::string name);

	// Given a texture entry, determine which wearable type owns it.
	LLWearableType::EType 		getTEWearableType(ETextureIndex index) const;

	static BOOL							isBakedImageId(const LLUUID& id);
	static EBakedTextureIndex			assetIdToBakedTextureIndex(const LLUUID& id);
	static LLUUID						localTextureIndexToMagicId(ETextureIndex t);

}; // End LLAvatarAppearanceDictionary

} // End namespace LLAvatarAppearanceDefines

#endif //LL_AVATARAPPEARANCE_DEFINES_H