// RpViewPackage.cpp : Implementation of CRpViewPackage
// CRpViewPackage represents the plugin. We implement here the
// IRsUnknownPackage interface that is asked during the plugin loading.
// The interface then enable communication with system and all other
// packages.

#include "stdafx.h"
#include "RpViewPackage.h"

// factories 
//#include "RsCmdFactory.h"
#include "RsVPNodeFactory.h"

// CRpViewPackage
CComPtr<IRpKernel>			 CRpViewPackage::m_spKernelPackage = NULL;
CComPtr<IRsSysFactory>		 CRpViewPackage::m_spSysFactory = NULL;
CComPtr<IRsSysCore>			 CRpViewPackage::m_spSysCore = NULL;
CComPtr<IRpViewPackage>		 CRpViewPackage::m_spSamplePackage = NULL;

HRESULT CRpViewPackage::GetKernelPackage(IRpKernel** ppPackage)
{
    // if you got assert here, ViewPackage package is not initialized 
    ATLASSERT(m_spKernelPackage != NULL);
    return m_spKernelPackage.CopyTo(ppPackage);
}

HRESULT CRpViewPackage::GetKernelNode(IRnKernel** ppNode)
{
	// if you got assert here, ViewPackage package is not initialized 
	ATLASSERT(m_spKernelPackage != NULL);
	return m_spKernelPackage->GetKernelNode(ppNode);
}

HRESULT CRpViewPackage::GetSysFactory(IRsSysFactory** ppSysFactory)
{
	// if you got assert here, ViewPackage package is not initialized 
	ATLASSERT(m_spSysFactory != NULL);
	return m_spSysFactory.CopyTo(ppSysFactory);
}
// IRsUnknownPackage Methods
STDMETHODIMP CRpViewPackage::Initialize(IRsUnknownPackage *pParentPackage)
{
    ATLASSERT(pParentPackage != NULL);

    HRESULT hRes = pParentPackage->QueryInterface(DEF_GUIDNAME(IRpKernel), (void**) &m_spKernelPackage );
    if (FAILED(hRes))
        return hRes;

    if (FAILED(hRes = QueryInterface(DEF_GUIDNAME(IRpViewPackage), (void**) &m_spSamplePackage)))
        return hRes;

    // get pointers to useful system resources like resources factories or syscore
    m_spKernelPackage->GetSysFactory(&m_spSysFactory);
    if (m_spSysFactory == NULL)
        return E_FAIL;

    m_spKernelPackage->GetSysCore(&m_spSysCore);
    if (m_spSysCore == NULL)
        return E_FAIL;

    
    // create node factory
    CComObject<CRsVPNodeFactory>* pNodeObj;
    hRes = CComObject<CRsVPNodeFactory>::CreateInstance(&pNodeObj);
    if (FAILED(hRes))
        return hRes;
    if (FAILED(hRes = pNodeObj->QueryInterface(&m_spNodeFactory)))
        return hRes;

   return S_OK;
}

STDMETHODIMP CRpViewPackage::UnInitialize()
{
	m_spKernelPackage.Release();
	m_spSysFactory.Release();
	m_spSysCore.Release();
	m_spSamplePackage.Release();

    return S_OK;
}


// returns NodeFactory interface provided by package
STDMETHODIMP CRpViewPackage::GetNodeFactory(IRsNodeFactory** ppNodeFactory)
{
	return m_spNodeFactory.CopyTo(ppNodeFactory);
}

// returns Command Factory interface provided by package
STDMETHODIMP CRpViewPackage::GetCmdFactory(IRsCmdFactory** ppCmdFactory)
{
	return E_NOTIMPL;
}

// returns Data object Factory interface provided by package
STDMETHODIMP CRpViewPackage::GetDataObjFactory(IRsDataObjFactory** ppDataObjFactory)
{
	return E_NOTIMPL;
}

