// RsCmdFactory.cpp : Implementation of CRsCmdFactory

#include "stdafx.h"
#include "resource.h"
#include "Ri3DLoader.h"
#include "RsCmdFactory.h"

#include "RcCreate3DLoader.h"
#include "RcUpdate3DLoader.h"

//#include "RcMaterialModifyExample.h"

// CRsCmdFactory
STDMETHODIMP CRsCmdFactory::CreateInstance(const IID *riid, IRsCommand** ppCmd)
{
    BEGIN_COMMAND_MAP()
        COMMAND_ENTRY(riid, ppCmd, IRcCreate3DLoader, CRcCreate3DLoader)
        COMMAND_ENTRY(riid, ppCmd, IRcUpdate3DLoader, CRcUpdate3DLoader)
    END_COMMAND_MAP()

    return E_INVALIDARG;
}

STDMETHODIMP CRsCmdFactory::CreateAggInstance(IUnknown* pUnkOuter, const IID *riid, IUnknown** ppvObject)
{
	return E_NOTIMPL;
}

STDMETHODIMP CRsCmdFactory::EnumCommandDesc(IRsEnumCmdDesc** ppEnumCmdDesc)
{
    static const RtObjDesc DscCreate3DLoader = {IDS_AUTHOR, 1, L"02/14/2008", ACCESS_RIGHTS_ALL, IDS_RC_CREATE_3D_LOADER, OBJUSER_DEPRECATED, RS_DOC_SAMPLES(0)};
    static const RtObjDesc DscUpdate3DLoader = {IDS_AUTHOR, 1, L"02/14/2008", ACCESS_RIGHTS_ALL, IDS_RC_UPDATE_3D_LOADER, OBJUSER_DEPRECATED, RS_DOC_SAMPLES(0)};

    BEGIN_COMMAND_DESC_MAP()
        COMMAND_DESC_ENTRY(IRcCreate3DLoader, CRp3DLoader, &DscCreate3DLoader, 0, IDB_CRETE_3D_LOADER)
        COMMAND_DESC_ENTRY(IRcUpdate3DLoader, CRp3DLoader, &DscUpdate3DLoader, 0, IDB_UPDATE_3D_LOADER)
    END_COMMAND_DESC_MAP()

    typedef CComEnum<IRsEnumCmdDesc, &__uuidof(IRsEnumCmdDesc), IRsCmdDesc*, _CopyInterface<IRsCmdDesc> > CRsEnumCmdDesc;

    CComPtr<IRpKernel>	spKernelPackage;
    CRp3DLoader::GetKernelPackage(&spKernelPackage);
    CComPtr<IRsSysFactory>	spFactory;
    spKernelPackage->GetSysFactory(&spFactory);

    CComObject<CRsEnumCmdDesc>* pEnum;
    HRESULT hr = CComObject<CRsEnumCmdDesc>::CreateInstance(&pEnum);
    if (FAILED(hr))	
        return hr;

    // number of the items in the descriptor array
    RtUlong lastIndex = sizeof(_cmdDesc) / sizeof(_cmdDesc[0]);

    // initialize array
    CInterfaceArray<IRsCmdDesc>	arrayDesc;
    // fill array
    for (RtUlong i = 0; i< lastIndex; i++)
    {
        // create descriptor instance
        CComPtr<IRsCmdDesc>	spCmdDesc;
        spFactory->CreateCmdDesc(&spCmdDesc);

        // initialize descriptor
        spCmdDesc->Initialize(&_cmdDesc[i]);

        // add it to array
        arrayDesc.Add(spCmdDesc);
    }

    // initialize enumerator so that caller takes ownership of the array
    hr = pEnum->Init((IRsCmdDesc**)&arrayDesc[0].p, 
        (IRsCmdDesc**)&arrayDesc[lastIndex-1].p, NULL ,AtlFlagCopy );

    if (SUCCEEDED(hr))
        hr = pEnum->QueryInterface(ppEnumCmdDesc);

    return hr;
}



STDMETHODIMP CRsCmdFactory::EnumScriptObjects(IRsEnumNamedItem** ppEnum)
{
    if (m_aNamedItemsArray.IsEmpty()) {
        {
            CComObject<CRi3DLoader>* pObj = NULL;
            HRESULT hRes = CComObject<CRi3DLoader>::CreateInstance(&pObj);
            if (FAILED(hRes))
                return hRes;
            CComPtr<IRsNamedItem> spNamedItem;
            if(FAILED(hRes = pObj->QueryInterface(&spNamedItem)))
                return hRes;
            m_aNamedItemsArray.Add(spNamedItem);
        }
    }


    typedef CComEnum<IRsEnumNamedItem, 
                    &__uuidof(IRsEnumNamedItem), 
                    IRsNamedItem*, 
                    _CopyInterface<IRsNamedItem> > CComEnumNamedItem;

    // create an instance of enumerator object
    CComObject<CComEnumNamedItem>* pObjEnum = NULL;
    HRESULT hr = CComObject<CComEnumNamedItem>::CreateInstance(&pObjEnum);

    if (FAILED(hr))
        return hr;

    size_t lastIndex = m_aNamedItemsArray.GetCount();

    if (lastIndex < 1)
    {
        // there is nothing in the list
        *ppEnum = NULL;
        return S_FALSE;
    }

    // initialize enumerator
    IRsNamedItem** pFirst = &m_aNamedItemsArray[0].p;
    IRsNamedItem** pLast = &m_aNamedItemsArray[lastIndex-1].p;
    pLast++;    // To avoid skip of the last element

    hr = pObjEnum->Init(pFirst, pLast, reinterpret_cast<IRpKernel*>(this), AtlFlagNoCopy );

    if (SUCCEEDED(hr))
        hr = pObjEnum->QueryInterface(ppEnum);

    return hr;
}