// InputBuffer.h : Declaration of the cInputBuffer

#ifndef __INPUTBUFFER_H_
#define __INPUTBUFFER_H_

#include "resource.h"       // main symbols
#include "DecalInputCP.h"

/////////////////////////////////////////////////////////////////////////////
// cInputBuffer
class ATL_NO_VTABLE cInputBuffer : 
	public CComObjectRootEx<CComSingleThreadModel>,
	public CComCoClass<cInputBuffer, &CLSID_InputBuffer>,
	public IConnectionPointContainerImpl<cInputBuffer>,
   public IProvideClassInfo2Impl< &CLSID_InputBuffer, &DIID_IInputBufferEvents, &LIBID_DecalInput >,
	public IDispatchImpl<IInputBuffer, &IID_IInputBuffer, &LIBID_DecalInput>,
   public IInputActionSite,
   public CProxyIInputBufferEvents< cInputBuffer >
{
public:
	cInputBuffer()
      : m_bWaiting( false ),
      m_nUntilTime( 0 )
	{
	}

   void FinalRelease();

   _variant_t m_tag;

   enum eEntryType
   {
      eExecute,
      ePush,
      ePop
   };

   struct cEntry
   {
      eEntryType m_eType;
      CComPtr< IInputAction > m_pAction;
   };

   typedef std::list< cEntry > cEntryList;
   cEntryList m_entries;

   typedef std::stack< cEntry * > cEntryStack;
   cEntryStack m_insertstack, m_playstack;
   cEntryList::iterator m_play;

   bool checkState();
   HRESULT addItem( BSTR strInit, IInputAction **ppAction );
   void runActions();

   // Delay information
   bool m_bWaiting;
   long m_nUntilTime;

DECLARE_REGISTRY_RESOURCEID(IDR_INPUTBUFFER)

DECLARE_PROTECT_FINAL_CONSTRUCT()

BEGIN_COM_MAP(cInputBuffer)
   COM_INTERFACE_ENTRY(IInputActionSite)
	COM_INTERFACE_ENTRY(IInputBuffer)
	COM_INTERFACE_ENTRY(IDispatch)
   COM_INTERFACE_ENTRY(IProvideClassInfo)
   COM_INTERFACE_ENTRY(IProvideClassInfo2)
	COM_INTERFACE_ENTRY_IMPL(IConnectionPointContainer)
END_COM_MAP()
BEGIN_CONNECTION_POINT_MAP(cInputBuffer)
   CONNECTION_POINT_ENTRY(DIID_IInputBufferEvents)
END_CONNECTION_POINT_MAP()

public:
   // IInputActionSite
	STDMETHOD(Delay)(long Time, VARIANT_BOOL Advance);
	STDMETHOD(FireEvent)(long nEventID, VARIANT vParam);
	STDMETHOD(MoveMouse)(long X, long Y);
	STDMETHOD(get_Service)(/*[out, retval]*/ IInputService * *pVal);

   // IInputBuffer
	STDMETHOD(Stop)();
	STDMETHOD(Run)();
	STDMETHOD(get_CanRun)(/*[out, retval]*/ VARIANT_BOOL *pVal);
	STDMETHOD(Pop)();
	STDMETHOD(Push)(BSTR Command);
	STDMETHOD(Add)(BSTR Command);
	STDMETHOD(get_Tag)(/*[out, retval]*/ VARIANT *pVal);
	STDMETHOD(put_Tag)(/*[in]*/ VARIANT newVal);
};

#endif //__INPUTBUFFER_H_