STDMETHODIMP CRpViewPackage::GetModuleInstance(RtInstance* pInstance)
{
	if (pInstance)
	{
		HINSTANCE hInstance = _AtlBaseModule.GetModuleInstance();
		*pInstance = (RtInstance)hInstance;
		return S_OK;
	}
	return E_INVALIDARG;
}

STDMETHODIMP CRpViewPackage::GetResourceInstance(RtInstance* pInstance)
{
	if (pInstance)
	{
		HINSTANCE hInstance = _AtlBaseModule.GetResourceInstance();
		*pInstance = (RtInstance)hInstance;
		return S_OK;
	}
	return E_INVALIDARG;
}

STDMETHODIMP CRpViewPackage::OnSysMessage(MSGID msgId, IRsUnknownMsg* pMsg)
{
	if (msgId == MSG_SYS_REGISTER) {
		// called when plugin has been loaded into rosetta
	}
	else if (msgId == MSG_SYS_UNREGISTER) {
		// Called when plugin has been unloaded from rosetta
	}
	else {
		// Handle other system messages here 
	};
    return S_OK;
}

//////////////////////////////////////////////////////////////////////////
// Some useful static methods:


HRESULT CRpViewPackage::CreateDataObj(const IID* piid, IRsDataObject** ppDataObj)
{
    HRESULT hr;

    if (ppDataObj == NULL)
        return E_INVALIDARG;

    if (m_spKernelPackage == NULL)
        return E_FAIL;

    CComPtr<IRsSysFactory>	spFactory;
    CComPtr<IRsDataObject>  spData;

    if (FAILED(hr = m_spKernelPackage->GetSysFactory(&spFactory)))
        return hr;

    if (FAILED(hr = spFactory->CreateDataObj(piid, &spData)))
        return hr;

    return spData->QueryInterface(ppDataObj);
}

HRESULT CRpViewPackage::CreateCmdObj(const IID *piid, IRsNode **ppCmd)
{
    HRESULT hr;

    if (ppCmd == NULL)
        return E_INVALIDARG;

    if (m_spKernelPackage == NULL)
        return E_FAIL;

    CComPtr<IRsSysFactory>	spFactory;
    if (FAILED(hr = m_spKernelPackage->GetSysFactory(&spFactory)))
        return hr;

    // create command object
    CComPtr<IRsCommand> spCommand;
    if (FAILED(hr = spFactory->CreateCommand(piid, &spCommand)))
        return hr;

    CComQIPtr<IRsNode> spNode = spCommand;
    if (FAILED(hr = spNode->LoadDefault()))
        return hr;

    return spNode.CopyTo(ppCmd);
}

HRESULT CRpViewPackage::CreateNode(const IID *piid, IRsNode **ppNode)
{
    HRESULT hr;

    if (ppNode == NULL)
        return E_INVALIDARG;

    CComPtr<IRsSysFactory> spFactory;
    if (FAILED(hr = m_spKernelPackage->GetSysFactory(&spFactory)))
        return hr;

    CComPtr<IRsNode> spNode;
    if (FAILED(hr = spFactory->CreateNode(piid, &spNode)))
        return hr;

    if (FAILED(hr = spNode->LoadDefault()))
        return hr;

    return spNode.CopyTo(ppNode);
}

HRESULT CRpViewPackage::ExecuteCommand(IRsNode *pCmdNode)
{
    if (pCmdNode == NULL)
        return E_FAIL;
    if (m_spSysCore == NULL) { //destroy command to prevent leaking
        pCmdNode->Destroy();
        return E_FAIL;
    };

    return m_spSysCore->ExecuteCommand(CComQIPtr<IRsCommand>(pCmdNode));
};

HRESULT CRpViewPackage::SendCommand(IRsNode *pCmdNode)
{
    if (pCmdNode == NULL)
        return E_FAIL;
    if (m_spSysCore == NULL) { //destroy command to prevent leaking
        pCmdNode->Destroy();
        return E_FAIL;
    };

    return m_spSysCore->SendCommand(pCmdNode);
};

