// Rn3DLoader.h : Declaration of the CRn3DLoader
// This is probably the main object as it represents the 3DLoader itself.
// You can see it in the Link Editor when you execute the 
// Rs3DLoader.Create3DLoader() script command.

#pragma once
#include "resource.h"   // main symbols

// Synchronization time between the monitored directory and thumbnails
#define RN3DLDCNS_SYNC_TIME             1500
#define RN3DLDCNS_SYNC_TIME_ARRANGING   100

// Flags of the CRn3DLoader::m_dwFlags
// All the flags bellow are used for node update through the CRn3DLoader::Update method
#define RN3DLDRFLG_3DLNODE_NONE         0x00000000
#define RN3DLDRFLG_3DLNODE_STNG_CHANGED 0x00000001  // One of the connectors' value has changed
#define RN3DLDRFLG_3DLNODE_POST_LOAD    0x00000002  // The node was de-serialized
#define RN3DLDRFLG_3DLNODE_UPD_CMD_SENT 0x00000004  // The update command was sent
#define RN3DLDRFLG_3DLNODE_ARRANGING    0x00000008  // Thumbnails' animation is running

// Connectors' IID definitions
// 3DLoader node is using only 1 string parameter that is used to set the focus directory
// FocusDir: Focused directory
// {B19F25E5-FE7B-480d-8FD2-73D6E29D91B5}
RS_DEFINE_GUID(CON_3DLOADER_NODE_DIR_PATH,
0xb19f25e5, 0xfe7b, 0x480d, 0x8f, 0xd2, 0x73, 0xd6, 0xe2, 0x9d, 0x91, 0xb5);


// IRn3DLoader
[
    object,
    uuid("7ACF09F2-0D89-4f25-9ABA-322A00E550DE"),
    helpstring("IRn3DLoader"),
    pointer_default(unique)
]
__interface IRn3DLoader : IUnknown
{
    /**
        This method is called from RcUpdate3DLoader. In other words, the method
        is called from master thread that can access the Dependency Graph too
        as it could be required during the update
    */
    [id(1), helpstring("method Update")] HRESULT Update();
};


// CRn3DLoader
class ATL_NO_VTABLE CRn3DLoader : 
    public CComObjectRootEx<CComMultiThreadModel>,
    public IRsUnknownNode,
	public IRn3DLoader
{
public:
    CRn3DLoader()
    {
        m_dwFlags = RN3DLDRFLG_3DLNODE_NONE;
        m_dwSyncTime = 0;
        m_hTimerQueue = INVALID_HANDLE_VALUE;
        m_hSyncTimer = INVALID_HANDLE_VALUE;
	}

    BEGIN_COM_MAP(CRn3DLoader)
        COM_INTERFACE_ENTRY(IRn3DLoader)
        COM_INTERFACE_ENTRY(IRsUnknownNode)
        COM_INTERFACE_ENTRY2(IUnknown, IRsUnknownNode)
        COM_INTERFACE_ENTRY2(IRsObject, IRsUnknownNode)
        COM_INTERFACE_ENTRY_AGGREGATE(DEF_GUIDNAME(IRnEncapsulator), m_pUnkAgg.p)
        COM_INTERFACE_ENTRY_AGGREGATE(DEF_GUIDNAME(IRsBaseNode), m_pUnkAgg.p)
        COM_INTERFACE_ENTRY_AGGREGATE_BLIND(m_pUnkAgg.p)    // Just for safety, used only for unknown interfaces
    END_COM_MAP()

    DECLARE_GET_CONTROLLING_UNKNOWN()
    DECLARE_PROTECT_FINAL_CONSTRUCT()

    HRESULT FinalConstruct();

    void FinalRelease() 
    {
        m_pUnkAgg.Release();
    }

public:
    // IRsObject
    RS_DECLARE_IRS_OBJECT(IRn3DLoader, L"3D Loader Node")

    // IRsUnknownNode
    STDMETHOD(OnGetValue)(CONID conID, IRsDataCache* pDataCache, VARIANT* pVtData, RtBool* pHandled);
    STDMETHOD(OnSetValue)(CONID conID, IRsDataCache* pDataCache, VARIANT* pvtData, RtBool* pHandled);
    STDMETHOD(OnDefaultValue)(CONID conID, VARIANT* pVtData, RtBool* pHandled);
    STDMETHOD(OnInvalidate)(CONID conID, RtBool* pHandled);
    STDMETHOD(OnInitialize)(void);
    STDMETHOD(OnLoadDefault)(void);
    STDMETHOD(OnDestroy)(void);

    //IRn3DLoader
    STDMETHOD(Update)();

public:
    HRESULT ActivateTimer(RtDWORD dwSyncTime);
    HRESULT DeactivateTimer(void);
    HRESULT SendUpdateCommand(void);

private:
    static VOID CALLBACK SyncCallback(PVOID lpParameter, BOOLEAN TimerOrWaitFired);
    HRESULT AddConsIfNecessary(void);
    HRESULT CheckForDirChanges(void);

private:

    // Flags
    RtDWORD m_dwFlags;
    CComPtr<IUnknown>         m_pUnkAgg;
    CComPtr<IRsUnknownNode>   m_pEncapsUnkn;     // Aggregated Encapsulator's IRsUnknownNode interface
    CComPtr<IRf3DLoader>      m_sp3DLoaderFnSet; // 3DLoader functions set
    CComPtr<IRfFileSupport>   m_spRfFileSupport; // File Support function set
    CComPtr<IRsFileIOGeneric> m_spFileIOGeneric; // Generic file support function set

    HANDLE m_hTimerQueue;   // Handle to synchronization timer Queue
    HANDLE m_hSyncTimer;    // Handle to synchronization timer
    RtDWORD m_dwSyncTime;   // The current synchronization time

    CComBSTR m_bstrDirPath; // The current monitored directory

//    CAtlArray<CComBSTR> m_bstrModeratorTxtMsgs;         // Moderator's text messages displayed in message box
};
