
#include "StdAfx.h"
#include "Factory.h"
#include "istrmap.h"
#include "mycontextbase.h"
#include "ComponentClass.h"

IMPLEMENT_DYNCREATE(CObjectFactory, CBLContext);

class CClassItem : public CCollectionItem
{
public:
    CRuntimeClass* m_pRuntimeClass;
    int m_nCtorParamsCount;
};

CCollection collClasses;

void CObjectFactory::RegisterClass(LPCSTR szClassName, CRuntimeClass* pRuntimeClass, int nCtorParamsCount)
{
    CClassItem* pClassItem = new CClassItem;
    pClassItem->SetName(szClassName);
    pClassItem->m_pRuntimeClass = pRuntimeClass;
    pClassItem->m_nCtorParamsCount = nCtorParamsCount;
    collClasses.Add(pClassItem);
}

CObjectFactory::CObjectFactory()
{
}

CObjectFactory::~CObjectFactory()
{
}

//CBLContext
char const* CObjectFactory::GetTypeString(void)const
{
    return "ФабрикаОбъектов";
}

int CObjectFactory::GetNMethods(void)const
{
    return collClasses.GetCount();
}

int CObjectFactory::FindMethod(char const* szName)const
{
    return collClasses.GetIndex(szName);
}

char const* CObjectFactory::GetMethodName(int nMethIndex, int bAlias)const
{
    return collClasses[nMethIndex]->GetName();
}

int CObjectFactory::GetNParams(int nMethIndex)const
{
    return static_cast<CClassItem*>(collClasses[nMethIndex])->m_nCtorParamsCount;
}

int CObjectFactory::GetParamDefValue(int nMethIndex, int nParamIndex, class CValue * pValue)const
{
    pValue->Reset();
    return 1;
}

int CObjectFactory::HasRetVal(int nMethIndex)const
{
    return 1;
}

int CObjectFactory::CallAsProc(int nMethIndex, class CValue** ppValues)
{
    return 0;
}

int CObjectFactory::CallAsFunc(int nMethIndex, class CValue& rValue, class CValue** ppValues)
{
    CClassItem* pClassItem = static_cast<CClassItem*>(collClasses[nMethIndex]);
    CBLContext* pBLContext = static_cast<CBLContext*>(pClassItem->m_pRuntimeClass->CreateObject());
    pBLContext->InitObject(pClassItem->GetName());
    
    BOOL bSuccess;

    if (pBLContext->IsKindOf(RUNTIME_CLASS(CComponentClass)))
    {
        int nIndex = pBLContext->FindMethod("_Create");
        if (nIndex != -1)
        {
            int nParamCount = pBLContext->GetNParams(nIndex);
            if (nParamCount == pClassItem->m_nCtorParamsCount)
                bSuccess = pBLContext->CallAsProc(nIndex, ppValues);
            else
            {
                CBLModule::RaiseExtRuntimeError("Не совпадает количество параметров.", 0);
                bSuccess = FALSE;
            }
        }
        else
        {
            CBLModule::RaiseExtRuntimeError("Не найден конструктор.", 0);
            bSuccess = FALSE;
        }
    }
    else
        //if object is internal, then he must be inherited by CMyContextBase
        bSuccess = static_cast<CMyContextBase*>(pBLContext)->_Create(ppValues);

    if (bSuccess)
	{
        rValue.AssignContext(pBLContext);
        pBLContext->DecrRef();
	}
    else
    {
        rValue.Reset();
        pBLContext->DecrRef();
    }

    return bSuccess;
}

