/////////////////////////////////////////////////////////////////////////////
// Name:        TitlePropDlg.cpp
// Purpose:     DVD title properties dialog
// Author:      Alex Thuering
// Created:     31.01.2004
// RCS-ID:      $Id: TitlePropDlg.cpp,v 1.42 2010/04/18 15:47:04 ntalex Exp $
// Copyright:   (c) Alex Thuering
// Licence:     GPL
/////////////////////////////////////////////////////////////////////////////

#include "TitlePropDlg.h"
#include "TitlesetManager.h"
#include "AVPropDlg.h"
#include "SubtitlePropDlg.h"
#include "MPEG.h"
#include "Config.h"
#include <wxVillaLib/utils.h>
#include <wx/tokenzr.h>
#include "rc/add.png.h"
#include "rc/remove.png.h"
#include "rc/preferences.png.h"

enum {
	AV_BT_ID = 7850,
	DO_NOT_TRANSCODE_CB_ID,
	VOB_BOX_ID,
	ADD_BT_ID,
	REMOVE_BT_ID,
	PROP_BT_ID
};

BEGIN_EVENT_TABLE(TitlePropDlg, wxPropDlg)
	EVT_LISTBOX(VOB_BOX_ID, TitlePropDlg::OnSelectItem)
	EVT_BUTTON(ADD_BT_ID, TitlePropDlg::OnAddBt)
	EVT_BUTTON(REMOVE_BT_ID, TitlePropDlg::OnRemoveBt)
	EVT_BUTTON(PROP_BT_ID, TitlePropDlg::OnPropBt)
	EVT_BUTTON(AV_BT_ID, TitlePropDlg::OnAV)
	EVT_CHECKBOX(DO_NOT_TRANSCODE_CB_ID, TitlePropDlg::OnDoNotTranscodeCheck)
END_EVENT_TABLE()

TitlePropDlg::TitlePropDlg(wxWindow* parent, DVD* dvd, int tsi, int pgci, int vobi): wxPropDlg(parent) {
	m_dvd = dvd;
	m_tsi = tsi;
	m_pgci = pgci;
	PgcArray& pgcs = m_dvd->GetPgcArray(tsi, false);
	m_audioLangCodes = &pgcs.GetAudioLangCodes();
	m_subtitleLangCodes = &pgcs.GetSubtitleLangCodes();
	m_video = &pgcs.GetVideo();
	m_pgc = pgcs[pgci];
	m_vob = m_pgc->GetVobs()[vobi];
	if (!m_vob->GetSlideshow())
		m_vob = new Vob(*m_vob);
	m_vobi = vobi;
	m_vobListBox = NULL;
	m_doNotTranscodeCheckBox = NULL;
	// set title
	wxString title = _("Properties") + wxString(wxT(" - "));
	if (dvd->GetTitlesets().Count() > 1)
		title += _("Titleset") + wxString::Format(wxT(" %d "), tsi+1);
	title += _("Title") + wxString::Format(wxT(" %d"), pgci+1);
	if (vobi>0)
		title += wxString::Format(wxT("-%d"), vobi+1);
	SetTitle(title);
	// create
	Create();
	SetSize(360,-1);
	// update vobBox
	if (m_vobListBox) {
		m_vobListBox->SetSelection(0);
		wxCommandEvent evt;
		OnSelectItem(evt);
	}
}

