/*
-----------------------------------------------------------------------------
This source file is part of OGRE 
(Object-oriented Graphics Rendering Engine)
For the latest info, see http://www.ogre3d.org/

Copyright (c) 2000-2006 Torus Knot Software Ltd
Also see acknowledgements in Readme.html

This program 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; either version 2 of the License, or (at your option) any later 
version.

This program 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 program; if not, write to the Free Software Foundation, Inc., 59 Temple 
Place - Suite 330, Boston, MA 02111-1307, USA, or go to 
http://www.gnu.org/copyleft/lesser.txt.

You may alternatively use this source under the terms of a specific version of
the OGRE Unrestricted License provided you have obtained such a license from
Torus Knot Software Ltd.
-----------------------------------------------------------------------------
*/
#ifndef __XSIHELPER_H__
#define __XSIHELPER_H__

#include <xsi_application.h>
#include <xsi_string.h>
#include <xsi_x3dobject.h>
#include <xsi_vertexcolor.h>
#include <xsi_math.h>
#include <xsi_ref.h>
#include <xsi_actionsource.h>
#include <xsi_animationsourceitem.h>
#include <xsi_progressbar.h>
#include <xsi_uitoolkit.h>
#include <xsi_shader.h>
#include <xsi_value.h>

#include <stdlib.h>
#include "OgrePrerequisites.h"
#include "OgreString.h"
#include "OgreColourValue.h"
#include "OgreLogManager.h"
#include "OgreStringVector.h"
#include "OgreSingleton.h"
#include "OgreVector3.h"
#include "OgreQuaternion.h"
#include "OgreHardwareVertexBuffer.h"

#define OGRE_XSI_NUM_MESH_STEPS 200

/// Useful function to convert XSI CValue to an Ogre String
/*
inline Ogre::String XSItoOgre(const XSI::CValue& xsival)
{

	switch(xsival.m_t)
	{
	case XSI::CValue::siString:
		return XSItoOgre(XSI::CString(xsival));
	case XSI::CValue::siVector3:
		return XSItoOgre(XSI::MATH::CVector3(xsival));
	default:
		return XSItoOgre(XSI::CString(xsival.GetAsText()));
	};

}
*/

/// Useful function to convert an XSI CString to an Ogre String
inline Ogre::String XSItoOgre(const XSI::CString& xsistr)
{
    // XSI CString is wide character

    if (xsistr.IsEmpty())
    {
        return Ogre::StringUtil::BLANK;
    }

    // first find out the size required
    size_t c = ::wcstombs(0, xsistr.GetWideString(), 2048);
    // temp character string (add one for terminator)
    char* tmp = new char[c+1];
    // do the real conversion
    ::wcstombs(tmp, xsistr.GetWideString(), c);
	tmp[c] = '\0';
    Ogre::String ret(tmp);
    delete [] tmp;

    return ret;
}
/// Useful function to convert an Ogre String to an XSI CString
inline XSI::CString OgretoXSI(const Ogre::String& str)
{
    // XSI CString is wide character

    if (str.empty())
    {
        return XSI::CString();
    }

    // first find out the size required
    size_t c = ::mbstowcs(0, str.c_str(), 2048);
    // temp character string (add one for terminator)
    wchar_t* tmp = new wchar_t[c+1];
    // do the real conversion
    ::mbstowcs(tmp, str.c_str(), c);
	tmp[c] = '\0';

    XSI::CString ret(tmp);
    delete [] tmp;

    return ret;
}

inline Ogre::Vector3 XSItoOgre(const XSI::MATH::CVector3& xsiVec)
{
    return Ogre::Vector3(xsiVec.GetX(), xsiVec.GetY(), xsiVec.GetZ());
}
inline Ogre::Quaternion XSItoOgre(const XSI::MATH::CQuaternion& xsiQuat)
{
	return Ogre::Quaternion(xsiQuat.GetW(), xsiQuat.GetX(), xsiQuat.GetY(), xsiQuat.GetZ());
}

inline Ogre::RGBA XSItoOgre(const XSI::CVertexColor& xsiColour)
{
	Ogre::ColourValue col(xsiColour.r / 255.0f, xsiColour.g / 255.0f, 
		xsiColour.b / 255.0f, xsiColour.a / 255.0f);
	return Ogre::VertexElement::convertColourValue(col, 
		Ogre::VertexElement::getBestColourVertexElementType());
}

inline void LogOgreAndXSI(const Ogre::String& msg)
{
	static XSI::Application app;
	Ogre::LogManager::getSingleton().logMessage(msg);
	app.LogMessage(OgretoXSI(msg));

}

inline void LogOgreAndXSI(const XSI::CString& msg)
{
	static XSI::Application app;
	Ogre::LogManager::getSingleton().logMessage(XSItoOgre(msg));
	app.LogMessage(msg);

}


namespace Ogre {

	class ProgressManager : public Singleton<ProgressManager>
	{
	protected:
		XSI::ProgressBar mProgressBar;
		size_t mNumberOfStages;
		size_t mProgress;

	public:
		ProgressManager(size_t numberOfStages);
		virtual ~ProgressManager();
			
		void progress(void);

		static ProgressManager& getSingleton(void);
		static ProgressManager* getSingletonPtr(void);

	};

	enum XSITrackType
	{
		XTT_POS_X = 0,
		XTT_POS_Y = 1,
		XTT_POS_Z = 2,
		XTT_ROT_X = 3,
		XTT_ROT_Y = 4,
		XTT_ROT_Z = 5,
		XTT_SCL_X = 6,
		XTT_SCL_Y = 7,
		XTT_SCL_Z = 8,
		XTT_COUNT = 9
	};
	/** An entry for a Deformer - need original index because this will be boneID */
	class DeformerEntry
	{
	public:
		unsigned short boneID;
		XSI::X3DObject obj;
		String parentName;
		StringVector childNames;
		bool hasVertexAssignments;
		bool parentIsChainEndEffector;
		bool hasAnyTracks;
		Bone* pBone;
		bool ikSample;
		double ikSampleInterval;
		XSI::MATH::CTransformation initialXform;
		// lists of action source items (probably only one per param?)
		XSI::AnimationSourceItem xsiTrack[XTT_COUNT];

		DeformerEntry(unsigned short theboneID, XSI::X3DObject& theobj)
			:boneID(theboneID), obj(theobj), hasVertexAssignments(false), 
			parentIsChainEndEffector(false), hasAnyTracks(false), pBone(0)
			
		{
		}

	};
	/// Map from deformer name to deformer entry
	typedef std::map<String,DeformerEntry*> DeformerMap;


	/** An entry for animation; allows the userto split the timeline into 
		multiple separate animations. 
	*/
	struct AnimationEntry
	{
		String animationName;
		long startFrame; 
		long endFrame; 
		double ikSampleInterval; // skeletal only
	};
	/// List of animations
	typedef std::list<AnimationEntry> AnimationList;

	/** Record of an XSI GL shader material. */
	struct MaterialEntry
	{
		String name;
		XSI::Shader xsiShader;
	};
	/// Map from material name to material entry
	typedef std::map<String, MaterialEntry*> MaterialMap;

	/** Record of XSI details that are to become a pass */
	struct PassEntry
	{
		XSI::CRefArray shaders;
	};
	typedef std::deque<PassEntry*> PassQueue;

	/// Map from texture projection name to index
	typedef std::map<String, int> TextureProjectionMap;

	/** Platform-independent file copy (destination folder must exist)
		Maybe use Boost::filesystem if this gets out of hand
	*/
	void copyFile(const String& src, const String& dest);

}
#endif

