// MotionSensor.h : Declaration of the CMotionSensor

#ifndef __MOTIONSENSOR_H_
#define __MOTIONSENSOR_H_

#include "resource.h"       // main symbols
#include "AppObject.h"
#include <atlwin.h>
#include "Advisers.h"
#include "ChannelObjectHelpers.h"
#include "VideoSurvCP.h"
#include "ChannelObjectsCP.h"
#include "CloneObjectImpl.h"

struct SAMPLEDESC {
	BYTE R;
	BYTE G;
	BYTE B;
};

/////////////////////////////////////////////////////////////////////////////
// CMotionSensor
class ATL_NO_VTABLE CMotionSensor : 
	public CComObjectRootEx<CComMultiThreadModel>,
	public CComCoClass<CMotionSensor, &CLSID_MotionSensor>,
	public CAppObjectRoot,
	public IStructureItemImpl,
	public IChannelObjectImpl,
	public IConnectionPointContainerImpl<CMotionSensor>,
	public CProxy_IStructureItemEvents<CMotionSensor>,
	public ISpecifyPropertyPagesImpl<CMotionSensor>,
	public ICloneObjectImpl,
	public IPersistStream,
	public IMotionSensor,
	public _IInputConnectorEvents,
	public _IOutputConnectorEvents,
	public _IChannelEvents,
	public _IConnectorEvents,
	public _IMotionSensorStateEvents,
	public CProxy_IGraphicsChannelObject<CMotionSensor>,
	protected CAdviseManager,
	public CProxy_IMultiStateEvents<CMotionSensor>,
	public IChannelMenuHandler,
	public IVssContextMenuHook
{
public:
	CMotionSensor() :
		CAppObjectRoot( CLSID_MotionSensor ),
	   IStructureItemImpl ( CLSID_MotionSensor ),
		m_hProcessThread( NULL ), m_hStopProcess( NULL ), m_hProcessImage( NULL ),
		m_nFPS(5), m_nTimerID(0), m_nAccMoving(0), m_bMotion(0), m_nCurSample (-1)
	{
	}

	STDMETHOD(FinalConstruct)();
	STDMETHOD(FinalRelease)();

	DECLARE_APP_OBJECT_SUPPORT()
	DECLARE_OBJECT_LOCKS_FUNCTIONS()
	DECLARE_VIEW_CHANGED_FUNCTION()
	DECLARE_ADVISE_MANAGER_SUPPORT()
	DECLARE_GRAPICS_OBJECT()

DECLARE_REGISTRY_RESOURCEID(IDR_MOTIONSENSOR)

DECLARE_PROTECT_FINAL_CONSTRUCT()

BEGIN_COM_MAP(CMotionSensor)
	COM_INTERFACE_ENTRY(IAppObject)
	COM_INTERFACE_ENTRY(IChannelMenuHandler)
	ISTRUCTUREITEMIMPL_ENTRIES
	ICHANNELOBJECTIMPL_ENTRIES
	COM_INTERFACE_ENTRY_IMPL(IConnectionPointContainer)
	COM_INTERFACE_ENTRY(IMotionSensor)
	COM_INTERFACE_ENTRY(IPersistStream)
	COM_INTERFACE_ENTRY(ICloneObject)
	COM_INTERFACE_ENTRY(ISpecifyPropertyPages)
	COM_INTERFACE_ENTRY(_IInputConnectorEvents)
	COM_INTERFACE_ENTRY(_IOutputConnectorEvents)
	COM_INTERFACE_ENTRY(_IChannelEvents)
	COM_INTERFACE_ENTRY(_IConnectorEvents)
	COM_INTERFACE_ENTRY(_IMotionSensorStateEvents)
END_COM_MAP()

BEGIN_CONNECTION_POINT_MAP(CMotionSensor)
	CONNECTION_POINT_ENTRY(IID__IStructureItemEvents)
	CONNECTION_POINT_ENTRY(IID__IGraphicsChannelObject)
	ICHANNELOBJECTIMPL_EVENTS
END_CONNECTION_POINT_MAP()

BEGIN_PROP_MAP(CMotionSensor)
	PROP_PAGE(CLSID_StructureItemPage)
	PROP_PAGE(CLSID_MultiStatePropPage)
END_PROP_MAP()

	virtual HRESULT RegisterCustomControls() { return S_OK; };
	virtual void UnregisterCustomControls() { return; };

	virtual void OnAddConnector( IConnector* pIConnector );
	virtual void OnRemoveConnector( IConnector* pIConnector );

// IMotionSensor
public:

// IStructureItem
public:
	STDMETHOD(Init)();
	STDMETHOD(PostInit)();
	STDMETHOD_(void,PreClose)();
	STDMETHOD_(void,Close)();
	STDMETHOD(get_SIName)(BSTR * pVal) {
		return m_bsSIName.CopyTo( pVal );
	}
	STDMETHOD(put_SIName)(BSTR newVal) {
		m_bsSIName = newVal;
		Fire_OnStructureItemNameChanged( this );
		return S_OK;
	}
	STDMETHOD(get_SIDescription)(BSTR * pVal) {
		return m_bsSIDescr.CopyTo( pVal );
	}
	STDMETHOD(put_SIDescription)(BSTR newVal) {
		m_bsSIDescr = newVal;
		Fire_OnStructureItemDescriptionChanged( this );
		return S_OK;
	}

protected:
	CComBSTR
		m_bsSIName,
		m_bsSIDescr;

// IGraphicsChannelObject
public:
	STDMETHOD(GetToolTipInfo)(IConnector *pIConnector,	BSTR *pTitle, BSTR *pText ) {
		CComBSTR bsTemp="Motion detector", bsTemp2="Working";
		bsTemp.CopyTo(pTitle); bsTemp2.CopyTo(pText);
		return S_OK;
	}

// IPersistStream
public:
	STDMETHOD(Load)(IStream *pStm);
	STDMETHOD(Save)(IStream *pStm, BOOL fClearDirty);
	STDMETHOD(GetSizeMax)(ULARGE_INTEGER *pcbSize) {
		if ( !pcbSize ) return E_POINTER;
		pcbSize->QuadPart = 0;
		return S_OK;
	}
	STDMETHOD(GetClassID)( CLSID *pClassID ) {
		return CopyClassValueTo( this, m_ClsID, pClassID );
	}
	STDMETHOD(IsDirty)() {
		return S_FALSE;
	}

private:
	STDMETHOD(LoadVersion0)(IStream *pStm);
	STDMETHOD(LoadVersion1)(IStream *pStm);

// IChannelMenuHandler
public:
	STDMETHOD(ProcessChannelEditorContextMenu)( IN IVssContextMenu* pIVssContextMenu );
	STDMETHOD(ProcessDisplayContextMenu)( IN IVssContextMenu* pIVssContextMenu ) {
		return E_NOTIMPL;
	}

// ICloneObject
public:
	STDMETHOD(Assign)(IUnknown* pSourceObj);
	STDMETHOD(AssignPart)(REFIID riid, IUnknown *pSource);
	STDMETHOD(EraseCloneHistory)();

// IVssContextMenuHook
public:
	STDMETHOD(ExecuteCommand)( UINT nID );

// _IInputConnectorEvents
public:
	STDMETHOD_(void, OnDataReceived)(IInputConnector * pIConnector, IUnknown* pDataUnk);

// _IOutputConnectorEvents
public:
	STDMETHOD_(void,OnStateChanged)(IOutputConnector* pIConnector);

// _IMultiStateEvents
public:
	virtual void _OnActiveStateChanged( IN IUnknown* pStateUnk );

// _IConnectorEvents
public:
	STDMETHOD_(VOID, OnConnected)(IConnector * pIConnector);
	STDMETHOD_(VOID, OnDisconnected)(IConnector * pIConnector);
	STDMETHOD_(VOID, OnOffsetChanged)(IConnector * pIConnector, tagPOINT newVal) {}
	STDMETHOD_(VOID, OnAlignChanged)(IConnector * pIConnector, ALIGN_TYPE newVal) {}

// _IChannelEvents
public:
	STDMETHOD_(void,OnTransferModeChanged)( CHANNEL_MODE newMode );

// _IMotionSensorStateEvents
public:
	STDMETHOD_(void,OnDetectionRateChanged)(IMotionSensorProperties * pState);
	STDMETHOD_(void,OnColorSensivityChanged)(IMotionSensorProperties * pState) {};
	STDMETHOD_(void,OnBrightnesSensivityChanged)(IMotionSensorProperties * pState) {};
	STDMETHOD_(void,OnSensivityChanged)(IMotionSensorProperties * pState) {};
	STDMETHOD_(void,OnResponceDelayChanged)(IMotionSensorProperties * pState) {};

// internal object implementation
protected:
	BOOL StartProcessThread();
	void StopProcessThread();
	static UINT __stdcall ProcessData( void* pParams );

	HRESULT SetupFPSTimer();

	HRESULT PreProcessImage( CComPtr<IImageData> oImageData, C2DArray<SAMPLEDESC>& arSamples );

private:
	CComQIPtr<IMathFactory>
		m_oMath;

	CComQIPtr<IInputConnector>
		m_oVideoInput;

	CComQIPtr<IOutputConnector>
		m_oSensorOutput;

	CComQIPtr<IOutputConnector>
		m_oVideoOutput;

	CComQIPtr<IGroupData>
		m_oCurFrame;

	C2DArray<SAMPLEDESC>
		m_arSamples[2];

	long
		m_nCurSample;

	long
		m_nResample;

	HANDLE
		m_hProcessThread,
		m_hStopProcess,
		m_hProcessImage,
		m_hTimerEvent,
		m_hVideoOutReady;

	long
		m_nTimerID;

	BOOL
		m_bMotion;

	long 
		m_nAccMoving;

	long
		m_nFPS;

	CHANNEL_MODE
		m_TransferMode;
};

#endif //__MOTIONSENSOR_H_

