/////////////////////////////////////////////////////////////////////////////
// Name:        SubtitlePropDlg.h
// Purpose:     The subtitle properties dialog
// Author:      Alex Thuering
// Created:     24.02.2010
// RCS-ID:      $Id: SubtitlePropDlg.cpp,v 1.3 2010/05/13 09:58:10 ntalex Exp $
// Copyright:   (c) Alex Thuering
// Licence:     GPL
/////////////////////////////////////////////////////////////////////////////

#include "SubtitlePropDlg.h"
#include "Utils.h"
#include <wx/filename.h>
#include <wxVillaLib/utils.h>

#include <fontconfig/fontconfig.h>
#define FONTS_CONF wxFindDataFile(wxT("fonts.conf"))

FontMap SubtitlePropDlg::s_fonts;

// begin wxGlade: ::extracode

// end wxGlade

BEGIN_EVENT_TABLE(SubtitlePropDlg, wxDialog)
    // begin wxGlade: SubtitlePropDlg::event_table
    EVT_LISTBOX(FONT_FAMILY_BOX_ID , SubtitlePropDlg::OnFontFamilySelected)
    EVT_LISTBOX(FONT_STYLE_BOX_ID , SubtitlePropDlg::OnFontStyleSelected)
    EVT_SPINCTRL(FONT_SIZE_SPIN_ID , SubtitlePropDlg::OnFontSizeChanged)
    EVT_LISTBOX(FONT_SIZE_BOX_ID , SubtitlePropDlg::OnFontSizeSelected)
    // end wxGlade
END_EVENT_TABLE()

SubtitlePropDlg::SubtitlePropDlg(wxWindow* parent, TextSub* textsub, wxString* language):
		wxDialog(parent, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER) {
	m_textsub = textsub;
	m_language = language;
	
    // begin wxGlade: SubtitlePropDlg::SubtitlePropDlg
    boxSizer2_staticbox = new wxStaticBox(this, -1, _("Margin"));
    boxSizer1_staticbox = new wxStaticBox(this, -1, _("Alignment"));
    m_langLabel = new wxStaticText(this, wxID_ANY, _("Language:"));
    const wxString *m_langChoice_choices = NULL;
    m_langChoice = new wxChoice(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0, m_langChoice_choices, 0);
    m_charsetLabel = new wxStaticText(this, wxID_ANY, _("Charset:"));
    const wxString *m_charsetChoice_choices = NULL;
    m_charsetChoice = new wxChoice(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0, m_charsetChoice_choices, 0);
    m_fontLabel = new wxStaticText(this, wxID_ANY, _("Font:"));
    const wxString *m_fontFamilyBox_choices = NULL;
    m_fontFamilyBox = new wxListBox(this, FONT_FAMILY_BOX_ID , wxDefaultPosition, wxDefaultSize, 0, m_fontFamilyBox_choices, wxLB_SINGLE|wxLB_SORT);
    const wxString *m_fontStyleBox_choices = NULL;
    m_fontStyleBox = new wxListBox(this, FONT_STYLE_BOX_ID , wxDefaultPosition, wxDefaultSize, 0, m_fontStyleBox_choices, wxLB_SINGLE|wxLB_SORT);
    m_fontSizeSpin = new wxSpinCtrl(this, FONT_SIZE_SPIN_ID , wxT(""), wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 0, 100);
    const wxString *m_fontSizeBox_choices = NULL;
    m_fontSizeBox = new wxListBox(this, FONT_SIZE_BOX_ID , wxDefaultPosition, wxDefaultSize, 0, m_fontSizeBox_choices, wxLB_SINGLE);
    m_previewLabel = new wxStaticText(this, wxID_ANY, _("Preview:"));
    m_previewText = new wxTextCtrl(this, wxID_ANY, _("ABCabcXYZxyz"));
    m_alignRadioTL = new wxRadioButton(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxRB_GROUP);
    m_alignRadioTC = new wxRadioButton(this, wxID_ANY, wxEmptyString);
    m_alignRadioTR = new wxRadioButton(this, wxID_ANY, wxEmptyString);
    m_alignRadioCL = new wxRadioButton(this, wxID_ANY, wxEmptyString);
    m_alignRadioCR = new wxRadioButton(this, wxID_ANY, wxEmptyString);
    m_alignRadioBL = new wxRadioButton(this, wxID_ANY, wxEmptyString);
    m_alignRadioBC = new wxRadioButton(this, wxID_ANY, wxEmptyString);
    m_alignRadioBR = new wxRadioButton(this, wxID_ANY, wxEmptyString);
    m_marginTop = new wxSpinCtrl(this, wxID_ANY, wxT(""), wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 0, 100);
    m_marginLeft = new wxSpinCtrl(this, wxID_ANY, wxT(""), wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 0, 100);
    m_marginRight = new wxSpinCtrl(this, wxID_ANY, wxT(""), wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 0, 100);
    m_marginBottom = new wxSpinCtrl(this, wxID_ANY, wxT(""), wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 0, 100);
    okBt = new wxButton(this, wxID_OK, _("OK"));
    m_cancelBt = new wxButton(this, wxID_CANCEL, _("Cancel"));

    set_properties();
    do_layout();
    // end wxGlade
}


