/******************************************************************************
 *                                                                         
 *               (C) COPYRIGHT Pacific MindWorks, Inc. 2001-2005
 *                          All rights reserved.
 *
 *****************************************************************************/

#ifndef __NTLSIMULATION_INCLUDED
#define __NTLSIMULATION_INCLUDED

#include <atlstr.h>
#include <atlcoll.h>

///////////////////////////////////////////////////////////////////////////////
//
//	CSimulationInfo
//

template <typename T>
class CSimulationInfo
	: public CModelBasedType
{
public:
	CSimulationInfo(T defaultValue, const CString& strModelOrFamily = _T(""))	
		: CModelBasedType(strModelOrFamily)
	{
		m_defaultValue = Copy(defaultValue);
	}

	~CSimulationInfo()
	{
		Delete(m_defaultValue);
	}

	T GetDefaultValue() const
	{
		return Copy(m_defaultValue);
	}

protected:
	static void Delete(T val);
	static T Copy(T val);

private:
	T m_defaultValue;
};

// Specializations for supported data types
template <>
inline void CSimulationInfo<double>::Delete(double val)
{
	NTL_UNUSED(val);
}

template <>
inline void CSimulationInfo<float>::Delete(float val)
{
	NTL_UNUSED(val);
}

template <>
inline void CSimulationInfo<long>::Delete(long val)
{
	NTL_UNUSED(val);
}

template <>
inline void CSimulationInfo<short>::Delete(short val)
{
	NTL_UNUSED(val);
}

template <>
inline void CSimulationInfo<BYTE>::Delete(BYTE val)
{
	NTL_UNUSED(val);
}

template <>
inline void CSimulationInfo<BSTR>::Delete(BSTR val)
{
	::SysFreeString(val);
}

template <>
inline double CSimulationInfo<double>::Copy(double val)
{
	return val;
}

template <>
inline float CSimulationInfo<float>::Copy(float val)
{
	return val;
}

template <>
inline long CSimulationInfo<long>::Copy(long val)
{
	return val;
}

template <>
inline short CSimulationInfo<short>::Copy(short val)
{
	return val;
}

template <>
inline BYTE CSimulationInfo<BYTE>::Copy(BYTE val)
{
	return val;
}

template <>
inline BSTR CSimulationInfo<BSTR>::Copy(BSTR val)
{
	return ::SysAllocString(val);
}


///////////////////////////////////////////////////////////////////////////////
//
//	CSimulationInfoManager
//

template <typename T>
class CSimulationInfoManager
{
public:
	CSimulationInfoManager(CSimulationInfo<T>* pFirstSimInfo, ...);

	T GetDefaultValue(const CString& strModel);
	CSimulationInfo<T>* LookupSimulationInfo(const CString& strModel);

	T GetDefaultDefaultValue();

private:
	typedef CSimulationInfo<T> SimInfo;
	typedef CModelBasedMap<SimInfo> SimInfoMap;		// key = model, value = CSimulationInfo
	SimInfoMap m_mapSimInfo;
};

template <typename T>
inline CSimulationInfoManager<T>::CSimulationInfoManager(CSimulationInfo<T>* pFirstSimInfo, ...)
{
	va_list argPtr;
	va_start(argPtr, pFirstSimInfo);

	m_mapSimInfo.BuildMap(pFirstSimInfo, argPtr);

	va_end(argPtr);
}

template <typename T>
inline T CSimulationInfoManager<T>::GetDefaultValue(const CString& strModel)
{
	CSimulationInfo<T>* pSimInfo = LookupSimulationInfo(strModel);
	if (pSimInfo == NULL)
	{
		return GetDefaultDefaultValue();
	}
	else
	{
		return pSimInfo->GetDefaultValue();
	}
}

template <typename T>
inline CSimulationInfo<T>* CSimulationInfoManager<T>::LookupSimulationInfo(const CString& strModel)
{
	CSimulationInfo<T>* pSimInfo = NULL;
	if (!m_mapSimInfo.Lookup(strModel, pSimInfo))
	{
		// When a family is used, it is expanded to models, so we should have found the model in that case
		// This means we have to use the value for default (empty string)
		if (!m_mapSimInfo.Lookup(_T(""), pSimInfo))
		{
			ATLASSERT(!"Simulation info not found for model.");
		}
	}

	return pSimInfo;
}

// Specializations for supported data types
template <>
inline double CSimulationInfoManager<double>::GetDefaultDefaultValue()
{
	return 0;
}

template <>
inline float CSimulationInfoManager<float>::GetDefaultDefaultValue()
{
	return 0;
}

template <>
inline long CSimulationInfoManager<long>::GetDefaultDefaultValue()
{
	return 0;
}

template <>
inline short CSimulationInfoManager<short>::GetDefaultDefaultValue()
{
	return 0;
}

template <>
inline BYTE CSimulationInfoManager<BYTE>::GetDefaultDefaultValue()
{
	return 0;
}

template <>
inline BSTR CSimulationInfoManager<BSTR>::GetDefaultDefaultValue()
{
	return ::SysAllocString(OLESTR(""));
}

#endif // __NTLSIMULATION_INCLUDED
