/******************************************************************************
 * Name:        common.cpp
 * Purpose:     common utils such as handling sound, i18n, string conversion
 * Author:      Xie, Chun-Da (jakky1)
 * E-mail:      jakky1@gmail.com
 * Created:     2004.7
 * Copyright:   (C) 2004 Xie, Chun-Da
 * Licence:     GPL : http://www.gnu.org/licenses/gpl.html
 * Modified by:
 ******************************************************************************/


#ifndef COMMON_CPP
#define COMMON_CPP
#include "common.h"

#include "login.h"

#include <wx/config.h>
#include <wx/fontdlg.h>

wxConfig cfg( _T("BBMan") );
int global_max_lines = 500;
// ============================================================================

#include <wx/thread.h>
class SCD_Thread : public wxThread
{
private:
	SCD_ThreadFunc m_thread_func;
	void *m_clientdata;

public:

	SCD_Thread() : wxThread()
	{
	}
	~SCD_Thread()
	{
	}

	static SCD_Thread* ExecFuncUsingThread(SCD_ThreadFunc func, void *clientdata)
	{
		SCD_Thread *t = new SCD_Thread();
		t->m_thread_func = func;
		t->m_clientdata = clientdata;
		t->Create();
		t->Run();
		return t;
	}

	ExitCode Entry()
	{
		m_thread_func(m_clientdata);
		return 0;
	}
};

void ExecFuncUsingThread(SCD_ThreadFunc func, void *clientdata)
{
	SCD_Thread::ExecFuncUsingThread(func, clientdata);
}

// ============================================================================

wxConfigBase* GetConfig()
{	return &cfg;	}
// ----------------------------------------------------------------------------
wxString CharPtrTowxString(const char *str)
{
	static wxMBConvUTF8 mb;
	return wxString( mb.cMB2WC(str) );
}
// ----------------------------------------------------------------------------
char* wxStringToCharPtr(const wxString &str)
{
	static wxMBConvUTF8 mb;
	return (char*) mb.cWX2MB( str.c_str() );
}
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
#include <wx/imaglist.h>
wxBitmap icon_list[30];
// ----------------------------------------------------------------------------
void MakeBitmapMask(wxBitmap& bmp)
{	bmp.SetMask( new wxMask(bmp, *wxWHITE) );	}
// ----------------------------------------------------------------------------
#include <wx/file.h>
void init_Icons()
{
	static bool isInit =false;
	if ( !isInit ) {

		#include "icon/shutdown.xpm"
		#include "icon/terminal.xpm"
		int i=0;
		
		wxIcon term_connect(terminal_xpm);
		wxIcon term_disconnect(Shutdown_xpm);
	
		icon_list[i]=term_disconnect;
		MakeBitmapMask(icon_list[i++]);
		icon_list[i]=term_connect;
		MakeBitmapMask(icon_list[i++]);
		icon_list[i]=term_connect;
		MakeBitmapMask(icon_list[i++]);
		isInit =true;
	}
}

