// RsNodeFactory.cpp : Implementation of CRsNodeFactory

#include "stdafx.h"
#include "RsNodeFactory.h"
#include "RpExamplesPlugin.h"
#include "RnWidgetExample.h"
#include "RnHeightField.h"
#include "RnConnectorExample.h"

STDMETHODIMP CRsNodeFactory::CreateInstance(const IID *riid, IRsNode** ppNode) 
{
	//define how to create each node
	BEGIN_NODE_MAP()
		NODE_ENTRY(riid, ppNode, IRnWidgetExample, CRnWidgetExample)
		NODE_ENTRY(riid, ppNode, IRnHeightField, CRnHeightField)
        NODE_ENTRY(riid, ppNode, IRnConnectorExample, CRnConnectorExample)
	END_NODE_MAP() 

	return E_INVALIDARG;
}


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


STDMETHODIMP CRsNodeFactory::EnumNodeDesc(IRsEnumNodeDesc** ppEnumNodeDesc) 
{
	//define descriptors for each node
    BEGIN_NODE_DESC_MAP()
		NODE_DESC_ENTRY(IRnWidgetExample,	CRpExamplesPlugin, /* fill object descriptor*/ 0, 0, 0)
		NODE_DESC_ENTRY(IRnHeightField,	CRpExamplesPlugin, /* fill object descriptor*/ 0, 0, 0)		
        NODE_DESC_ENTRY(IRnConnectorExample, CRpExamplesPlugin, /* fill object descriptor*/ 0, 0, 0)
	END_NODE_DESC_MAP()

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

	// system factory
	CComPtr<IRpKernel> spKernel;
	CRpExamplesPlugin::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 registered connectors exported by this example package
    static const RtConDesc _conDesc[] =
	{
        {&CON_CONEX_REGISTERED_CONNECTOR, L"Operand 1", L"Operand 1", VT_R4, NULL, CONFLG_IN},
        {&IID_NULL, NULL, NULL, VT_EMPTY, NULL , static_cast<RtConFlags>(0)}
    };

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

 	CComPtr<IRpKernel>	spKernelPackage;
	CRpExamplesPlugin::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;
}