void TitlePropDlg::CreatePropPanel(wxSizer* sizer) {
	if (m_vob->GetSlideshow()) {
		Slideshow* slideshow = m_vob->GetSlideshow();
		wxSizer* grpSizer = BeginGroup(sizer, _("Slideshow"), wxT(""), false, false, true, 1);
		wxFlexGridSizer* grid = new wxFlexGridSizer(3, 4, 4);
		grid->AddGrowableCol(1);
		wxArrayString formats = DVD::GetVideoFormatLabels();
		AddChoiceProp(grid, _("Format:"), formats[slideshow->GetVideoFormat()-2], formats);
		formats = DVD::GetAspectRatioLabels();
		int ar = slideshow->GetAspectRatio() >= 1 ? slideshow->GetAspectRatio()-1 : 0;
		AddChoiceProp(grid, wxT(""), formats[ar], formats);
		AddSpinProp(grid, _("Duration:"), slideshow->GetDuration(), 1, 1000, 100, _("sec"));
		grpSizer->Add(grid, 0, wxEXPAND|wxALL, 6);
	} else {
		wxSizer* grpSizer = BeginGroup(sizer, _("Video object"), wxT(""), false, false, true, 1);
		wxBoxSizer* vobPane = new wxBoxSizer(wxHORIZONTAL);
		grpSizer->Add(vobPane, 1, wxEXPAND);
		
		m_vobListBox = new VobListBox(this, VOB_BOX_ID, m_vob, *m_audioLangCodes, *m_subtitleLangCodes, m_dvd);
		vobPane->Add(m_vobListBox, 1, wxEXPAND);
		
		wxBoxSizer* buttonPane = new wxBoxSizer(wxVERTICAL);
		vobPane->Add(buttonPane, 0, wxEXPAND|wxLEFT, 4);
		m_addBt = new wxBitmapButton(this, ADD_BT_ID, wxBITMAP_FROM_MEMORY(add));
		m_addBt->SetHelpText(_("Add file..."));
		buttonPane->Add(m_addBt, 0, wxALIGN_CENTER);
		buttonPane->Add(4, 4);
		m_delBt = new wxBitmapButton(this, REMOVE_BT_ID, wxBITMAP_FROM_MEMORY(remove));
		m_delBt->SetHelpText(_("Remove file"));
		buttonPane->Add(m_delBt, 0, wxALIGN_CENTER);
		buttonPane->Add(4, 4);
		m_propBt = new wxBitmapButton(this, PROP_BT_ID, wxBITMAP_FROM_MEMORY(preferences));
		m_propBt->SetHelpText(_("Properties..."));
		buttonPane->Add(m_propBt, 0, wxALIGN_CENTER);
		buttonPane->Add(10, 10, 1, wxEXPAND);
		
		wxFlexGridSizer* grid = new wxFlexGridSizer(2, 4, 4);
		grpSizer->Add(grid, 0, wxEXPAND|wxALL, 6);
		grid->AddGrowableCol(1);
		AddText(grid, wxT(""));
		AddCheckProp(grid, _("do not remultiplex/transcode"), m_vob->GetDoNotTranscode(), false,
				DO_NOT_TRANSCODE_CB_ID);
		m_doNotTranscodeCheckBox = (wxCheckBox*) GetLastControl();
		UpdateDoNotTranscodeCheck();
		grid->Add(2, 2);
		grid->Add(2, 2);
		AddTextProp(grid, _("Chapters:"), m_vob->GetChapters());
		AddSpinProp(grid, _("Pause:"), m_vob->GetPause(), -1, 254, 100, _("sec"));
	}
	sizer->Add(6, 6);

	wxSizer* grpSizer = BeginGroup(sizer, _("Title"));
	wxFlexGridSizer* grid = new wxFlexGridSizer(3, 2, 4, 4);
	grid->AddGrowableCol(1);
	AddFileProp(grid, _("Palette:"), m_pgc->GetPalette(), wxFD_OPEN, wxT("..."), wxT("*.rgb;*.yuv"));
	
	// Pre- and post commands
	wxArrayString commands = GetPreCommands();
	AddComboProp(grid, _("Pre commands:"), m_pgc->GetPreCommands(), commands);
	commands.Add(wxT("exit;"));
	AddComboProp(grid, _("Post commands:"), m_pgc->GetPostCommands(), commands);
	grpSizer->Add(grid, 0, wxEXPAND|wxALL, 6);
}

/**
 * Returns list of pre commands
 */