/*
void init_Icons()
{
	int i=0, k;
	int height;
	wxString theme_path = GetThemePath();

	//讀取連線標籤圖示
	if( wxFile::Exists( theme_path + _T("leds.bmp") ) )
	{
		wxBitmap tbimg( theme_path + _T("leds.bmp") , wxBITMAP_TYPE_BMP );
		height = tbimg.GetHeight();
		for(k=0;k<4;k++)
			MakeBitmapMask( icon_list[i++] = tbimg.GetSubBitmap( wxRect( k*height, 0, height, height ) ) );
	}


	//讀取一般圖示
	if( wxFile::Exists( theme_path + _T("icons.bmp") ) )
	{
		wxBitmap icon_img( theme_path + _T("icons.bmp") , wxBITMAP_TYPE_BMP );
		height = icon_img.GetHeight();
		for(k=0;k<16;k++)
			MakeBitmapMask( icon_list[i++] = icon_img.GetSubBitmap( wxRect( k*height, 0, height, height ) ) );
	}

	#include "icon/bbman_16.xpm"
	wxIcon bbman_icon( bbman_16_xpm );
	icon_list[i++] = bbman_icon;
}
*/
// ----------------------------------------------------------------------------
wxBitmap& GetProgramIcon(int icon_id)
{
	if(icon_id >= BBMAN_ICON_END)	return wxNullBitmap;
	return icon_list[icon_id];
}
// ----------------------------------------------------------------------------
void AppendMenuItemWithBitmap(wxMenu *parent, int id, const wxString& item, wxBitmap& bmp)
{
	wxMenuItem *mi;
	mi = new wxMenuItem(parent, id, item);
	mi->SetBitmap(bmp);
	parent->Append(mi);
}
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
wxString GetThemePath()
{
	wxString path;
	GetConfig()->Read( GetUserConfigPath(_T("/setting/theme")) , & path , _T("default") );
	path = _T("theme/") + path + _T("/");
	return path;
}
// ----------------------------------------------------------------------------
#include <wx/dir.h>
#include <wx/choicdlg.h>
void ShowThemeSelector(wxWindow *parent)
{
	wxDir dir( wxGetCwd() + _T("/theme") );
	wxString dirname;
	wxArrayString theme_list;
	int now_theme_id = -1;
	int c;

	wxString orig_theme;
	GetConfig()->Read( GetUserConfigPath(_T("/setting/theme")) , & orig_theme , _T("default") );

	//find all the sub dirs under "theme" directory
	bool b;
	b = dir.GetFirst( &dirname, wxEmptyString, wxDIR_DIRS );
	c = 0;
	while(b)
	{
		theme_list.Add( dirname );
		if(dirname == orig_theme)	now_theme_id = c;
		c++;
		b = dir.GetNext( &dirname );
	}

	int id = wxGetSingleChoiceIndex( wxString(gettext("Current theme : ")) + orig_theme ,
				wxString(gettext("Select a theme")), theme_list, parent );
	if(id==-1)	return;	//user cancel select a theme

	if( orig_theme == theme_list[id] )	return;	//user choose the original theme

	GetConfig()->Write( GetUserConfigPath(_T("/setting/theme")) , theme_list[id] );
	wxMessageBox( gettext("This setting will enabled at the next startup.") );
}
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
#include <wx/clipbrd.h>
//#include "scd_gtk_textctrl.h"	//ShowCopyDialog()
void CopyToClipboard(wxString text , bool comm_with_other)
{
	if (wxTheClipboard->Open())
    {
        wxTheClipboard->SetData( new wxTextDataObject(text) );
        wxTheClipboard->Close();
    }

/*
    if (wxTheClipboard->Open())
    {
//      wxTheClipboard->SetData( new wxTextDataObject( CharPtrTowxString(Big5ToUnicode(wxStringToCharPtr(text))) ) );
//      wxTheClipboard->SetData( new wxTextDataObject( text ) );
        wxTheClipboard->SetData( new wxTextDataObject(text) );
        wxTheClipboard->Close();
    }
    wxTheClipboard->Clear();
    static wxTextCtrl textctrl;
    wxString txt = GetSelectionContent(withANSI);
wxMessageBox(txt);
    textctrl.SetValue( txt );
    textctrl.SetSelection( 0, -1 );
    textctrl.Copy();
    textctrl.SetValue( wxEmptyString );
*/

#ifdef __WXGTK__
//	/*if(comm_with_other)*/	ShowCopyDialog( text );
#endif

}
// ----------------------------------------------------------------------------
wxString GetTextFromClipboard(bool comm_with_other)
{
	wxString text;

    if (wxTheClipboard->Open())
    {
		if( wxTheClipboard->IsSupported( wxDF_TEXT ) )
        {
            wxTextDataObject data;
            wxTheClipboard->GetData( data );
            text = data.GetText();
        }
        wxTheClipboard->Close();
    }


//	text = UTF8_To_Big5( wxStringToCharPtr(text) );

#ifdef __WXGTK__
	/*if(comm_with_other && text.IsEmpty() )*/	//text = ShowPasteDialog();
#endif

//	text = UTF8_To_Big5( wxStringToCharPtr(text) );

	return text;
}
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------

