#include "addoptioncheckdlg.h"
#include "windowattrmanager.h"
#include <wx/tokenzr.h>
#include <wx/txtstrm.h>
#include <wx/sstream.h>
#include <list>
#include <algorithm> // std::find

AddOptionCheckDlg::AddOptionCheckDlg(wxWindow* parent, const wxString& title, const Compiler::CmpCmdLineOptions& cmpOptions, const wxString& value)
: AddOptionCheckDialogBase(parent, wxID_ANY, title)
, m_cmpOptions(cmpOptions)
{
	WindowAttrManager::Load(this, wxT("AddOptionCheckDlg"), NULL);

	// Fill the list of available options
	Compiler::CmpCmdLineOptions::const_iterator itOption = m_cmpOptions.begin();
	for ( ; itOption != m_cmpOptions.end(); ++itOption)
	{
		const Compiler::CmpCmdLineOption& cmpOption = itOption->second;
		m_checkListOptions->Append(cmpOption.help + wxT(" [") + cmpOption.name + wxT("]"));
	}
	
	// Update controls
	SetValue(value);
}

AddOptionCheckDlg::~AddOptionCheckDlg()
{
	WindowAttrManager::Save(this, wxT("AddOptionCheckDlg"), NULL);
}

void AddOptionCheckDlg::SetValue(const wxString& value)
{
	m_textCmdLn->SetValue(value);
	
	UpdateOptions();
	UpdateCmdLine();
}

wxString AddOptionCheckDlg::GetValue() const
{
	return m_textCmdLn->GetValue();
}

void AddOptionCheckDlg::OnOptionToggled( wxCommandEvent& event )
{
	UpdateCmdLine();
	UpdateOptions();
}

void AddOptionCheckDlg::OnOptionsText( wxCommandEvent& event )
{
	UpdateCmdLine();
}

void AddOptionCheckDlg::UpdateOptions()
{
	// Remove all check boxes
	m_checkListOptions->Freeze();
	
	for (unsigned int idx = 0; idx < m_checkListOptions->GetCount(); ++idx)
	{
		m_checkListOptions->Check(idx, false);
	}
	
	// Check all options entered 
	wxString customOptions;
	wxStringTokenizer tkz(m_textCmdLn->GetValue(), wxT(";"));
	while(tkz.HasMoreTokens())
	{
		wxString token = tkz.GetNextToken();
		token = token.Trim().Trim(false);
		if (!token.empty())
		{
			Compiler::CmpCmdLineOptions::const_iterator itOption = m_cmpOptions.find(token);
			if(itOption != m_cmpOptions.end())
			{
				const Compiler::CmpCmdLineOption& cmpOption = itOption->second;
				m_checkListOptions->Check(m_checkListOptions->FindString(cmpOption.help + wxT(" [") + cmpOption.name + wxT("]")));			
			}
			else
			{
				if(!customOptions.empty()) customOptions << wxT(";");
				customOptions << token;
			}
		}
	}
	m_textOptions->ChangeValue(customOptions);
	
	m_checkListOptions->Thaw();
}

void AddOptionCheckDlg::UpdateCmdLine()
{
	// Store all actual options
	std::list<wxString> options;
	wxStringInputStream input(m_textOptions->GetValue());
	wxTextInputStream text(input);
	while( !input.Eof() ) {
		wxString option = text.ReadLine().Trim().Trim(false);
		if (!option.empty())
		{
			options.push_back(option);
		}
	}
	
	// Read check box options
	for (unsigned int idx = 0; idx < m_checkListOptions->GetCount(); ++idx)
	{
		wxString value = m_checkListOptions->GetString(idx).AfterLast(wxT('[')).BeforeLast(wxT(']'));
		if (m_checkListOptions->IsChecked(idx))
		{
			// If the option doesn't exist actually, add it
			if (std::find(options.begin(), options.end(), value) == options.end())
			{
				//options.push_back(value.AfterLast(wxT('[')).BeforeLast(wxT(']')));
				options.insert(options.begin(), value);
			}
			else
				// uncheck the option if already defined manualy
				m_checkListOptions->Check(idx, false);
		}
	}
	
	// Update the options textctrl
	wxString value;
	std::list<wxString>::const_iterator itOption = options.begin();
	for ( ; itOption != options.end(); ++itOption)
	{
		if(!value.Contains(*itOption + wxT(";")))
		{
			if(!value.empty()) value << wxT(";");
			value << *itOption;
		}
	}
	m_textCmdLn->SetValue(value);
}

