// RsApCmdFactory.cpp : Implementation of CRsApCmdFactory

#include "stdafx.h"
#include "RpAnimPluginPackage.h"
#include "RsApCmdFactory.h"

#include "RiAnimPlugin.h"
#include "RcApOpenToolbar.h"
#include "RaClip.h"
#include "RcCreateProcClip.h"


// CRsApCmdFactory
STDMETHODIMP CRsApCmdFactory::CreateInstance(const IID *riid, IRsCommand** ppCmd)
{
    BEGIN_COMMAND_MAP()
		COMMAND_ENTRY(riid, ppCmd, IRcApOpenToolbar, CRcApOpenToolbar)
		COMMAND_ENTRY(riid, ppCmd, IRcCreateProcClip, CRcCreateProcClip)
		COMMAND_ENTRY(riid, ppCmd, IRaClip, CRaClip) 
    END_COMMAND_MAP()

    return E_INVALIDARG;
}

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

STDMETHODIMP CRsApCmdFactory::EnumCommandDesc(IRsEnumCmdDesc** ppEnumCmdDesc)
{
	BEGIN_COMMAND_DESC_MAP()
		COMMAND_DESC_ENTRY(IRcApOpenToolbar, CRpAnimPlugin, /* fill object descriptor*/ 0, CMDFLAG_INTERFACE, 0)
		COMMAND_DESC_ENTRY(IRcCreateProcClip, CRpAnimPlugin, /* fill object descriptor*/ 0, CMDFLAG_MASTER, 0)
		COMMAND_DESC_ENTRY(IRaClip, CRpAnimPlugin, /* fill object descriptor*/ 0, CMDFLAG_MASTER, 0)
	END_COMMAND_DESC_MAP()

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

	CComPtr<IRpKernel>	spKernelPackage;
	CRpAnimPlugin::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 CRsApCmdFactory::EnumScriptObjects(IRsEnumNamedItem** ppEnum)
{
    if (m_aNamedItemsArray.IsEmpty()) {
		{
			CComObject<CRiAnimPlugin>* pObj = NULL;
			HRESULT hRes = CComObject<CRiAnimPlugin>::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;
}