void OnLinkClicked( char *link, enum LINK_TYPE _t);

#include <wx/strconv.h>

// ----------------------------------------------------------------------------
// resources
// ----------------------------------------------------------------------------

// the application icon (under Windows and OS/2 it is in resources)
/*
#if defined(__WXGTK__) || defined(__WXMOTIF__) || defined(__WXMAC__) || defined(__WXMGL__) || defined(__WXX11__)
	#include "mondrian.xpm"
#endif
*/
bool blAA = true;
wxFont global_default_fnt;
bool isFullScreen = false;
//wxFontEncoding global_default_enc = wxFONTENCODING_DEFAULT;
//wxFontEncoding global_default_big5 = wxFONTENCODING_DEFAULT;
//wxFontEncoding global_default_gb = wxFONTENCODING_DEFAULT;

encodingList global_encoding;

void ShowAbout()
{
	wxMessageBox( wxString( gettext("Welcome to BBMan")) + BBMAN_VERSION
		+ wxString( gettext(".\n\nBBMan is designed by Xie, Chun-Da, Dept. of Computer Science, National Chengchi University, Taiwan.\n\nBBMan web page: http://bbman.sf.net/\nMy email box: jakky1@pchome.com.tw\n\nThanks to :\nhttp://www.foood.net/ --- default toolbar Icon set designer\nchivalry@nccu.edu.tw --- BBMan Program Icon.") )
		, wxEmptyString, wxOK | wxICON_INFORMATION );

//	blAA = ! blAA;
//	global_default_fnt.SetNoAntiAliasing( !blAA );
}

wxString GetStatusBarText()
{
	return wxString(_T("BBMan ")) + BBMAN_VERSION
		+ wxString(gettext(". Designer : Xie, Chun-Da, Dept. of Computer Science, NCCU, Taiwan"));
}


#ifndef __WXGTK__
#include <wx/sound.h>	//wxWave 播放音樂
#define wxWave wxSound
wxWave wav;
#endif
bool use_bell;
void SCD_PlaySound()
{
	if( use_bell )	wxBell();
	else
	{
#ifndef __WXGTK__
		wav.Play();
#else
		wxString player, file;
		if( GetConfig()->Read( GetUserConfigPath(_T("/setting/sound_file")) , & file ) && GetConfig()->Read( GetUserConfigPath(_T("/setting/sound_player")) , & player ) )
			wxExecute( player + _T(" ") + file );
#endif
	}
}

void init_sound()
{
	wxString sound_file;
	use_bell = false;
	GetConfig()->Read( GetUserConfigPath(_T("/setting/sound_file")) , & sound_file , wxEmptyString );
	if( sound_file.IsEmpty() )	use_bell = true;
#ifndef __WXGTK__
	else
	{
		if( wav.Create( sound_file ) )	use_bell = false;
		else
		{
			use_bell = true;
			wxMessageBox( gettext("Can't load sound file") );
		}
	}
#endif
}





//******************** 把目前正在開啟的視窗都記錄下來 ******************//
static bool blEnableNaws = false;
void init_Naws()
{
	blEnableNaws = GetConfig()->Exists( GetUserConfigPath(_T("/setting/enable_naws")) );
}
void EnableNaws(bool b)
{
	if( b == blEnableNaws )	return;
	blEnableNaws = b;
	if( b )	GetConfig()->Write( GetUserConfigPath(_T("/setting/enable_naws")) , true );
	else	GetConfig()->DeleteEntry( GetUserConfigPath(_T("/setting/enable_naws")) );
}
bool isEnableNaws()	{	return blEnableNaws;	}


//#include "frm_telnet.h"
//#include "frm_editterm.h"