wxArrayString TitlePropDlg::GetPreCommands() {
	wxArrayString commands;
	for (unsigned int pgci=0; pgci < m_dvd->GetVmgm().Count(); pgci++)
		commands.Add(wxString::Format(wxT("call vmgm menu %d;"),pgci+1));
	if (m_dvd->GetVmgm().Count() == 0 && m_dvd->IsEmptyMenuEnabled())
		commands.Add(wxT("call vmgm menu 1;"));
	for (int tsi=0; tsi<(int)m_dvd->GetTitlesets().Count(); tsi++) {
		Titleset* ts = m_dvd->GetTitlesets()[tsi];
		if (tsi == m_tsi) { // same titleset
			StringSet entrySet = ts->GetMenus().GetEntries();
			for (StringSet::const_iterator entry = entrySet.begin(); entry != entrySet.end(); entry++)
				if (*entry == wxT("root"))
					commands.Add(wxT("call menu;"));
				else
					commands.Add(wxString::Format(wxT("call menu entry %s;"), entry->c_str()));
		}
		if (m_dvd->IsJumppadsEnabled()) {
			for (int pgci=1; pgci<(int)ts->GetMenus().Count(); pgci++)
				commands.Add(wxString::Format(wxT("call titleset %d menu %d;"), tsi+1, pgci+1));
		}
		if (m_dvd->IsJumppadsEnabled() || tsi == m_tsi) {
			for (int pgci=0; pgci<(int)ts->GetTitles().Count(); pgci++)
				if (tsi == m_tsi) // same titleset
					commands.Add(wxString::Format(wxT("jump title %d;"), pgci+1));
				else
					commands.Add(wxString::Format(wxT("jump titleset %d title %d;"), tsi+1, pgci+1));
		}
	}
	return commands;
}

bool TitlePropDlg::SetValues() {
	// check commands
	DVDAction action(false, BUTTON_ACTION);
	action.SetCustom(GetString(4));
	if (!action.IsValid(m_dvd, m_tsi, m_pgci, false, wxT(""), true, false))
		return false;
	action.SetCustom(GetString(5));
	if (!action.IsValid(m_dvd, m_tsi, m_pgci, false, wxT(""), true, false))
		return false;
	
	int n = 0;
	if (m_vob->GetSlideshow()) {
		Slideshow* slideshow = m_vob->GetSlideshow();
		slideshow->SetVideoFormat((VideoFormat) (GetInt(n++)+2));
		slideshow->SetAspectRatio((AspectRatio) (GetInt(n++)+1));
		slideshow->SetDuration(GetInt(n++));
	} else {
		// update vob
		m_vobListBox->UpdateVob();
		m_vob->SetDoNotTranscode(GetBool(n++) && m_vob->GetAudioFilenames().GetCount() == 0);
		m_vob->SetChapters(GetString(n++));
		m_vob->SetPause(GetInt(n++));
		// set new vob
		m_pgc->GetVobs()[m_vobi] = m_vob;
		// update audio language list
		wxArrayString audioLangCodes = m_vobListBox->GetAudioLangCodes();
		m_audioLangCodes->Clear();
		for (wxArrayString::iterator it = audioLangCodes.begin(); it != audioLangCodes.end(); it++)
			m_audioLangCodes->Add(*it);
		// update subtitle language list
		wxArrayString subtitleLangCodes = m_vobListBox->GetSubtitleLangCodes();
		m_subtitleLangCodes->Clear();
		for (wxArrayString::iterator it = subtitleLangCodes.begin(); it != subtitleLangCodes.end(); it++)
			m_subtitleLangCodes->Add(*it);
	}
	m_pgc->SetPalette(GetString(n++));
	m_pgc->SetPreCommands(GetString(n++));
	m_pgc->SetPostCommands(GetString(n++));
	return true;
}