void SubtitlePropDlg::set_properties() {
    // begin wxGlade: SubtitlePropDlg::set_properties
    SetTitle(_("Subtitle Properties"));
    m_fontFamilyBox->SetMinSize(wxSize(-1, 250));
    m_fontStyleBox->SetMinSize(wxSize(140, 40));
    m_fontSizeSpin->SetMinSize(wxSize(48, -1));
    m_fontSizeBox->SetMinSize(wxSize(-1, 40));
    m_alignRadioBC->SetValue(1);
    m_marginTop->SetMinSize(wxSize(48, -1));
    m_marginLeft->SetMinSize(wxSize(48, -1));
    m_marginRight->SetMinSize(wxSize(48, -1));
    m_marginBottom->SetMinSize(wxSize(48, -1));
    // end wxGlade
    
    m_langChoice->Append(DVD::GetLanguageNames());
    map<wxString, wxString>& langMap = DVD::GetLanguageMap();
	for (map<wxString, wxString>::iterator langIt = langMap.begin(); langIt != langMap.end(); langIt++) {
		if (langIt->second == *m_language) {
			m_langChoice->SetStringSelection(langIt->first);
		}
	}

	m_charsetChoice->Append(DVD::GetCharsets());
	m_charsetChoice->SetStringSelection(m_textsub->GetCharacterSet());

    FontMap& fonts = GetFontMap();
    for (FontMap::iterator fontIt = fonts.begin(); fontIt != fonts.end(); fontIt++) {
    	m_fontFamilyBox->Append(fontIt->first);
    }
    m_fontFamilyBox->SetStringSelection(m_textsub->GetFontFamily());
	wxCommandEvent evt;
	OnFontFamilySelected(evt);
	m_fontStyleBox->SetStringSelection(m_textsub->GetFontStyle());
	
	for (int i=6; i<72; i++) {
		if (i>18) {
			i++;
		} else if (i>28) {
			i += 3;
		} else if (i>40) {
			i += 7;
		}
		m_fontSizeBox->Append(wxString::Format(wxT("%d"), i));
	}
	
	m_fontSizeSpin->SetValue((int)m_textsub->GetFontSize());
	wxSpinEvent spnEvt;
	OnFontSizeChanged(spnEvt);
	m_alignRadioTL->SetValue(m_textsub->GetAlignment() == (wxALIGN_TOP | wxALIGN_LEFT));
	m_alignRadioTC->SetValue(m_textsub->GetAlignment() == (wxALIGN_TOP | wxALIGN_CENTER_HORIZONTAL));
	m_alignRadioTR->SetValue(m_textsub->GetAlignment() == (wxALIGN_TOP | wxALIGN_RIGHT));
	m_alignRadioCL->SetValue(m_textsub->GetAlignment() == (wxALIGN_CENTER_VERTICAL | wxALIGN_LEFT));
	m_alignRadioCR->SetValue(m_textsub->GetAlignment() == (wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT));
	m_alignRadioBL->SetValue(m_textsub->GetAlignment() == (wxALIGN_BOTTOM | wxALIGN_LEFT));
	m_alignRadioBC->SetValue(m_textsub->GetAlignment() == (wxALIGN_BOTTOM | wxALIGN_CENTER_HORIZONTAL));
	m_alignRadioBR->SetValue(m_textsub->GetAlignment() == (wxALIGN_BOTTOM | wxALIGN_RIGHT));
	m_marginLeft->SetValue(m_textsub->GetLeftMargin());
	m_marginRight->SetValue(m_textsub->GetRightMargin());
	m_marginTop->SetValue(m_textsub->GetTopMargin());
	m_marginBottom->SetValue(m_textsub->GetBottomMargin());
}