//BBS_Frame *telnet_frame;
//wxPointerArray aa;
wxPointerArray edit_win_list;
/*
void ShowTelnet()
{
	telnet_frame = new BBS_Frame(_T("BBMan"),
	                             wxPoint(50, 50), wxSize(750, 550));

	//還原成上次的視窗大小
	int w = 0;
	int h = 0;
	if( GetConfig()->Read( GetUserConfigPath(_T("/setting/win_geo/width")), & w ) && GetConfig()->Read( GetUserConfigPath(_T("/setting/win_geo/height")), & h ) )
		telnet_frame->SetSize( w, h );
	if( GetConfig()->Read( GetUserConfigPath(_T("/setting/win_geo/left")), & w ) && GetConfig()->Read( GetUserConfigPath(_T("/setting/win_geo/top")), & h ) )
	{
//		wxSize ds = wxGetDisplaySize();
		if(w < 0)	w = 0;
//		else if(w + 300 > ds.GetWidth() )		w = ds.GetWidth() - 300;
		if(h < 0)	h = 0;
//		else if(h + 300 > ds.GetHeight() )	h = ds.GetHeight() - 300;
		telnet_frame->Move( w, h );
	}

	//開啟有設定自動開啟的 BBS
	SiteInfo si;
 	GetConfig()->SetPath( GetUserConfigPath(_T("/bookmark/")) );
	wxString name, str;
	long id;
	bool ret;
	ret = GetConfig()->GetFirstEntry( name , id );
	while( ret )
	{
		if( GetConfig()->Read( name , &str ) )
		{
			si.Set(str);
			if( si.autoopen )	telnet_frame->connect(si);
		}
		ret = GetConfig()->GetNextEntry( name , id );
	}
	telnet_frame->ShowSpecifiedTerminal(0);
	//

	telnet_frame->Show(TRUE);

	GetConfig()->Read( GetUserConfigPath(_T("/setting/win_geo/fullscreen")) , & w , 0 );
	if(w==1)	telnet_frame->FullScreen();
	//
}
*/

/*
void ShowAnsiEditor()
{
	frame_EditTerm *editframe = new frame_EditTerm( gettext("BBMan - ANSI Editor"),
			wxPoint(50, 50), wxSize(750, 550) );
	editframe->Show(TRUE);

	edit_win_list.Add( editframe );
}

void CloseAnsiEditor(wxFrame *win)
{
	edit_win_list.Remove(win);
}
//**********************************************************************

void LockScreen()
{
	wxString pass, line;
	if( isAnonymousLogin() )
	{
		while(true)
		{
			pass = wxGetPasswordFromUser( gettext("Please input a password. Later you will need this password to restore BBMan window.\n(Password need to be at least 3 letters)"), gettext("Hide BBMan") );
			if( pass.IsEmpty() )	{	wxMessageBox( gettext("Cancel Hiding BBMan") );	return;	}
			if( pass.Length() < 3 ) {	wxMessageBox( gettext("Password needs to be at last 3 letters please.") );	continue;	}
			line = wxGetPasswordFromUser( gettext("Please enter password again to make sure you remember what password you just typed."), gettext("Hide BBMan") );
			if( pass != line ) wxMessageBox( gettext("Password confirming failed, please input again.") );
			else	break;
		}
	}
	else pass = GetLoginPassword();

	int c = edit_win_list.GetCount();
	telnet_frame->Show(false);
	for(int i=0;i<c;i++)	((wxFrame*)(edit_win_list.Item(i)))->Show(false);

	while(true)
	{
		line = wxGetPasswordFromUser( gettext("Please enter password to restore BBMan window."), _T("Restore BBMan window") );
		if( pass == line ) 	break;
	}

	telnet_frame->Show(true);
	for(int j=0;j<c;j++)	((wxFrame*)(edit_win_list.Item(j)))->Show(true);
}
*/
#include "scd_terminal.h"
#include <wx/settings.h>
#include <wx/fontutil.h>

int var_fnt_size;

void GlobalDefaultFont()
{
#ifdef __WXGTK__
	wxString fnt_name ="Fixed 8";
#else
	wxString fnt_name ="0;-13;0;0;0;400;0;0;0;0;3;2;1;49;Courier New";
#endif
	wxNativeFontInfo fi;
	if( fi.FromString( fnt_name ) )	global_default_fnt.SetNativeFontInfo(fi);
	global_default_fnt.SetNoAntiAliasing( !blAA );
}


