/*
 *  
 *  $Id: ventanacontrollogs.cpp $
 *  Ginkgo CADx Project
 *
 *  Copyright 2008-12 MetaEmotion S.L. All rights reserved.
 *  http://ginkgo-cadx.com
 *
 *  This file is licensed under LGPL v3 license.
 *  See License.txt for details
 *
 *
 */
#include <wx/wx.h>
#include <main/controllers/log4cplus/guiappender.h>
#include <main/controllers/configurationcontroller.h>
#include <api/internationalization/internationalization.h>
#include <set>
#include <fstream>
#include <sstream>
#include <wx/strconv.h>
#include <wx/log.h>
#include <wx/filedlg.h>
#include <wx/msgdlg.h>

#include "ventanacontrollogs.h"

#include <resources/ginkgoresourcesmanager.h>
#define LOGGER "VentanaControlLogs"
#include <main/controllers/controladorlog.h>
#include <main/entorno.h>

IMPLEMENT_DYNAMIC_CLASS(LogAsyncEvent, wxEvent)

#define COL_FECHA           0
#define COL_NIVEL           1
#define COL_MENSAJE			2

namespace GNC {
	namespace GUI {

		VentanaControlLogs* VentanaControlLogs::m_pInstance = NULL;

		VentanaControlLogs* VentanaControlLogs::Instance()
		{
			if(m_pInstance == NULL) {
				m_pInstance = new VentanaControlLogs();
			}
			return m_pInstance;
		}

		void VentanaControlLogs::CerrarSiAbierta()
		{
			if(m_pInstance != NULL)
			{
				m_pInstance->Close(true);
				m_pInstance = NULL;
			}
		}

		void VentanaControlLogs::Refrescar()
		{
		}

		//region Interfaz ILogger

		void VentanaControlLogs::Append(const GNC::GCS::Logging::LogEvent& le)
		{
			LogAsyncEvent lae(le);
			this->AddPendingEvent(lae);
		}

		//endregion

		VentanaControlLogs::VentanaControlLogs() : VentanaControlLogsBase(NULL)
		{
			m_needRefresh = false;

			wxIcon icono;
			icono.CopyFromBitmap(GinkgoResourcesManager::Logos::GetLogoGinkgo32x32());
			this->SetIcon(icono);

			// Setup del combobox de niveles

			GNC::GCS::IControladorLog::Instance()->GetLogLevelsMap(m_MapaLogLevels);

			int i = 0;

			for (GNC::GCS::IControladorLog::MapaLogLevels::iterator it = m_MapaLogLevels.begin(); it != m_MapaLogLevels.end(); ++it, i++)
			{
				m_pComboNivel->Insert(wxString::FromUTF8((*it).second.c_str()), 0);
			}

			// Setup del nivel actual

			wxString nivelActual = wxString::FromUTF8(m_MapaLogLevels[GNC::GCS::IControladorLog::Instance()->GetActiveLogLevel()].c_str());

			bool notfound = true;
			for (int i = 0; notfound && i < (int)m_pComboNivel->GetCount(); i++)
			{
				if (nivelActual == m_pComboNivel->GetString(i) ) {
					m_pComboNivel->Select(i);
					notfound = false;
				}
			}

			this->Connect(wxEVT_LOG_ASYNC, LogAsyncEventHandler(VentanaControlLogs::OnLogAsync), NULL, this);

			this->Connect( m_menuItemGuardar->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( VentanaControlLogs::OnGuardarRegistros ) );
			this->Connect( m_menuItemLimpiar->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( VentanaControlLogs::OnLimpiarClick ) );
            this->Connect( m_menuItemSalir->GetId(), wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler( VentanaControlLogs::OnSalirClick ) );

			Layout();

			gnkLog4cplus::GUIAppender::Instance()->Attach(this);

			Show();
		}

		VentanaControlLogs::~VentanaControlLogs()
		{
			m_pInstance = NULL;
			gnkLog4cplus::GUIAppender::Instance()->Attach(NULL);

		}

