//-----------------------------------------------------------------------------
#ifndef drawingCanvasH
#define drawingCanvasH drawingCanvasH
//-----------------------------------------------------------------------------
#include "DevData.h"
#include <wx/scrolwin.h>
#include <mvIMPACT_CPP/mvIMPACT_acquire.h>

//-----------------------------------------------------------------------------
template<typename T>
inline const T& saveAssign( const T& val, const T& min, const T& max )
//-----------------------------------------------------------------------------
{
	return ( ( val > max ) ? max : ( val < min ) ? min : val );
}

//-----------------------------------------------------------------------------
class DrawingCanvas : public wxScrolledWindow
//-----------------------------------------------------------------------------
{
	DECLARE_DYNAMIC_CLASS(DrawingCanvas)
	DECLARE_EVENT_TABLE()
protected:
	bool						m_boActive;
	mutable wxCriticalSection	m_critSect;
	virtual void	HandleSizeEvent( wxSizeEvent& e );
public:
	explicit		DrawingCanvas() {}
	explicit		DrawingCanvas( wxWindow* parent, wxWindowID id = -1, const wxPoint& pos = wxDefaultPosition,
						const wxSize& size = wxDefaultSize, long style = wxSUNKEN_BORDER,
						const wxString& name = wxT("DrawingCanvas"), bool boActive = false );
	bool			IsActive( void ) const { return m_boActive; }
	void			OnSize( wxSizeEvent& );
	virtual void	SetActive( bool boActive );
};

//-----------------------------------------------------------------------------
struct AOI
//-----------------------------------------------------------------------------
{
	wxRect							m_rect;
	wxColour						m_colour;
	wxString						m_description;
	const DrawingCanvas*	m_pOwner;
	explicit AOI() : m_rect(0,0,0,0), m_colour(0,0,0), m_description(wxEmptyString), m_pOwner(0) {}
	explicit AOI( const wxRect& r, const wxColour& c, const wxString& desc, const DrawingCanvas* const pOwner ) : m_rect(r), m_colour(c), m_description(desc), m_pOwner(pOwner) {}
};

class ImageCanvas;

//-----------------------------------------------------------------------------
struct PlotPoint
//-----------------------------------------------------------------------------
{
	int cnt_;
	int val_;
	PlotPoint( int cnt, int val ) : cnt_(cnt), val_(val) {}
	PlotPoint() : cnt_(0), val_(0) {}
};

//-----------------------------------------------------------------------------
struct NamedColour
//-----------------------------------------------------------------------------
{
	const wxColour* pColour_;
	wxString description_;
	NamedColour() : pColour_(0), description_(wxT("")) {}
	NamedColour( const wxColour* p, const wxString& d ) : pColour_(p), description_(d) {}
};

//-----------------------------------------------------------------------------
class PlotCanvas : public DrawingCanvas
//-----------------------------------------------------------------------------
{
	int				m_BorderWidth;
protected:
	int				m_ImageCount;
	int				m_UpdateFrequency;
public:
	explicit	PlotCanvas() {}
	explicit	PlotCanvas( wxWindow* parent, wxWindowID id = -1, const wxPoint& pos = wxDefaultPosition,
					const wxSize& size = wxDefaultSize, long style = wxSUNKEN_BORDER,
					const wxString& name = wxT("PlotCanvas"), bool boActive = false );
	bool		SetUpdateFrequency( int frequency );
	int			GetBorderWidth( void ) const { return m_BorderWidth; }
	void		SetBorderWidth( int borderWidth );
	//-----------------------------------------------------------------------------
	enum TUpdateLimit
	//-----------------------------------------------------------------------------
	{
		ulMin = 1,
		ulMax = 100
	};
};

class wxGrid;