void init_font()
{
	global_default_fnt = GetCurrentFont();
	var_fnt_size = global_default_fnt.GetPointSize();
}

static bool isInited = false;

void SetGlobalDefaultFont(wxString fnt_name)
{
	wxNativeFontInfo fi;
	if( fi.FromString( fnt_name ) )	global_default_fnt.SetNativeFontInfo(fi);
	global_default_fnt.SetNoAntiAliasing( !blAA );
	isInited = true;
}

wxFont GetCurrentFont()
{
	if( ! isInited )
	{
		isInited = true;
		GlobalDefaultFont();
/*
		global_default_fnt = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);

		wxString fnt_name;

		if( GetConfig()->Read( GetUserConfigPath(_T("/setting/font")), & fnt_name ) )
		{
			wxNativeFontInfo fi;
			if( fi.FromString( fnt_name ) )	global_default_fnt.SetNativeFontInfo(fi);
		}
		global_default_fnt.SetNoAntiAliasing( !blAA );
		*/
//		global_default_fnt.SetDefaultEncoding(wxFONTENCODING_CP950);
	}
	return global_default_fnt;
}

int GetVarFontSize()
{	return var_fnt_size;	}
void SetVarFontSize(int s)
{	var_fnt_size = s;	}

void UserSetFont(wxWindow *frm)
{
	
	wxFont fnt = wxGetFontFromUser( frm , global_default_fnt );
	if ( fnt == wxNullFont ) return;
    wxFont myFont(fnt.GetPointSize(), //pointsize
				 fnt.GetFamily(), //family
				 fnt.GetStyle(),//style
				 fnt.GetWeight(),//weight
				 fnt.GetUnderlined(),//underline
				 fnt.GetFaceName(),//facename
			     global_encoding.current);
	
	global_default_fnt = myFont;
	global_default_fnt.SetNoAntiAliasing( !blAA );
	isInited=true;
	/*
	wxLogMessage("", 
	fnt.GetDefaultEncoding()
	wxFont::GetFaceName
	wxFont::GetFamily
	wxFont::GetNativeFontInfoDesc
	wxFont::GetPointSize
	wxFont::GetStyle
	wxFont::GetUnderlined
	wxFont::GetWeight
*/

	wxLogMessage("Set font %s",	fnt.GetNativeFontInfoDesc().c_str());

}

void UserChangeEncoding(wxFontEncoding enc)
{
	
	wxFont fnt = global_default_fnt;
	wxString facename;
    wxFont myFont(fnt.GetPointSize(), //pointsize
				 wxFONTFAMILY_MODERN , //family
				 wxNORMAL,//style
				 wxNORMAL,//weight
				 false,//underline
				 wxEmptyString,//facename
			     enc);
	global_default_fnt = myFont;
	/*
fnt.GetDefaultEncoding()
fnt.GetFaceName
fnt.GetFamily
fnt.GetNativeFontInfoDesc
fnt.GetPointSize
fnt.GetStyle
fnt.GetUnderlined
fnt.GetWeight
*/
	
	//global_default_fnt.SetDefaultEncoding(enc);
}



/*
void UserSetFont(wxFrame *frm)
{
	wxFont fnt = wxGetFontFromUser( frm , global_default_fnt );
	if( fnt.Ok() )
	{
		global_default_fnt = fnt;
		global_default_fnt.SetNoAntiAliasing( !blAA );

		telnet_frame->SetTerminalFont(fnt);
		int c = edit_win_list.GetCount();
		for(int i=0;i<c;i++)
			((frame_EditTerm*)(edit_win_list.Item(i)))->SetTerminalFont(fnt);

		GetConfig()->Write( GetUserConfigPath(_T("/setting/font")), fnt.GetNativeFontInfoDesc() );
	}
	else
		wxMessageBox( gettext("The font you choosed is not correct, cancel change of font option.") );
}
*/





