// RsNodeFactory.cpp : Implementation of CRsNodeFactory

#include "stdafx.h"
#include "RsNodeFactory.h"
#include "Rn3DLoader.h"

STDMETHODIMP CRsNodeFactory::CreateInstance(const IID *riid, IRsNode** ppNode) 
{
    // Define how to create each node
    BEGIN_NODE_MAP()
        NODE_ENTRY(riid, ppNode, IRn3DLoader, CRn3DLoader)
    END_NODE_MAP() 

    return E_INVALIDARG;
}


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


STDMETHODIMP CRsNodeFactory::EnumNodeDesc(IRsEnumNodeDesc** ppEnumNodeDesc) 
{
    static const RtObjDesc DscRn3DLoader = {IDS_AUTHOR, 1, L"02/14/2008", ACCESS_RIGHTS_ALL, IDS_RN_3D_LOADER, OBJUSER_DEVELOPER, RS_DOC_SAMPLES(0)};

    //define descriptors for each node
    BEGIN_NODE_DESC_MAP()
        NODE_DESC_ENTRY(IRn3DLoader, CRp3DLoader, &DscRn3DLoader, 0, IDB_RN_3D_LOADER)
    END_NODE_DESC_MAP()

    typedef CComEnum<IRsEnumNodeDesc, &__uuidof(IRsEnumNodeDesc), IRsNodeDesc*, _CopyInterface<IRsNodeDesc> > CRsEnumNodeDesc;

    // system factory
    CComPtr<IRpKernel> spKernel;
    CRp3DLoader::GetKernelPackage(&spKernel);
    CComPtr<IRsSysFactory> spFactory;
    HRESULT hr = spKernel->GetSysFactory(&spFactory);
    if (FAILED(hr))	
        return hr;

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

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

    // initialize array
    CInterfaceArray<IRsNodeDesc>	arrayDesc;

    // fill array
    for (RtUlong i = 0; i< lastIndex; i++)
    {
        // create descriptor instance
        CComPtr<IRsNodeDesc>	spNodeDesc;
        spFactory->CreateNodeDesc(&spNodeDesc);

        // initialize descriptor
        spNodeDesc->Initialize(&_nodeDesc[i]);

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

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

    if (SUCCEEDED(hr)) 
        hr = pEnum->QueryInterface(ppEnumNodeDesc);
    return hr;
}

STDMETHODIMP CRsNodeFactory::EnumConDesc(IRsEnumConDesc** ppEnumConDesc)
{
	// define global connectors exported by this example package
    static const RtConDesc _conDesc[] =
	{
        {&IID_NULL, NULL, NULL, VT_EMPTY, NULL , static_cast<RtConFlags>(0)}
    };

    typedef CComEnum<IRsEnumConDesc, &__uuidof(IRsEnumConDesc), IRsConDescriptor*, _CopyInterface<IRsConDescriptor> > CRsEnumConDesc;

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

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

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

	// initialize array
	CInterfaceArray<IRsConDescriptor>	arrayDesc;
	
	// fill array
	for(RtUlong i = 0; i<lastIndex; i++)
	{
		// create descriptor instance
        CComPtr<IRsConDescriptor>	spConDesc;
		spFactory->CreateConnectorDesc(_conDesc+i, &spConDesc);
		
		// add it to array
		arrayDesc.Add(spConDesc);
	}
	
	// initialize enumerator so that caller takes ownership of the array
	hr = pEnum->Init((IRsConDescriptor**)&arrayDesc[0].p, 
					 (IRsConDescriptor**)&arrayDesc[lastIndex-1].p, NULL ,AtlFlagCopy  );

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

    return hr;
}