void SubtitlePropDlg::do_layout() {
    // begin wxGlade: SubtitlePropDlg::do_layout
    wxBoxSizer* mainSizer = new wxBoxSizer(wxVERTICAL);
    wxBoxSizer* buttonSizer = new wxBoxSizer(wxHORIZONTAL);
    wxFlexGridSizer* propSizer = new wxFlexGridSizer(4, 2, 4, 2);
    wxBoxSizer* propSizer2 = new wxBoxSizer(wxHORIZONTAL);
    wxStaticBoxSizer* boxSizer2 = new wxStaticBoxSizer(boxSizer2_staticbox, wxHORIZONTAL);
    wxFlexGridSizer* marginSizer = new wxFlexGridSizer(3, 3, 4, 4);
    wxStaticBoxSizer* boxSizer1 = new wxStaticBoxSizer(boxSizer1_staticbox, wxHORIZONTAL);
    wxGridSizer* alignSizer = new wxGridSizer(3, 3, 12, 16);
    wxBoxSizer* fontSizer = new wxBoxSizer(wxHORIZONTAL);
    wxBoxSizer* fSizer1 = new wxBoxSizer(wxVERTICAL);
    wxBoxSizer* fSizer2 = new wxBoxSizer(wxHORIZONTAL);
    wxBoxSizer* fSizer3 = new wxBoxSizer(wxVERTICAL);
    wxBoxSizer* charsetSizer = new wxBoxSizer(wxHORIZONTAL);
    wxBoxSizer* langSizer = new wxBoxSizer(wxHORIZONTAL);
    propSizer->Add(m_langLabel, 0, wxALIGN_CENTER_VERTICAL, 0);
    langSizer->Add(m_langChoice, 0, 0, 0);
    propSizer->Add(langSizer, 1, wxEXPAND, 0);
    propSizer->Add(m_charsetLabel, 0, wxALIGN_CENTER_VERTICAL, 0);
    charsetSizer->Add(m_charsetChoice, 0, 0, 0);
    propSizer->Add(charsetSizer, 1, wxEXPAND, 0);
    propSizer->Add(m_fontLabel, 0, wxTOP, 2);
    fontSizer->Add(m_fontFamilyBox, 0, wxRIGHT|wxEXPAND, 6);
    fSizer2->Add(m_fontStyleBox, 0, wxRIGHT|wxEXPAND, 6);
    fSizer3->Add(m_fontSizeSpin, 0, wxBOTTOM|wxEXPAND, 6);
    fSizer3->Add(m_fontSizeBox, 1, wxEXPAND, 0);
    fSizer2->Add(fSizer3, 0, wxEXPAND, 0);
    fSizer1->Add(fSizer2, 1, wxBOTTOM|wxEXPAND, 6);
    fSizer1->Add(m_previewLabel, 0, wxLEFT|wxRIGHT, 2);
    fSizer1->Add(m_previewText, 0, wxRIGHT|wxTOP|wxEXPAND, 2);
    fontSizer->Add(fSizer1, 1, wxEXPAND, 0);
    propSizer->Add(fontSizer, 0, wxEXPAND, 0);
    propSizer->Add(20, 20, 0, wxEXPAND, 0);
    alignSizer->Add(m_alignRadioTL, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 0);
    alignSizer->Add(m_alignRadioTC, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 0);
    alignSizer->Add(m_alignRadioTR, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 0);
    alignSizer->Add(m_alignRadioCL, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 0);
    alignSizer->Add(0, 0, 0, 0, 0);
    alignSizer->Add(m_alignRadioCR, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 0);
    alignSizer->Add(m_alignRadioBL, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 0);
    alignSizer->Add(m_alignRadioBC, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 0);
    alignSizer->Add(m_alignRadioBR, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 0);
    boxSizer1->Add(alignSizer, 0, wxLEFT|wxTOP, 4);
    propSizer2->Add(boxSizer1, 0, wxRIGHT|wxEXPAND, 8);
    marginSizer->Add(8, 8, 0, 0, 0);
    marginSizer->Add(m_marginTop, 0, 0, 0);
    marginSizer->Add(8, 8, 0, 0, 0);
    marginSizer->Add(m_marginLeft, 0, 0, 0);
    marginSizer->Add(8, 8, 0, 0, 0);
    marginSizer->Add(m_marginRight, 0, 0, 0);
    marginSizer->Add(8, 8, 0, 0, 0);
    marginSizer->Add(m_marginBottom, 0, 0, 0);
    marginSizer->Add(8, 8, 0, 0, 0);
    boxSizer2->Add(marginSizer, 1, wxALL, 4);
    propSizer2->Add(boxSizer2, 0, wxEXPAND, 0);
    propSizer->Add(propSizer2, 1, wxLEFT|wxRIGHT|wxTOP|wxEXPAND, 6);
    propSizer->AddGrowableRow(2);
    propSizer->AddGrowableCol(1);
    mainSizer->Add(propSizer, 1, wxALL|wxEXPAND, 10);
    buttonSizer->Add(10, 10, 1, wxEXPAND, 0);
    buttonSizer->Add(okBt, 0, 0, 0);
    buttonSizer->Add(8, 8, 0, 0, 0);
    buttonSizer->Add(m_cancelBt, 0, 0, 0);
    buttonSizer->Add(10, 10, 1, wxEXPAND, 0);
    mainSizer->Add(buttonSizer, 0, wxLEFT|wxRIGHT|wxBOTTOM|wxEXPAND, 4);
    SetSizer(mainSizer);
    mainSizer->Fit(this);
    Layout();
    Centre();
    // end wxGlade
    m_langChoice->SetMinSize(wxSize(m_fontFamilyBox->GetSize().GetWidth(), -1));
    m_charsetChoice->SetMinSize(wxSize(m_fontFamilyBox->GetSize().GetWidth(), -1));
    OnFontChanged();
    m_langChoice->SetFocus();
    SetMinSize(GetSize());
}