void setLinkProgram(enum LINK_TYPE _t , wxString program_path)
{
	switch(_t)
	{
		case LINK_HTTP:
		case LINK_HTTPS:
			GetConfig()->Write( GetUserConfigPath(_T("/setting/link_program/http")), program_path );	break;
		case LINK_FTP:
		case LINK_SFTP:
			GetConfig()->Write( GetUserConfigPath(_T("/setting/link_program/ftp")), program_path );	break;
		case LINK_EMAIL:
			GetConfig()->Write( GetUserConfigPath(_T("/setting/link_program/email")), program_path );	break;
		default : break;
	}
}

wxString getLinkProgram(enum LINK_TYPE _t)
{
	wxString program_path = wxEmptyString;

	switch(_t)
	{
		case LINK_HTTP:
		case LINK_HTTPS:
			if( GetConfig()->Read( GetUserConfigPath(_T("/setting/link_program/http")), & program_path ) );
			else
			{
#if defined(__WXGTK__)
				program_path = _T("mozilla");
#else
				program_path = _T("C:\\Program Files\\Internet Explorer\\IEXPLORE.EXE");
#endif
			}
			break;
		case LINK_FTP:
		case LINK_SFTP:
			if( GetConfig()->Read( GetUserConfigPath(_T("/setting/link_program/ftp")), & program_path ) );
			else
			{
#if defined(__WXGTK__)
				program_path = _T("mozilla");
#else
				program_path = _T("C:\\Program Files\\Internet Explorer\\IEXPLORE.EXE");
#endif
			}
			break;
		case LINK_EMAIL:
			if( GetConfig()->Read( GetUserConfigPath(_T("/setting/link_program/email")), & program_path ) );
			else
			{
#if defined(__WXGTK__)
				program_path = _T("mozilla");
#else
				program_path = _T("C:\\Program Files\\Internet Explorer\\IEXPLORE.EXE");
#endif
			}
			break;
		default : break;
	}

	return program_path;
}
/*
void OnLinkClicked( char *link, enum LINK_TYPE _t)
{
	switch(_t)
	{
		case LINK_TELNET:
			telnet_frame->connect( CharPtrTowxString(link) );
			break;
		case LINK_HTTP:
		case LINK_HTTPS:
		case LINK_FTP:
		case LINK_SFTP:
		case LINK_EMAIL:
			wxExecute( wxString::Format( getLinkProgram(_t) + _T(" %s"), link) );
			break;
		default : break;
	}
}

void OpenHyperlink(char *link)
{
	enum LINK_TYPE _t;
	if( strstr(link, "http:/") == link )	
		_t = LINK_HTTP;
	else if( strstr(link, "https:/") == link )	_t = LINK_HTTPS;
	else if( strstr(link, "telnet:/") == link )	_t = LINK_TELNET;
	else if( strstr(link, "bbs:/") == link )	_t = LINK_TELNET;
	else if( strstr(link, "ftp:/") == link )	_t = LINK_FTP;
	else if( strstr(link, "sftp:/") == link )	_t = LINK_SFTP;
	else if( strstr(link, "@") != NULL )	_t = LINK_EMAIL;
	else _t = LINK_HTTP;
	OnLinkClicked(link, _t);
}
*/
// ----------------------------------------------------------------------------
wxApp *app = NULL;
void SetApp(wxApp *_app)
{	app = _app;	}
// ----------------------------------------------------------------------------
wxApp* GetApp()
{	return app;	}
// ----------------------------------------------------------------------------
void AppProcessOtherEvents()
{
	if( !app )	return;
	if( app->Pending() )	app->Dispatch();
	app->Yield();
}
// ----------------------------------------------------------------------------
void Init_LineWrapedLength()
{
	long len;
	if( GetConfig()->Read( GetUserConfigPath(_T("/setting/line_wraped_length")) , & len ) )
		SCD_Terminal::SetLineWrapedLength(len);
}
// ----------------------------------------------------------------------------
void SetLineWrapedLength(int len)
{
	SCD_Terminal::SetLineWrapedLength(len);
	GetConfig()->Write( GetUserConfigPath(_T("/setting/line_wraped_length")), SCD_Terminal::GetLineWrapedLength() );
}
// ============================================================================

#endif
