#include <apps/Common/wxAbstraction.h>
#include "WizardSaturation.h"
#include <wx/slider.h>

using namespace std;

//=============================================================================
//============== Implementation WizardSaturation ==============================
//=============================================================================
BEGIN_EVENT_TABLE(WizardSaturation, OkAndCancelDlg)
	EVT_CHECKBOX(widCBEnable, WizardSaturation::OnCBEnable)
	EVT_COMMAND_SCROLL_THUMBTRACK(widSLSaturation, WizardSaturation::OnSLSaturation)
	EVT_SPINCTRL(widSCSaturation, WizardSaturation::OnSCSaturationChanged)

#ifdef BUILD_WITH_TEXT_EVENTS_FOR_SPINCTRL // BAT: Unfortunately on linux wxWidgets 2.6.x - ??? handling these messages will cause problems, while on Windows not doing so will not always update the GUI as desired :-(
		EVT_TEXT(widSCSaturation, WizardSaturation::OnSCSaturationTextChanged)
#endif // #ifdef BUILD_WITH_TEXT_EVENTS_FOR_SPINCTRL
END_EVENT_TABLE()

//-----------------------------------------------------------------------------
WizardSaturation::WizardSaturation( wxWindow* pParent, const wxString& title )
: OkAndCancelDlg(pParent, widMainFrame, title, wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER | wxMAXIMIZE_BOX | wxMINIMIZE_BOX)
//-----------------------------------------------------------------------------
{

}

//-----------------------------------------------------------------------------
void WizardSaturation::CreateGUI( void )
//-----------------------------------------------------------------------------
{
	/*
		|-------------------------------------|
		| pTopDownSizer                       |
		|                spacer               |
		| |---------------------------------| |
		| | slider  spin control            | |
		| |---------------------------------| |
		|                spacer               |
		| |---------------------------------| |
		| | saturation hints                | |
		| |---------------------------------| |
		|                spacer               |
		| |---------------------------------| |
		| | pButtonSizer                    | |
		| |---------------------------------| |
		|-------------------------------------|
	*/

	wxPanel* pPanel = new wxPanel(this);

	pCBEnable_ = new wxCheckBox(pPanel, widCBEnable, wxT("Enable"));
	pCBEnable_->SetToolTip( wxT("Enables/disables the color twist matrix for saturation adjustment") );
	pSLSaturation_ = new wxSlider(pPanel, widSLSaturation, 1000, -10000, 10000, wxDefaultPosition, wxSize(150, -1), wxSL_HORIZONTAL);

	wxBoxSizer* pSaturationControlsSizer = new wxBoxSizer(wxHORIZONTAL);
	pSaturationControlsSizer->Add( new wxStaticText(pPanel, wxID_ANY, wxT(" Saturation:")) );
	pSaturationControlsSizer->Add( pSLSaturation_, wxSizerFlags().Expand() );
	pSCSaturation_ = new wxSpinCtrlDbl();
	pSCSaturation_->Create( pPanel, widSCSaturation, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, -10., 10., 1., 0.001, wxSPINCTRLDBL_AUTODIGITS, wxT("%.3f") );
	pSCSaturation_->SetMode( mDouble );
	pSaturationControlsSizer->Add( pSCSaturation_, wxSizerFlags().Expand() );

	wxFont fixedPitchFont(10, wxFONTFAMILY_MODERN, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL);
	fixedPitchFont.SetWeight( wxFONTWEIGHT_BOLD );
	fixedPitchFont.SetUnderlined( true );
	wxTextAttr fixedPitchStyle;
	fixedPitchStyle.SetFont( fixedPitchFont );
	wxTextCtrl* pSaturationHints = new wxTextCtrl(pPanel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE | wxSUNKEN_BORDER | wxTE_RICH | wxTE_READONLY);
	WriteToTextCtrl( pSaturationHints, wxT("Saturation Formula:\n"), fixedPitchStyle );
	fixedPitchFont.SetWeight( wxFONTWEIGHT_NORMAL );
	fixedPitchFont.SetUnderlined( false );
	fixedPitchStyle.SetFont( fixedPitchFont );
	WriteToTextCtrl( pSaturationHints, wxT(" [0.299 + 0.701*K       , 0.587*(1-K) , 0.114*(1-K)     ]\n"), fixedPitchStyle );
	WriteToTextCtrl( pSaturationHints, wxT(" [0.299*(1-K) + 0.701*K , 0.587       , 0.114*(1-K)     ]\n"), fixedPitchStyle );
	WriteToTextCtrl( pSaturationHints, wxT(" [0.299*(1-K) + 0.701*K , 0.587*(1-K) , 0.114 + 0.886*K ]\n"), fixedPitchStyle );
	WriteToTextCtrl( pSaturationHints, wxT("\n"), fixedPitchStyle );
	WriteToTextCtrl( pSaturationHints, wxT("K is the saturation factor\n"), fixedPitchStyle );
	WriteToTextCtrl( pSaturationHints, wxT("K > 1 increases saturation\n"), fixedPitchStyle );
	WriteToTextCtrl( pSaturationHints, wxT("K = 1 means no change\n"), fixedPitchStyle );
	WriteToTextCtrl( pSaturationHints, wxT("0 < K < 1 decreases saturation\n"), fixedPitchStyle );
	WriteToTextCtrl( pSaturationHints, wxT("K = 0 produces B&W\n"), fixedPitchStyle );
	WriteToTextCtrl( pSaturationHints, wxT("K < 0 inverts color\n"), fixedPitchStyle );
	pSaturationHints->ScrollLines( -(256*256) ); // make sure the text control always shows the beginning of the help text

	wxBoxSizer* pTopDownSizer = new wxBoxSizer(wxVERTICAL);
	pTopDownSizer->AddSpacer( 10 );
	pTopDownSizer->Add( pCBEnable_ );
	pTopDownSizer->AddSpacer( 10 );
	pTopDownSizer->Add( pSaturationControlsSizer );
	pTopDownSizer->AddSpacer( 10 );
	pTopDownSizer->Add( pSaturationHints, wxSizerFlags(3).Expand() );
	pTopDownSizer->AddSpacer( 10 );
	AddButtons( pPanel, pTopDownSizer, true );
	FinalizeDlgCreation( pPanel, pTopDownSizer );
	SetSize( 560, 360 );
}

