// RpExamplesPlugin.h : Declaration of the CRpExamplesPlugin
#pragma once

#define EXAMPLE_PACKAGE_VERSION1			1	// cmdprompt package version
#define EXAMPLE_PACKAGE_VERSION				EXAMPLE_PACKAGE_VERSION1  

[
	object,
	helpstring("IRpExamplesPlugin Interface"),
	uuid("851DEB0F-0AB8-426c-B363-3818E99AE2CA"),
	pointer_default(unique)
]
__interface IRpExamplesPlugin : public IUnknown
{
public:
};



[
	ATTRIBUTE_COCLASS,
	threading(both),
	vi_progid("ExamplesPlugin.RpExamplesPlugin"),
	progid("ExamplesPlugin.RpExamplesPlugin.1"),
	version(1.0),
	uuid("C9A4BD64-E1E7-4fcc-A5B2-D2502BCFCC95"),
	helpstring("RpExamplesPlugin Class")
]
class ATL_NO_VTABLE CRpExamplesPlugin: 
	public IRpExamplesPlugin,
    public IRsUnknownPackage,
    public IRsModulePackage,
	public IRsPackageDesc
{
private:
    /**@name Attributes */
    //@{
        /// Pointer to kernel Package.
    static CComPtr<IRpKernel>			m_spKernelPackage;
		/// Pointer to sys factory for creating rs objects
	static CComPtr<IRsSysFactory>		m_spSysFactory;
		/// Pointer to sys core for synchronous command processing
	static CComPtr<IRsSysCore>			m_spSysCore;
	
		/// Pointer to Command prompt Package.
    static CComPtr<IRpExamplesPlugin>   m_spSamplePackage;
	
    	/// node factory
	CComPtr<IRsNodeFactory>				m_spNodeFactory;
		/// command factory
	CComPtr<IRsCmdFactory>				m_spCmdFactory;
		/// command factory
	CComPtr<IRsDataObjFactory>			m_spDataObjFactory;
        /// UI control object factory
	//CComPtr<IRsUIControlFactory>		m_spUIControlFactory;
    //@}

public:
    /**@name Methods */
    //@{
        /// Constructor, this constructor does nothing important.
    CRpExamplesPlugin()
    {
    }

        /// This method does nothing important.
    HRESULT FinalConstruct()
    {
        return S_OK;
    }

        /// This method just releases array of named items.
    void FinalRelease() 
    {
        //m_NamedItemsArray.RemoveAll();
    }

    /** This method allow access to the kernel package interface IRpKernel.
        @param ppPackage Out Pointer to the kernel package interface.
    */
	static HRESULT GetKernelPackage(IRpKernel** ppPackage);

    /** This method allow access to the System core .
        @param ppSysCore Out Pointer to the system core IRsSysCore.
    */
	static IRsSysCore *GetSysCore() 
	{
		return m_spSysCore;
	};


	/** Template for convenient creating of commands*/
	template<class T>
	static HRESULT CreateCommand(T **ppCmdNode)
	{
		if (!m_spSysFactory)
			return E_FAIL;
		CComPtr<IRsCommand> spCmd;
		m_spSysFactory->CreateCommand(DEF_GUIDNAME_PTR(T), &spCmd);
		if (!spCmd)
			return E_FAIL;

		CComQIPtr<IRsNode> spNode = spCmd;
		if (spNode) {
			HRESULT hr = spNode->LoadDefault();
			if (hr != S_OK) {
				spNode->Destroy();
				return hr;
			};
		};
		return spCmd.QueryInterface(ppCmdNode);		
	};
   	
	/** Template for convenient creating of nodes*/
	template<class T>
	static HRESULT CreateNode(T **ppNode)
	{
		if (!m_spSysFactory)
			return E_FAIL;
		CComPtr<IRsNode> spNode;
		m_spSysFactory->CreateNode(DEF_GUIDNAME_PTR(T), &spNode);
		if (!spNode)
			return E_FAIL;

		spNode->LoadDefault();
		return spNode.QueryInterface(ppNode);		
	};

	/** Template for convenient creating of data objects*/
	template<class T>
	static HRESULT CreateDataObject(T **ppDo)
	{
		if (!m_spSysFactory)
			return E_FAIL;
		CComPtr<IRsDataObject> spDo;
		m_spSysFactory->CreateDataObj(DEF_GUIDNAME_PTR(T), &spDo);
		if (!spDo)
			return E_FAIL;
		return spDo.QueryInterface(ppDo);		
	};
	
	/** Template for convenient access to other packages*/
	template <class T>
	static HRESULT FindPackage(GUID *pId, T **ppPackage)
	{
		if (!m_spKernelPackage)
			return E_FAIL;
		CComPtr<IRsUnknownPackage> spPck;
		m_spKernelPackage->FindPackage(*pId,&spPck);
		if (!spPck)
			return E_FAIL;
		return spPck.QueryInterface(ppPackage);
	};



	static HRESULT CreateCommand(GUID *id, IRsCommand **ppCmdNode)
	{
		if (!m_spSysFactory)
			return E_FAIL;
		CComPtr<IRsCommand> spCmd;

		HRESULT hr = m_spSysFactory->CreateCommand(id, &spCmd);
		if (FAILED(hr))
			return hr;
		
		CComQIPtr<IRsNode> spNode = spCmd;
		if (spNode) {
			hr = spNode->LoadDefault();
			if (hr != S_OK) {
				spNode->Destroy();
				return hr;
			};
		};
		return spCmd.CopyTo(ppCmdNode);
	};
   	
	//helper method for synchronous execution of commands
	static HRESULT ExecuteCommand(IRsCommand *pCmdNode)
	{
		if (!m_spSysCore) {
			//destroy command to prevent leaking
			CComQIPtr<IRsNode> spNode = pCmdNode;
			spNode->Destroy();
			return E_FAIL;
		};
		return m_spSysCore->ExecuteCommand(pCmdNode);
	};

    /**@name Methods of interface IRsUnknownPackage */
        //@{
    STDMETHOD(Initialize)(IRsUnknownPackage *pParentPackage);
        /// This method releases m_pKernelPackage.
    STDMETHOD(UnInitialize)();
		/// package messages handler
    STDMETHOD(OnSysMessage)(MSGID msgId, IRsUnknownMsg* pMsg);
		/// returns NodeFactory interface provided by package
	STDMETHOD(GetNodeFactory)(IRsNodeFactory** ppNodeFactory);
		/// returns Command Factory interface provided by package
	STDMETHOD(GetCmdFactory)(IRsCmdFactory** ppCmdFactory);
		/// returns Data Object Factory interface provided by package
	STDMETHOD(GetDataObjFactory)(IRsDataObjFactory** ppDataObjFactory);
	    /// returns Package module instance
    STDMETHOD(GetModuleInstance)(RtInstance* pInstance);
	    /// returns Package resource instance
    STDMETHOD(GetResourceInstance)(RtInstance* pInstance);
		/// package version
	RS_DECLARE_PACKAGE_VERSION(PRODUCT_VERSION, EXAMPLE_PACKAGE_VERSION);
	RS_PACKAGE_DESCRIPTION(L"Collection of basic sdk examples");
        //@}
    //@}

    // Macros are reason of problems for Doc++ so they should be out of
    // scope of Doc++ comments

    // IRsObject Methods
    RS_DECLARE_IRS_OBJECT(CRpExamplesPlugin, L"Examples Package")

    // we want only one instance of example plugin package
    DECLARE_CLASSFACTORY_SINGLETON(CRpExamplesPlugin)
    DECLARE_NOT_AGGREGATABLE(CRpExamplesPlugin)
    DECLARE_PROTECT_FINAL_CONSTRUCT()

    // log support
    RS_LOG_ACCESS(m_spKernelPackage)
    #define RS_LOG(lev, hr, text) CRpExamplesPlugin::MyLogEntry(lev, hr, text, __FILE__, __LINE__);   


    BEGIN_COM_MAP(CRpExamplesPlugin)
        COM_INTERFACE_ENTRY(IRpExamplesPlugin)
        COM_INTERFACE_ENTRY2(IRsObject, IRsUnknownPackage)
        COM_INTERFACE_ENTRY(IRsUnknownPackage)
        COM_INTERFACE_ENTRY(IRsModulePackage)
    END_COM_MAP()

};


