
/*
  File: include/mia/Factory.h
  Description: MIA class factory definitions
  Part of the Mantis project
  (c) 2002 Lycos Inc.

  This file is distributed for the sole purpose of allowing you to write
  software to interface with Sonique 2 and other Mantis programs. It is
  not to be modified or used for any other purpose without written
  authorization.

  If you redistribute this file, it must be in the original package
  complete with all other files provided, including the usage agreement.

  Do not remove this notice.
*/

#ifndef _FACTORY_H_
#define _FACTORY_H_

class MIFactory : public MGeneric // MID_IFACTORY
{
public:
	virtual MRESULT	__stdcall	CreateInstance( const MID& mInterface, void** ppToHere, MObject* pOuter )							= 0;
};

class MIFactoryCallback
{
public:
	virtual void	__stdcall	GenericAnalogListChanged( )		= 0;
};

class MIFactoryServer : public MGeneric // MID_IFACTORY_SERVER
{
public:
	virtual MRESULT __stdcall	AddIFactory(	const MID& mIFactory, MIFactory* pInstance )													= 0; // runtime only
	virtual MRESULT __stdcall	RemoveIFactory( const MID& mIFactory )																			= 0;
	virtual MRESULT __stdcall	GetIFactory(	const MID& mIFactory, MIFactory** pToHere )														= 0;
	virtual MRESULT __stdcall	CreateInstance( const MID& mIFactory, const MID& mInterface, void** ppToHere,  MObject * pOuter )				= 0;
	virtual MRESULT __stdcall	GetGenericAnalogCount( const MID& mGenericFactoryID, uint32& toHere )											= 0;
	virtual MRESULT __stdcall	GetGenericAnalogIndex( const MID& mGenericFactoryID, uint32 index, MID& mFactoryToHere, WString& wsNameToHere )	= 0;
	virtual MRESULT __stdcall	RegisterAnalogChangeCallback( MIFactoryCallback* pCallback, bool bRegister )									= 0;
	virtual MRESULT __stdcall	GetPathForFactory( MID& mFactory, WString& wsPathToHere )														= 0;
};

#define ADD_GENERIC_REF 1
#define ADD_INNER_REF   2
#define ADD_NO_REF		3

template<class TYPE, class CASTTYPE, const MID* mid, int nRefType, class PARAMTYPE >
class SimpleFactoryParam : public MIFactory
{
	// MIFactory
	virtual MRESULT	__stdcall	CreateInstance( const MID& mInterface, void** ppToHere, MObject* /*pOuter*/ )
	{
		// DO shit here.
		if( mInterface == *mid )
			*ppToHere = (CASTTYPE*) new TYPE(m_Param);
		else
			*ppToHere = NULL;
		
		if( *ppToHere )
		{
			switch( nRefType )
			{
			case ADD_GENERIC_REF:
				((MGeneric*)(*ppToHere))->AddRef();
				break;
			case ADD_INNER_REF:
				((MInnerGeneric*)(*ppToHere))->InnerAddRef();
				break;
			}
			return M_OK;
		}
		
		return GetBasicError(ERR_BASIC_UNKNOWNOBJECT); 
	}
	
	// MGeneric
	IMPLEMENT_REFERENCECOUNT();
	IMPLEMENT_QUERYMODULE();
	
public:
	SimpleFactoryParam(PARAMTYPE param) :
		m_Param(param)
	{ 
		MGENERIC_CONSTRUCTOR(); 
	}
protected:
	PARAMTYPE	m_Param;
};


template<class TYPE, class CASTTYPE, const MID* mid, int nRefType>
class SimpleFactory : public MIFactory
{

	// MIFactory
	virtual MRESULT	__stdcall	CreateInstance( const MID& mInterface, void** ppToHere, MObject* /*pOuter*/ )
	{
		// DO shit here.
		if( mInterface == *mid )
			*ppToHere = (CASTTYPE*) new TYPE;
		else
			*ppToHere = NULL;

		if( *ppToHere )
		{
			switch( nRefType )
			{
			case ADD_GENERIC_REF:
				((MGeneric*)(*ppToHere))->AddRef();
				break;
			case ADD_INNER_REF:
				((MInnerGeneric*)(*ppToHere))->InnerAddRef();
				break;
			}
			return M_OK;
		}

		return GetBasicError(ERR_BASIC_UNKNOWNOBJECT); 
	}

	// MGeneric
	IMPLEMENT_REFERENCECOUNT();
	IMPLEMENT_QUERYMODULE();

public:
	SimpleFactory() { MGENERIC_CONSTRUCTOR(); }
};

template<class TYPE, const MID* mid, int nRefType>
class SimpleSingletonFactory : public MIFactory
{

	// MIFactory
	virtual MRESULT	__stdcall	CreateInstance( const MID& mInterface, void** ppToHere, MObject* /*pOuter*/ )
	{
		// DO shit here.
		if( mInterface == *mid )
			*ppToHere = (void*)m_pInstance;
		else
			*ppToHere = NULL;

		if( *ppToHere )
		{
			switch( nRefType )
			{
			case ADD_GENERIC_REF:
				((MGeneric*)(*ppToHere))->AddRef();
				break;
			case ADD_INNER_REF:
				((MInnerGeneric*)(*ppToHere))->InnerAddRef();
				break;
			}
			return M_OK;
		}

		return GetBasicError(ERR_BASIC_UNKNOWNOBJECT); 
	}

    const TYPE* m_pInstance;

	// MGeneric
	IMPLEMENT_REFERENCECOUNT();
	IMPLEMENT_QUERYMODULE();

public:
	SimpleSingletonFactory(const TYPE* pInstance) { MGENERIC_CONSTRUCTOR(); m_pInstance = pInstance; }
};

#endif//_FACTORY_