//=============================================================================
//============== Implementation WizardSaturationViaColorTwist =================
//=============================================================================
//-----------------------------------------------------------------------------
WizardSaturationViaColorTwist::WizardSaturationViaColorTwist( wxWindow* pParent, const wxString& title, mvIMPACT::acquire::Device* pDev )
: WizardSaturation(pParent, title), ip_(pDev)
//-----------------------------------------------------------------------------
{
	CreateGUI();
	pCBEnable_->SetValue( ( ip_.colorTwistEnable.read() == bTrue ) ? true : false );
}

//-----------------------------------------------------------------------------
void WizardSaturationViaColorTwist::ApplySaturation( const bool boEnable, const double K )
//-----------------------------------------------------------------------------
{
	try
	{
		ip_.colorTwistEnable.write( boEnable ? bTrue : bFalse );
		ip_.setSaturation( K );
	}
	catch( const ImpactAcquireException& e )
	{
		wxMessageDialog errorDlg(NULL, wxString::Format(wxT("Failed to apply saturation(Error: %s(%s))"), ConvertedString(e.getErrorString()).c_str(), ConvertedString(e.getErrorCodeAsString()).c_str()), wxT("Error"), wxOK | wxICON_INFORMATION);
	}
}

//=============================================================================
//============== Implementation WizardSaturationViaColorTransformationControl =
//=============================================================================
//-----------------------------------------------------------------------------
WizardSaturationViaColorTransformationControl::WizardSaturationViaColorTransformationControl( wxWindow* pParent, const wxString& title, mvIMPACT::acquire::Device* pDev )
: WizardSaturation(pParent, title), ctc_(pDev)
//-----------------------------------------------------------------------------
{
	CreateGUI();
	pCBEnable_->SetValue( ( ctc_.colorTransformationEnable.read() == bTrue ) ? true : false );
}

//-----------------------------------------------------------------------------
void WizardSaturationViaColorTransformationControl::ApplySaturation( const bool boEnable, const double K )
//-----------------------------------------------------------------------------
{
	try
	{
		ctc_.colorTransformationEnable.write( boEnable ? bTrue : bFalse );
		std::vector<double> row(3, 0.);
		row[0] = 0.299       + 0.701*K;
		row[1] = 0.587*(1-K);
		row[2] = 0.114*(1-K);
		ctc_.colorTransformationValueSelector.writeS( "Gain00" );
		ctc_.colorTransformationValue.write( row[0] );
		ctc_.colorTransformationValueSelector.writeS( "Gain01" );
		ctc_.colorTransformationValue.write( row[1] );
		ctc_.colorTransformationValueSelector.writeS( "Gain02" );
		ctc_.colorTransformationValue.write( row[2] );
		row[0] = 0.299*(1-K);
		row[1] = 0.587       + 0.413*K;
		row[2] = 0.114*(1-K);
		ctc_.colorTransformationValueSelector.writeS( "Gain10" );
		ctc_.colorTransformationValue.write( row[0] );
		ctc_.colorTransformationValueSelector.writeS( "Gain11" );
		ctc_.colorTransformationValue.write( row[1] );
		ctc_.colorTransformationValueSelector.writeS( "Gain12" );
		ctc_.colorTransformationValue.write( row[2] );
		row[0] = 0.299*(1-K);
		row[1] = 0.587*(1-K);
		row[2] = 0.114       + 0.886*K;
		ctc_.colorTransformationValueSelector.writeS( "Gain20" );
		ctc_.colorTransformationValue.write( row[0] );
		ctc_.colorTransformationValueSelector.writeS( "Gain21" );
		ctc_.colorTransformationValue.write( row[1] );
		ctc_.colorTransformationValueSelector.writeS( "Gain22" );
		ctc_.colorTransformationValue.write( row[2] );
	}
	catch( const ImpactAcquireException& e )
	{
		wxMessageDialog errorDlg(NULL, wxString::Format(wxT("Failed to apply saturation(Error: %s(%s))"), ConvertedString(e.getErrorString()).c_str(), ConvertedString(e.getErrorCodeAsString()).c_str()), wxT("Error"), wxOK | wxICON_INFORMATION);
	}
}