//-----------------------------------------------------------------------------
class ImageAnalysisPlotCanvas : public PlotCanvas
//-----------------------------------------------------------------------------
{
public:
	enum TDisplayMethod
	{
		dmGraphical,
		dmNumerical
	};
private:
	wxColour			m_AOIColour;
	ImageCanvas*		m_pImageCanvas;
	wxString			m_ConfigName;
	bool				m_boAOIFullMode;
	TDisplayMethod		m_DisplayMethod;
	bool				SetAOI( const mvIMPACT::acquire::ImageBuffer* pIB, int x, int y, int w, int h );
protected:
	//-----------------------------------------------------------------------------
	template<typename _Ty>
	void AssignDisplayParameter( _Ty& parameter, const _Ty& newValue )
	//-----------------------------------------------------------------------------
	{
		if( parameter != newValue )
		{
			parameter = newValue;
			if( m_DisplayMethod == dmGraphical )
			{
				UpdateAnalysisOutput( true );
			}
		}
	}
	//-----------------------------------------------------------------------------
	enum
	//-----------------------------------------------------------------------------
	{
		VAL_COUNT_8_BIT = 256,
		VAL_COUNT_10_BIT = VAL_COUNT_8_BIT << 2,
		VAL_COUNT_12_BIT = VAL_COUNT_8_BIT << 4,
		VAL_COUNT_14_BIT = VAL_COUNT_8_BIT << 6,
		VAL_COUNT_16_BIT = VAL_COUNT_8_BIT << 8
	};
	//-----------------------------------------------------------------------------
	enum TPlane
	//-----------------------------------------------------------------------------
	{
		pRed = 0,
		pY = 0,
		pCb = 0,
		pEvenEven = 0,
		pChannel0Hor = 0,
		pChannel0 = 0,
		pGreen = 1,
		pU = 1,
		pCr = 1,
		pEvenOdd = 1,
		pChannel0Ver = 1,
		pChannel1 = 1,
		pBlue = 2,
		pV = 2,
		pOddEven = 2,
		pChannel1Hor = 2,
		pChannel2 = 2,
		pOddOdd = 3,
		pChannel1Ver = 3,
		pChannel2Hor = 4,
		pChannel2Ver = 5,
		PLANE_CNT
	};
	unsigned int		m_valCount;
	int					m_AOIx;
	int					m_AOIy;
	int					m_AOIw;
	int					m_AOIh;
	AOI*				m_pAOI;
	int					m_GridStepsX;
	int					m_GridStepsY;
	int					m_ChannelCount;
	mvIMPACT::acquire::TImageBufferPixelFormat m_pixelFormat;
	mvIMPACT::acquire::TBayerMosaicParity m_bayerParity;
	bool				m_boUnsupportedPixelFormat;
	static const wxColour	m_ADarkerKindOfGreen;
	NamedColour			m_Pens[PLANE_CNT];
	int					m_DrawStart_percent;
	int					m_DrawWindow_percent;
	wxGrid*				m_pNumericalDisplay;
	virtual void		CreateGridCustom( void );
	int					GetPercentageToDraw( void ) const { return ( ( 100 - m_DrawStart_percent ) < m_DrawWindow_percent ) ? ( 100 - m_DrawStart_percent ) : m_DrawWindow_percent; }
	void				GetDrawRange( unsigned int* pFrom, unsigned int* pTo ) const;
	virtual void		HandleSizeEvent( wxSizeEvent& e );
	bool				MustUpdate( const mvIMPACT::acquire::ImageBuffer* pIB, int plotChannelCount, int x, int y, int w, int h, bool boForceRefresh, bool* pboAOIChanged = 0, bool* pboImageFormatChanged = 0 );
	void				SetDefaultPens( void );
	void				SetBayerDescriptions( mvIMPACT::acquire::TBayerMosaicParity bayerParity );
	void				SetBayerPens( mvIMPACT::acquire::TBayerMosaicParity bayerParity );
	void				UpdateAnalysisOutput( bool boEraseBackground );
	virtual void		UpdateGrid( void );
public:
	explicit			ImageAnalysisPlotCanvas() {}
	explicit			ImageAnalysisPlotCanvas( wxWindow* parent, const wxString& configName, wxWindowID id = -1, const wxPoint& pos = wxDefaultPosition,
							const wxSize& size = wxDefaultSize, long style = wxSUNKEN_BORDER,
							const wxString& name = wxT("ImageAnalysisPlotCanvas"), bool boActive = false, int channelCount = 0 );
	void				CreateGrid( wxWindow* pParent );
	wxGrid*				GetGrid( void ) const { return m_pNumericalDisplay; }
	virtual wxString	GetGridValue( int row, int col ) const = 0;
	void				SetDisplayMethod( TDisplayMethod displayMethod );
	TDisplayMethod		GetDisplayMethod( void ) const { return m_DisplayMethod; }
	const wxString&		GetConfigName( void ) const { return m_ConfigName; }
	virtual void		RefreshData( const RequestData& data, int x = -1, int y = -1, int w = -1, int h = -1, bool boForceRefresh = false ) = 0;
	virtual void		SetActive( bool boActive );
	bool				IsAOIFullModeActive( void ) const { return m_boAOIFullMode; }
	void				SetAOIFullMode( bool boActive );
	void				SetAOIColour( const wxColour& );
	const AOI*			GetAOI( void ) const { return m_pAOI; }
	wxRect				GetAOIRect( void ) const { return wxRect(m_AOIx, m_AOIy, m_AOIw, m_AOIh); }
	virtual bool		HasPercentageWindow( void ) const { return false; }
	void				SetDrawStartPercent( int value_percent );
	void				SetDrawWindowWidthPercent( int value_percent );
	virtual bool		HasStepWidthParameter( void ) const { return false; }
	virtual bool		HasGridSteps( void ) const { return false; }
	void				SetGridSteps( int XSteps, int YSteps );
	void				RegisterImageCanvas( ImageCanvas* p );
};

#endif // drawingCanvasH
