// RpAnimPlugin.cpp : Implementation of CRpAnimPlugin
// CRpAnimPlugin 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 "RpAnimPluginPackage.h"
#include "RsApCmdFactory.h"
#include "RcApOpenToolbar.h"

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

// CRpAnimPlugin
CComPtr<IRpKernel>				CRpAnimPlugin::m_spKernelPackage = NULL;
CComPtr<IRsSysFactory>			CRpAnimPlugin::m_spSysFactory = NULL;
CComPtr<IRsSysCore>				CRpAnimPlugin::m_spSysCore = NULL;


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

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

HRESULT CRpAnimPlugin::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 CRpAnimPlugin::Initialize(IRsUnknownPackage *pParentPackage)
{
    ATLASSERT(pParentPackage != NULL);

    HRESULT hRes = pParentPackage->QueryInterface(DEF_GUIDNAME(IRpKernel), (void**) &m_spKernelPackage );
    if (FAILED(hRes))
        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 command factory
    CComObject<CRsApCmdFactory>* pCmdObj;
    hRes = CComObject<CRsApCmdFactory>::CreateInstance(&pCmdObj);
    if (FAILED(hRes))
        return hRes;
    if (FAILED(hRes = pCmdObj->QueryInterface(&m_spCmdFactory)))
        return hRes;
	
   return S_OK;
}

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

    return S_OK;
}


// returns NodeFactory interface provided by package
STDMETHODIMP CRpAnimPlugin::GetNodeFactory(IRsNodeFactory** ppNodeFactory)
{
	return E_NOTIMPL;
}

// returns Command Factory interface provided by package
STDMETHODIMP CRpAnimPlugin::GetCmdFactory(IRsCmdFactory** ppCmdFactory)
{
	return m_spCmdFactory.CopyTo(ppCmdFactory);
}

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

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

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

STDMETHODIMP CRpAnimPlugin::OnSysMessage(MSGID msgId, IRsUnknownMsg* pMsg)
{
	HRESULT hRes = S_OK;

	
	if(msgId == MSG_SYS_PACKAGE_LOADED )
    {
		//package is loaded from the plugin manager  
        CComQIPtr<IRsSysMsg>    spSysMsg = pMsg;
        if(spSysMsg)
        {
            CComPtr<IRsUnknownPackage>  spPackage;
            spSysMsg->GetPackage(&spPackage);
            CComQIPtr<IRpAnimPlugin> spAnimPlugin = spPackage;
            
			if(spAnimPlugin)  
			{
				// open toolbar
				hRes = OpenPluginToolbar();			
			}
        }
	}
	else if (msgId == MSG_SYS_READY) 
	{
		// called when the system finishes the initialization process
		// the object-constraint graph is already initialized at this stage

		// check if the plugin toolbar is present or not
		hRes = OpenPluginToolbar();
	}
	else if (msgId == MSG_SYS_REGISTER) 
	{
		// called right after the package is registered in the system 
	}
	else if (msgId == MSG_SYS_UNREGISTER) 
	{
		// called right after the package is unregistered from the system
	}
	else 
	{
		// Handle other system messages here 
	};


    return hRes;
}

HRESULT CRpAnimPlugin::OpenPluginToolbar(void)
{
	// send command to open plugin toolbar asynchronously 
	CComPtr<IRsNode> spCmd;
	HRESULT hr = CreateCmdObj(DEF_GUIDNAME_PTR(IRcApOpenToolbar), &spCmd);
	if (FAILED(hr))
		return hr;

	return SendCommand(spCmd);
}

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


HRESULT CRpAnimPlugin::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 CRpAnimPlugin::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 CRpAnimPlugin::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 CRpAnimPlugin::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 CRpAnimPlugin::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);
};