// wxGlade: add SubtitlePropDlg event handlers

void SubtitlePropDlg::OnFontFamilySelected(wxCommandEvent& event) {
	// update font style choice
	m_fontStyleBox->Clear();
	if (m_fontFamilyBox->GetSelection() < 0)
		return;
	map<wxString, wxString>& styles = GetFontMap()[m_fontFamilyBox->GetStringSelection()];
	for (map<wxString, wxString>::iterator styleIt = styles.begin(); styleIt != styles.end(); styleIt++) {
		m_fontStyleBox->Append(styleIt->first);
	}
	m_fontStyleBox->SetStringSelection(wxT("Regular"));
	if (m_fontStyleBox->GetSelection() == -1)
		m_fontStyleBox->SetStringSelection(wxT("Normal"));
	if (m_fontStyleBox->GetSelection() == -1)
		m_fontStyleBox->SetStringSelection(wxT("Standard"));
	if (m_fontStyleBox->GetSelection() == -1)
		m_fontStyleBox->SetSelection(0);
	OnFontChanged();
}


void SubtitlePropDlg::OnFontStyleSelected(wxCommandEvent &event) {
	OnFontChanged();
}

void SubtitlePropDlg::OnFontSizeChanged(wxSpinEvent &event) {
	m_fontSizeBox->SetStringSelection(wxString::Format(wxT("%d"), m_fontSizeSpin->GetValue()));
	OnFontChanged();
}

