#include "svncommand.h"
#include "environmentconfig.h"
#include "subversion_strings.h"
#include "svn_console.h"
#include "globals.h"
#include "subversion2.h"

BEGIN_EVENT_TABLE(SvnCommand, wxEvtHandler)
EVT_COMMAND(wxID_ANY, wxEVT_PROC_DATA_READ,  SvnCommand::OnProcessOutput)
EVT_COMMAND(wxID_ANY, wxEVT_PROC_TERMINATED, SvnCommand::OnProcessTerminated)
END_EVENT_TABLE()

SvnCommand::SvnCommand(Subversion2* plugin)
		: m_process(NULL)
		, m_handler(NULL)
		, m_plugin (plugin)
{
}

SvnCommand::~SvnCommand()
{
	ClearAll();
}

bool SvnCommand::Execute(const wxString &command, const wxString &workingDirectory, SvnCommandHandler *handler, Subversion2 *plugin)
{
	// Dont run 2 commands at the same time
	if(m_process) {
		if(handler) {
			//handler->GetPlugin()->GetShell()->AppendText(svnANOTHER_PROCESS_RUNNING);
			delete handler;
		}
		return false;
	}

	ClearAll();

	// Wrap the command in the OS Shell
	wxString cmdShell (command);
	WrapInShell(cmdShell);


	// Apply the environment variables before executing the command
	StringMap om;
	om[wxT("LC_ALL")] = wxT("C");

	bool useOverrideMap = m_plugin->GetSettings().GetFlags() & SvnUsePosixLocale;
	EnvSetter env(m_plugin->GetManager()->GetEnv(), useOverrideMap ? &om : NULL);


	m_process = CreateAsyncProcess(this, command, IProcessCreateDefault, workingDirectory);
	if ( !m_process ) {
		return false;
	}
	m_workingDirectory = workingDirectory.c_str();
	m_command          = command.c_str();
	m_handler          = handler;
	return true;
}

void SvnCommand::OnProcessOutput(wxCommandEvent& event)
{
	ProcessEventData *ped = (ProcessEventData*)event.GetClientData();
	if( ped ) {
		m_output.Append(ped->GetData().c_str());
		delete ped;
	}
}

void SvnCommand::OnProcessTerminated(wxCommandEvent& event)
{
	ProcessEventData *ped = (ProcessEventData*)event.GetClientData();
	if( ped ) {
		delete ped;
	}

	if (m_handler) {

		if(m_handler->TestLoginRequired(m_output)) {
			// re-issue the last command but this time with login dialog
			m_handler->GetPlugin()->GetConsole()->AppendText(_("Authentication failed. Retrying...\n"));
			m_handler->ProcessLoginRequired(m_workingDirectory);

		} else if(m_handler->TestVerificationFailed(m_output)) {
			m_handler->GetPlugin()->GetConsole()->AppendText(_("Server certificate verification failed. Retrying...\n"));
			m_handler->ProcessVerificationRequired();

		} else {
			// command ended successfully, invoke the "success" callback
			m_handler->Process(m_output);
		}

		delete m_handler;
		m_handler = NULL;
	}

	if (m_process) {
		delete m_process;
		m_process = NULL;
	}
}

void SvnCommand::ClearAll()
{
	m_workingDirectory.Clear();
	m_command.Clear();
	m_output.Clear();
}
