#include "CFireFlierClientApp.hh"
#include "CDlgSrc.hh"
#include "fireflierIO.h"
#include <sstream>
#include <algorithm>
//#if FF_DEBUG
#include <iostream>
#include <iomanip.h>
//#endif
using namespace std;


CDlgSrc::CDlgSrc()
	: Gtk::Window()
	, m_textviewSrc(Gtk::TextBuffer::create())
{
	initGUI();

	ffIO.networkThread.signal_Src_avail().connect(m_signalSrcAvail.slot(true));
	m_signalSrcAvail.connect(SigC::slot(*this, &CDlgSrc::on_Src_avail));
}


CDlgSrc::~CDlgSrc()
{
#ifdef WITHGCONF
	if (m_gconfUI[strGConfUISrcDlg_remember].get_bool())
	{
		if (is_visible())
			save_pos_and_size();
		m_gconfUI.write();
	}
#endif
}

void CDlgSrc::initGUI()
{
	m_textviewSrc.set_editable(false);

	Gtk::VBox* vboxWhole = manage(new Gtk::VBox);
	Gtk::HBox* hboxDlgAction = manage(new Gtk::HBox(true, 5));
	hboxDlgAction->set_border_width(5);

	Gtk::ScrolledWindow* scrwnd = manage(new Gtk::ScrolledWindow);
	scrwnd->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
	scrwnd->add(m_textviewSrc);

	Gtk::Button* butOk = manage(new Gtk::Button(Gtk::Stock::CLOSE));
	hboxDlgAction->pack_start(*butOk, Gtk::PACK_EXPAND_WIDGET, 2);
	vboxWhole->pack_start(*scrwnd, Gtk::PACK_EXPAND_WIDGET, 0);
	vboxWhole->pack_start(*hboxDlgAction, Gtk::PACK_SHRINK, 0);

	add(*vboxWhole);
	set_modal(false);
	set_title(strAppTitle+"::Source");
	show_all_children();
	
#ifdef WITHGCONF	
	m_gconfUI.add_dir(gb_pGConfClient, strGConfUISrcDlg, SigC::slot(*this, &CDlgSrc::on_value_changed));
	on_value_changed("", Gnome::Conf::Value());
	signal_delete_event().connect(SigC::slot(*this, &CDlgSrc::on_delete));
	butOk->signal_clicked().connect(SigC::slot(*this, &CDlgSrc::on_butOk_clicked));
#else
	m_textviewSrc.modify_font(Pango::FontDescription("Courier 10 Pitch"));
	resize(600, 200);
	butOk->signal_clicked().connect(SigC::slot(*this, &CDlgSrc::hide));
#endif
}

#ifdef WITHGCONF
bool CDlgSrc::on_delete(GdkEventAny*)
{
	save_pos_and_size();
	return false;
}

void CDlgSrc::on_butOk_clicked()
{
	save_pos_and_size();
	hide();
}

void CDlgSrc::save_pos_and_size()
{
	int nX, nY;
	get_position(nX, nY);
	m_gconfUI[strGConfUISrcDlg_posX].set(nX);
	m_gconfUI[strGConfUISrcDlg_posY].set(nY);
	m_gconfUI[strGConfUISrcDlg_sizeX].set(get_width());
	m_gconfUI[strGConfUISrcDlg_sizeY].set(get_height());
}

void CDlgSrc::on_value_changed(const ustring& strKey, const Gnome::Conf::Value& value)
{
	bool bFFConcerned = (strKey.find(strGConfUISrcDlg) != ustring::npos);
#if FF_DEBUG
	cerr << "CDlgSrc::on_value_changed(): strKey=" << strKey << endl;
	cerr << "CDlgSrc::on_value_changed()::bFFConcerned=" << bFFConcerned << endl;
#endif
	if (bFFConcerned && strKey.length())
		m_gconfUI[strKey] = value;
	if (bFFConcerned || !strKey.length())
	{
#if FF_DEBUG
		cerr << "CDlgSrc::on_value_changed(): moving window" << endl;
#endif
		move(m_gconfUI[strGConfUISrcDlg_posX].get_int(), m_gconfUI[strGConfUISrcDlg_posY].get_int());
		resize(m_gconfUI[strGConfUISrcDlg_sizeX].get_int(), m_gconfUI[strGConfUISrcDlg_sizeY].get_int());
		Pango::FontDescription font(m_gconfUI[strGConfUISrcDlg_font].get_string());
		m_textviewSrc.modify_font(font);
	}
}
#endif // WITHGCONF

void CDlgSrc::on_Src_avail(const char* szMsg, int nLen)
{
	m_textviewSrc.get_buffer()->set_text(formatMsg(szMsg, nLen));
}


ustring CDlgSrc::formatMsg(const char* src, int nLen)
{
	const char* const HEX = "0123456789abcdef";

    if (!src || !nLen)
		return "";

	ostringstream result;
    int pos = 0;
    
    while (pos < nLen)
    {
		// make up a hex row
		for (int i = 0; i < 16; i++)
		{
			if (i == 8)
				result << "  ";
			else if (i%4 == 0)
					result << ' ';
			if (i+pos < nLen)
			  result << hex << src[i+pos] << ' ';
			else
				result << "   ";
		}

		result << "   ";

		// make up a ascii-row
		// ascii row failed. (utf8 validate assertion failed)
		/*  for (int i = 0; i < 16; i++)
		    {
		    if (i == 8)
		    result << "  ";
		    else if (i%4 == 0)
		    result << ' ';
		    
		    if ((i+pos < nLen) && 
		        (src[i+pos] >= 32)) // printable character
			result << src[i+pos];
		        else if (i+pos < nLen)
			        result << '.'; // non-printable character
		    }*/

		pos += 16; // next row
		result << '\n';
    }

    return result.str();
}