void SubtitlePropDlg::OnFontSizeSelected(wxCommandEvent &event) {
	long size;
	if (m_fontSizeBox->GetStringSelection().ToLong(&size))
		m_fontSizeSpin->SetValue(size);
	OnFontChanged();
}

void SubtitlePropDlg::OnFontChanged() {
	m_previewText->SetMinSize(wxSize(-1, -1));
	wxFont font = m_previewText->GetFont();
	font.SetFaceName(m_fontFamilyBox->GetStringSelection());
	wxString style = m_fontStyleBox->GetStringSelection().Lower();
	if (style.Find(wxT("slant")) != wxNOT_FOUND || style.Find(wxString(_("slant")).Lower()) != wxNOT_FOUND) {
		font.SetStyle(wxFONTSTYLE_SLANT);
	} else if (style.Find(wxT("italic")) != wxNOT_FOUND || style.Find(wxString(_("italic")).Lower()) != wxNOT_FOUND
			|| style.Find(wxT("cursiva")) != wxNOT_FOUND) {
		font.SetStyle(wxFONTSTYLE_ITALIC);
	} else
		font.SetStyle(wxFONTSTYLE_NORMAL);
	if (style.Find(wxT("light")) != wxNOT_FOUND || style.Find(wxString(_("light")).Lower()) != wxNOT_FOUND)
		font.SetWeight(wxFONTWEIGHT_LIGHT);
	else if (style.Find(wxT("bold")) != wxNOT_FOUND || style.Find(wxString(_("bold")).Lower()) != wxNOT_FOUND)
		font.SetWeight(wxFONTWEIGHT_BOLD);
	else
		font.SetWeight(wxFONTWEIGHT_NORMAL);
	font.SetPointSize(m_fontSizeSpin->GetValue());
	m_previewText->SetFont(font);
	if (GetSizer()) {
		GetSizer()->Fit(this);
		Layout();
		if (m_previewText->GetSize().GetHeight() < 56)
			m_previewText->SetMinSize(wxSize(-1, 56));
		GetSizer()->Fit(this);
		Layout();
	}
}