void TitlePropDlg::CreateButtonPane(wxSizer* sizer, bool resetButton, bool dontShowCheckbox) {
	wxBoxSizer* buttonPane = new wxBoxSizer(wxHORIZONTAL);
	wxButton* avBt = new wxButton(this, AV_BT_ID, _("Video..."));
	buttonPane->Add(avBt, 0, wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL);
	buttonPane->Add(10, 10, 1, wxEXPAND);
	wxButton* okBt = new wxButton(this, wxID_OK, _("OK"));
	okBt->SetDefault();
	buttonPane->Add(okBt, 0, wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL);
	buttonPane->Add(8, 0);
	wxButton* cancelBt = new wxButton(this, wxID_CANCEL, _("Cancel"));
	buttonPane->Add(cancelBt, 0, wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL);
	sizer->Add(buttonPane, 0, wxEXPAND|wxLEFT|wxRIGHT|wxBOTTOM, 10);
}

void TitlePropDlg::OnSelectItem(wxCommandEvent& event) {
	m_delBt->Enable(m_vobListBox->GetSelection() > 0);
	m_propBt->Enable(m_vobListBox->GetSelection() >= 1 + (int) m_vob->GetAudioFilenames().GetCount());
}

void TitlePropDlg::OnAddBt(wxCommandEvent& event) {
	wxString audio = wxThumbnails::GetAudioExtWildcard();
	wxString subtitle = wxThumbnails::GetSubtitleExtWildcard();
	wxFileDialog dialog(this, _("Choose a file"), wxT(""), wxT(""),
			_("Audio & Subtitle Files") + wxString::Format(wxT("|%s%s|"), audio.c_str(), subtitle.c_str())
			+ _("Audio Files") + wxString::Format(wxT(" (%s)|%s|"), audio.c_str(), audio.c_str())
			+ _("Subtitle Files") + wxString::Format(wxT(" (%s)|%s|"), subtitle.c_str(), subtitle.c_str()),
			wxFD_OPEN);
	// set file browser dir
	dialog.SetDirectory(s_config.GetLastAddDir() + wxFILE_SEP_PATH);
	if (dialog.ShowModal() == wxID_OK) {
		if (wxThumbnails::IsAudio(dialog.GetPath()))
			m_vobListBox->AddAudio(dialog.GetPath());
		else
			m_vobListBox->AddSubtitle(dialog.GetPath());
		s_config.SetLastAddDir(dialog.GetDirectory());
		UpdateDoNotTranscodeCheck();
	}
}

void TitlePropDlg::OnRemoveBt(wxCommandEvent& event) {
	m_vobListBox->RemoveItem(m_vobListBox->GetSelection());
	wxCommandEvent evt;
	OnSelectItem(evt);
	UpdateDoNotTranscodeCheck();
}

void TitlePropDlg::OnPropBt(wxCommandEvent& event) {
	m_vobListBox->Update();
	int idx = m_vobListBox->GetSelection() - 1 - m_vob->GetAudioFilenames().GetCount();
	wxString subtitleLanguage = m_vobListBox->GetSubtitleLangCodes()[idx];
	SubtitlePropDlg dialog(this, m_vob->GetSubtitles()[idx], &subtitleLanguage);
	if (dialog.ShowModal() == wxID_OK) {
		m_vobListBox->GetSubtitleLangCodes()[idx] = subtitleLanguage;
	}
}

void TitlePropDlg::OnAV(wxCommandEvent& event) {
	AVPropDlg propDlg(this, m_video, false);
	if (propDlg.ShowModal() == wxID_OK) {
		wxCommandEvent evt(EVT_COMMAND_DVD_CHANGED, this->GetId());
		GetEventHandler()->ProcessEvent(evt);
	}
}

void TitlePropDlg::OnDoNotTranscodeCheck(wxCommandEvent& event) {
	m_vobListBox->SetDoNotTranscode(event.IsChecked());
}

void TitlePropDlg::UpdateDoNotTranscodeCheck() {
	if (m_doNotTranscodeCheckBox == NULL)
		return;
	if (m_vobListBox->HasAudioFiles())
		m_doNotTranscodeCheckBox->SetValue(false);
	m_doNotTranscodeCheckBox->Enable(!m_vobListBox->HasAudioFiles() && MPEG::HasNavPacks(m_vob->GetFilename()));
}