		void VentanaControlLogs::OnClose( wxCloseEvent& event )
		{
			this->Disconnect(wxEVT_LOG_ASYNC, LogAsyncEventHandler(VentanaControlLogs::OnLogAsync), NULL, this);
			gnkLog4cplus::GUIAppender::Instance()->Attach(NULL);

			event.Skip();
		}

		void VentanaControlLogs::OnLogAsync(LogAsyncEvent& event)
		{
			wxCSConv conv(wxFONTENCODING_UTF8);
			wxString str(event.LogEvent.formattedmsg.c_str(), conv);
			if (str.IsEmpty() && !event.LogEvent.formattedmsg.empty()) { // Fallback: CONV TO ISO
				wxCSConv convLatin1(wxFONTENCODING_ISO8859_1);
				str = wxString(event.LogEvent.formattedmsg.c_str(), convLatin1);
			}
			m_pRegistros->AppendText(str);
			m_needRefresh = true;
		}

		void VentanaControlLogs::OnInternalIdle()
		{
			if (m_needRefresh) {
				m_pRegistros->Refresh(true);
				m_needRefresh = false;
			}
		}

		void VentanaControlLogs::OnGuardarRegistros( wxCommandEvent& /*event*/ )
		{
			wxFileDialog seleccionarFichero (this, _("Save logs"), wxT(""), wxT(""), _("Log file (*.log) | *.log | Text file (*.txt) | *.txt"),wxFD_SAVE);
			int response = seleccionarFichero.ShowModal();
			if (response == wxID_OK) {
				if(wxFileExists(seleccionarFichero.GetPath())) {
					response = wxMessageBox(_("File exists\nWould you like to overwrite it?"),_("Overwrite"),wxYES_NO | wxCANCEL,this);
					if(response != wxYES) {
						return;
					}
				}

				std::ofstream fout;
				std::ostringstream sout;
				try {
					fout.open(TOPATH(seleccionarFichero.GetPath()));
				}
				catch (std::exception& ex)
				{
					sout << _Std("File couldn't be stored ") << seleccionarFichero.GetPath().ToUTF8() << " : " << ex.what();
					wxMessageBox(wxString::FromUTF8(sout.str().c_str()),_("Error"),wxICON_ERROR);
					return;
				}

				if (!fout)
				{
					sout << _Std("File couldn't be stored ") << seleccionarFichero.GetPath().ToUTF8();
					wxMessageBox(wxString::FromUTF8(sout.str().c_str()),_("Error"),wxICON_ERROR);
					return;
				}

				try {
					fout << m_pRegistros->GetValue().ToUTF8();
				}
				catch (std::exception& ex)
				{
					sout << _Std("File couldn't be stored ") << seleccionarFichero.GetPath().ToUTF8() << " : " << ex.what();
					wxMessageBox(wxString::FromUTF8(sout.str().c_str()),_("Error"),wxICON_ERROR);
					return;
				}

				try {
					fout.close();
				}
				catch (std::exception& ex)
				{
					sout << _Std("Could not write to file") << seleccionarFichero.GetPath().ToUTF8() << " : " << ex.what();
					wxMessageBox(wxString::FromUTF8(sout.str().c_str()),_("Error"),wxICON_ERROR);
				}
			}
		}

		void VentanaControlLogs::OnNivelChoice( wxCommandEvent& /*event*/ )
		{

			int nivel = GNC::GCS::IControladorLog::Instance()->GetLogLevelCode(std::string(m_pComboNivel->GetStringSelection().ToUTF8()));

			GNC::GCS::IControladorLog::Instance()->SetActiveLogLevel(nivel);
			GNC::GCS::ConfigurationController::Instance()->writeIntGeneral("/GinkgoCore/Log", "LogLevel", nivel);

		}

		void VentanaControlLogs::LimpiarRegistros()
		{
			m_pRegistros->Clear();
			gnkLog4cplus::GUIAppender::Instance()->clear();

		}

		void VentanaControlLogs::OnSalirClick( wxCommandEvent& /*event*/ )
		{
			Close();
		}

		void VentanaControlLogs::OnKeyDown( wxKeyEvent& event )
		{
			if (event.GetKeyCode() == WXK_ESCAPE) {
				Close();
				event.Skip(false);
			}
			else {
				event.Skip();
			}
		}
	}

}