FontMap& SubtitlePropDlg::GetFontMap() {
	if (s_fonts.size() > 0)
		return s_fonts;
#ifdef __WXMSW__
	wxString fontConfigFile;
	if (!wxGetEnv(wxT("FONTCONFIG_FILE"), &fontConfigFile)) {
		// load config and fonts
		FcConfig* fc = FcConfigCreate ();
		if (fc == NULL) {
			wxLogError(wxString(wxT("SubtitlePropDlg::UpdateFontList(): ")) + wxString(wxT("FcConfigCreate failed.")));
			return s_fonts;
		}
		FcConfigParseAndLoad(fc, (const FcChar8*) (const char*) FONTS_CONF.ToUTF8(), FcTrue);
		FcConfigBuildFonts(fc);
		FcConfigSetCurrent(fc);
	}
#endif
	FcPattern* pattern = FcPatternBuild(NULL, FC_OUTLINE, FcTypeBool, 1, FC_SCALABLE, FcTypeBool, 1, NULL);
	FcObjectSet* objectSet = FcObjectSetBuild(FC_FAMILY, FC_STYLE, FC_FULLNAME, FC_FILE, FC_INDEX, NULL);
	FcFontSet* fontSet = FcFontList(0, pattern, objectSet);
	FcObjectSetDestroy(objectSet);
	FcPatternDestroy(pattern);
	if (fontSet == NULL)
		return s_fonts;
	for (int fi = 0; fi < fontSet->nfont; fi++) {
		// font file
		FcChar8* str;
		if (FcPatternGetString(fontSet->fonts[fi], FC_FILE, 0, &str) != FcResultMatch)
			continue;
		wxString fontFilename = wxString::FromUTF8((char*) str);
#if 1
		fontFilename = fontFilename.AfterLast(wxT('/'));
#endif
		// font file index
		int fontFileIndex = 0;
		FcPatternGetInteger(fontSet->fonts[fi], FC_INDEX, 0, &fontFileIndex);
		if (fontFileIndex > 0)
			continue;
		// family name
		if (FcPatternGetString(fontSet->fonts[fi], FC_FAMILY, 0, &str) != FcResultMatch)
			continue;
		wxString fontFamily = wxString::FromUTF8((char*) str);
		// style name
		if (FcPatternGetString(fontSet->fonts[fi], FC_STYLE, 0, &str) != FcResultMatch)
			continue;
		wxString fontStyle = wxString::FromUTF8((char*) str);
		s_fonts[fontFamily][fontStyle] = fontFilename;
	}
	FcFontSetDestroy(fontSet);
	return s_fonts;
}

int SubtitlePropDlg::ShowModal() {
	int res = wxDialog::ShowModal();
	if (res == wxID_OK) {
		*m_language = DVD::GetLanguageMap()[m_langChoice->GetStringSelection()];
		m_textsub->SetCharacterSet(m_charsetChoice->GetStringSelection());
		m_textsub->SetFontFamily(m_fontFamilyBox->GetStringSelection());
		m_textsub->SetFontStyle(m_fontStyleBox->GetStringSelection());
		m_textsub->SetFontSize(m_fontSizeSpin->GetValue());
		if (m_alignRadioTL->GetValue())
			m_textsub->SetAlignment((wxAlignment) (wxALIGN_TOP | wxALIGN_LEFT));
		else if (m_alignRadioTC->GetValue())
			m_textsub->SetAlignment((wxAlignment) (wxALIGN_TOP | wxALIGN_CENTER_HORIZONTAL));
		else if (m_alignRadioTR->GetValue())
			m_textsub->SetAlignment((wxAlignment) (wxALIGN_TOP | wxALIGN_RIGHT));
		else if (m_alignRadioCL->GetValue())
			m_textsub->SetAlignment((wxAlignment) (wxALIGN_CENTER_VERTICAL | wxALIGN_LEFT));
		else if (m_alignRadioCR->GetValue())
			m_textsub->SetAlignment((wxAlignment) (wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT));
		else if (m_alignRadioBL->GetValue())
			m_textsub->SetAlignment((wxAlignment) (wxALIGN_BOTTOM | wxALIGN_LEFT));
		else if (m_alignRadioBC->GetValue())
			m_textsub->SetAlignment((wxAlignment) (wxALIGN_BOTTOM | wxALIGN_CENTER_HORIZONTAL));
		else if (m_alignRadioBR->GetValue())
			m_textsub->SetAlignment((wxAlignment) (wxALIGN_BOTTOM | wxALIGN_RIGHT));
		m_textsub->SetLeftMargin(m_marginLeft->GetValue());
		m_textsub->SetRightMargin(m_marginRight->GetValue());
		m_textsub->SetTopMargin(m_marginTop->GetValue());
		m_textsub->SetBottomMargin(m_marginBottom->GetValue());
	}
	return res;
}
