/////////////////////////////////////////////////////////////////////////////
// Name:        CellPropDlg.cpp
// Purpose:     DVD cell properties dialog
// Author:      Alex Thuering
// Created:     23.04.2011
// RCS-ID:      $Id: CellPropDlg.cpp,v 1.5 2013/06/30 13:24:47 ntalex Exp $
// Copyright:   (c) Alex Thuering
// Licence:     GPL
/////////////////////////////////////////////////////////////////////////////

#include "CellPropDlg.h"
#include "TitlePropDlg.h"

//(*InternalHeaders(CellPropDlg)
#include <wx/intl.h>
#include <wx/button.h>
#include <wx/string.h>
//*)

//(*IdInit(CellPropDlg)
const long CellPropDlg::ID_MEDIA_CTRL = wxNewId();
const long CellPropDlg::ID_SLIDER = wxNewId();
const long CellPropDlg::ID_TIME_CTRL = wxNewId();
const long CellPropDlg::ID_TIME_SPINB = wxNewId();
const long CellPropDlg::ID_FRAME_SPINBT = wxNewId();
const long CellPropDlg::ID_DURATION_CTRL = wxNewId();
const long CellPropDlg::ID_STATICTEXT1 = wxNewId();
const long CellPropDlg::ID_CHOICE1 = wxNewId();
const long CellPropDlg::ID_END_CTRL = wxNewId();
const long CellPropDlg::ID_END_SPIN = wxNewId();
const long CellPropDlg::ID_END_FRAME_SPINBT = wxNewId();
const long CellPropDlg::ID_RADIOBUTTON1 = wxNewId();
const long CellPropDlg::ID_RADIOBUTTON2 = wxNewId();
const long CellPropDlg::ID_RADIOBUTTON3 = wxNewId();
const long CellPropDlg::ID_COMMANDS_CTRL = wxNewId();
//*)

BEGIN_EVENT_TABLE(CellPropDlg,wxDialog)
	//(*EventTable(CellPropDlg)
	//*)
	EVT_COMMAND_SCROLL(ID_SLIDER, CellPropDlg::OnSliderScroll)
END_EVENT_TABLE()

CellPropDlg::CellPropDlg(wxWindow* parent, DVD* dvd, int tsi, int pgci, Vob* vob, Cell* cell) {
	m_dvd = dvd;
	m_tsi = tsi;
	m_pgci = pgci;
	m_vob = vob;
	m_cell = cell;

	//(*Initialize(CellPropDlg)
	wxStaticText* staticText2;
	wxBoxSizer* boxSizer1;
	wxStaticText* staticText5;
	wxStaticText* staticText4;
	wxStaticText* staticText3;
	wxStaticText* StaticText1;
	wxFlexGridSizer* flexGridSizer1;
	wxStdDialogButtonSizer* stdDialogButtonSizer;
	wxBoxSizer* BoxSizer1;
	wxBoxSizer* BoxSizer3;
	wxBoxSizer* mainSizer;

	Create(parent, wxID_ANY, _("Cell properties"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER, _T("wxID_ANY"));
	mainSizer = new wxBoxSizer(wxVERTICAL);
	m_mediaCtrl = new MediaCtrlFF(this, ID_MEDIA_CTRL, wxT(""), wxDefaultPosition,wxDefaultSize, 0, wxDefaultValidator, _T("ID_MEDIA_CTRL"));
	m_mediaCtrl->SetMinSize(wxSize(300, 200));
	m_mediaCtrl->SetWindowStyle(wxBORDER_NONE);
	mainSizer->Add(m_mediaCtrl, 1, wxALL|wxEXPAND|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 4);
	m_slider = new wxSlider(this, ID_SLIDER, 0, 0, 100, wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("ID_SLIDER"));
	mainSizer->Add(m_slider, 0, wxEXPAND|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 2);
	flexGridSizer1 = new wxFlexGridSizer(0, 2, 2, 4);
	flexGridSizer1->AddGrowableCol(1);
	StaticText1 = new wxStaticText(this, wxID_ANY, _("Time:"), wxDefaultPosition, wxDefaultSize, 0, _T("wxID_ANY"));
	flexGridSizer1->Add(StaticText1, 0, wxLEFT|wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL, 4);
	BoxSizer3 = new wxBoxSizer(wxHORIZONTAL);
	m_timeCtrl = new wxTextCtrl(this, ID_TIME_CTRL, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("ID_TIME_CTRL"));
	BoxSizer3->Add(m_timeCtrl, 0, wxEXPAND|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
	m_timeSpinBt = new wxSpinButton(this, ID_TIME_SPINB, wxDefaultPosition, wxDefaultSize, wxSP_VERTICAL|wxSP_ARROW_KEYS, _T("ID_TIME_SPINB"));
	m_timeSpinBt->SetRange(0, 100);
	m_timeSpinBt->SetMinSize(wxSize(16,12));
	BoxSizer3->Add(m_timeSpinBt, 0, wxEXPAND|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
	m_frameSpinBt = new wxSpinButton(this, ID_FRAME_SPINBT, wxDefaultPosition, wxDefaultSize, wxSP_VERTICAL|wxSP_ARROW_KEYS, _T("ID_FRAME_SPINBT"));
	m_frameSpinBt->SetRange(-9999, 9999);
	m_frameSpinBt->SetMinSize(wxSize(16,12));
	BoxSizer3->Add(m_frameSpinBt, 0, wxEXPAND|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
	staticText2 = new wxStaticText(this, wxID_ANY, _("Pause:"), wxDefaultPosition, wxDefaultSize, 0, _T("wxID_ANY"));
	BoxSizer3->Add(staticText2, 0, wxLEFT|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 8);
	m_pauseSpin = new wxSpinCtrl(this, ID_DURATION_CTRL, _T("0"), wxDefaultPosition, wxSize(60,-1), 0, 0, 999, 0, _T("ID_DURATION_CTRL"));
	m_pauseSpin->SetValue(_T("0"));
	BoxSizer3->Add(m_pauseSpin, 0, wxLEFT|wxEXPAND|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 4);
	staticText3 = new wxStaticText(this, wxID_ANY, _("sec"), wxDefaultPosition, wxDefaultSize, 0, _T("wxID_ANY"));
	BoxSizer3->Add(staticText3, 0, wxLEFT|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 2);
	BoxSizer3->Add(-1,-1,1, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
	flexGridSizer1->Add(BoxSizer3, 0, wxALL|wxEXPAND|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 0);
	StaticText2 = new wxStaticText(this, ID_STATICTEXT1, _("End:"), wxDefaultPosition, wxDefaultSize, 0, _T("ID_STATICTEXT1"));
	flexGridSizer1->Add(StaticText2, 0, wxLEFT|wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL, 4);
	BoxSizer1 = new wxBoxSizer(wxHORIZONTAL);
	m_endChoice = new wxChoice(this, ID_CHOICE1, wxDefaultPosition, wxDefaultSize, 0, 0, 0, wxDefaultValidator, _T("ID_CHOICE1"));
	m_endChoice->SetSelection( m_endChoice->Append(_("Auto")) );
	m_endChoice->Append(_("Custom"));
	BoxSizer1->Add(m_endChoice, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 0);
	m_endCtrl = new wxTextCtrl(this, ID_END_CTRL, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("ID_END_CTRL"));
	BoxSizer1->Add(m_endCtrl, 0, wxLEFT|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 2);
	m_endSpinBt = new wxSpinButton(this, ID_END_SPIN, wxDefaultPosition, wxDefaultSize, wxSP_VERTICAL|wxSP_ARROW_KEYS, _T("ID_END_SPIN"));
	m_endSpinBt->SetRange(0, 100);
	m_endSpinBt->SetMinSize(wxSize(16,12));
	BoxSizer1->Add(m_endSpinBt, 0, wxEXPAND|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 0);
	m_endFrameSpinBt = new wxSpinButton(this, ID_END_FRAME_SPINBT, wxDefaultPosition, wxDefaultSize, wxSP_VERTICAL|wxSP_ARROW_KEYS, _T("ID_END_FRAME_SPINBT"));
	m_endFrameSpinBt->SetRange(-9999, 9999);
	m_endFrameSpinBt->SetMinSize(wxSize(16,12));
	BoxSizer1->Add(m_endFrameSpinBt, 0, wxEXPAND|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
	flexGridSizer1->Add(BoxSizer1, 1, wxALL|wxEXPAND|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 0);
	staticText5 = new wxStaticText(this, wxID_ANY, _("Type:"), wxDefaultPosition, wxDefaultSize, 0, _T("wxID_ANY"));
	flexGridSizer1->Add(staticText5, 0, wxLEFT|wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL, 4);
	boxSizer1 = new wxBoxSizer(wxHORIZONTAL);
	m_chapterBt = new wxRadioButton(this, ID_RADIOBUTTON1, _("Chapter"), wxDefaultPosition, wxDefaultSize, wxRB_GROUP, wxDefaultValidator, _T("ID_RADIOBUTTON1"));
	boxSizer1->Add(m_chapterBt, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 4);
	m_programBt = new wxRadioButton(this, ID_RADIOBUTTON2, _("Program"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("ID_RADIOBUTTON2"));
	boxSizer1->Add(m_programBt, 0, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 0);
	m_regularBt = new wxRadioButton(this, ID_RADIOBUTTON3, _("Regular cell"), wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator, _T("ID_RADIOBUTTON3"));
	boxSizer1->Add(m_regularBt, 0, wxALL|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 0);
	flexGridSizer1->Add(boxSizer1, 1, wxALL|wxEXPAND|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
	staticText4 = new wxStaticText(this, wxID_ANY, _("Commands:"), wxDefaultPosition, wxDefaultSize, 0, _T("wxID_ANY"));
	flexGridSizer1->Add(staticText4, 0, wxLEFT|wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL, 4);
	m_commandsCtrl = new wxComboBox(this, ID_COMMANDS_CTRL, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0, 0, 0, wxDefaultValidator, _T("ID_COMMANDS_CTRL"));
	flexGridSizer1->Add(m_commandsCtrl, 1, wxEXPAND|wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL, 4);
	mainSizer->Add(flexGridSizer1, 0, wxLEFT|wxRIGHT|wxEXPAND|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
	stdDialogButtonSizer = new wxStdDialogButtonSizer();
	stdDialogButtonSizer->AddButton(new wxButton(this, wxID_OK, wxEmptyString));
	stdDialogButtonSizer->AddButton(new wxButton(this, wxID_CANCEL, wxEmptyString));
	stdDialogButtonSizer->Realize();
	mainSizer->Add(stdDialogButtonSizer, 0, wxALL|wxEXPAND|wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL, 5);
	SetSizer(mainSizer);
	mainSizer->Fit(this);
	mainSizer->SetSizeHints(this);

	Connect(ID_TIME_CTRL,wxEVT_COMMAND_TEXT_UPDATED,(wxObjectEventFunction)&CellPropDlg::OnChangeTime);
	Connect(ID_TIME_SPINB,wxEVT_SCROLL_THUMBTRACK,(wxObjectEventFunction)&CellPropDlg::OnTimeSpin);
	Connect(ID_FRAME_SPINBT,wxEVT_SCROLL_LINEUP,(wxObjectEventFunction)&CellPropDlg::OnFrameSpin);
	Connect(ID_CHOICE1,wxEVT_COMMAND_CHOICE_SELECTED,(wxObjectEventFunction)&CellPropDlg::OnEndChoice);
	Connect(ID_END_CTRL,wxEVT_COMMAND_TEXT_UPDATED,(wxObjectEventFunction)&CellPropDlg::OnChangeEnd);
	Connect(ID_END_SPIN,wxEVT_SCROLL_THUMBTRACK,(wxObjectEventFunction)&CellPropDlg::OnEndSpin);
	Connect(ID_END_FRAME_SPINBT,wxEVT_SCROLL_LINEUP,(wxObjectEventFunction)&CellPropDlg::OnEndFrameSpin);
	//*)
	Connect(wxID_OK, wxEVT_COMMAND_BUTTON_CLICKED, (wxObjectEventFunction)&CellPropDlg::OnOkBt);
	stdDialogButtonSizer->GetAffirmativeButton()->SetDefault();

	int x = 0;
	m_timeCtrl->GetTextExtent(wxT("00:00:00.000"), &x, NULL);
	m_timeCtrl->SetMinSize(wxSize(x + 10, -1));
	m_endCtrl->SetMinSize(wxSize(x + 10, -1));
	m_pauseSpin->GetTextExtent(wxT("999"), &x, NULL);
	m_pauseSpin->SetMinSize(wxSize(x + 32, -1));

	m_mediaCtrl->Load(vob->GetFilename());
	m_slider->SetMax(m_mediaCtrl->Length()/1000);
	m_timeSpinBt->SetMax(m_mediaCtrl->Length()/1000);
	m_endSpinBt->SetMax(m_mediaCtrl->Length()/1000);

	SeekVideo(m_cell->GetStart());
	m_endChoice->SetSelection(m_cell->GetEnd() == -1 ? 0 : 1);
	m_endSpinBt->SetValue(m_cell->GetEnd() >= 0 ? m_cell->GetEnd() / 1000 : 0);
	m_endCtrl->ChangeValue(wxString(m_cell->GetEnd() >= 0 ? Time2String(m_cell->GetEnd(), true) : wxT("")));
	m_pauseSpin->SetValue(m_cell->GetPause());
	m_regularBt->SetValue(true);
	m_chapterBt->SetValue(m_cell->IsChapter());
	m_programBt->SetValue(m_cell->IsProgram());
	m_commandsCtrl->Append(TitlePropDlg::GetCommandList(m_dvd, m_tsi));
	m_commandsCtrl->SetValue(m_cell->GetCommands());

	wxCommandEvent evt;
	OnEndChoice(evt);
	m_timeCtrl->SetFocus();
}

CellPropDlg::~CellPropDlg() {
	//(*Destroy(CellPropDlg)
	//*)
}

void CellPropDlg::SeekVideo(long pos, bool updateTimeCtrl) {
	m_slider->SetValue(lround(pos / 1000));
	m_timeSpinBt->SetValue(lround(pos / 1000));
	m_mediaCtrl->Seek((wxFileOffset) pos);
	if (updateTimeCtrl)
		m_timeCtrl->ChangeValue(Time2String(pos, true));
}

void CellPropDlg::OnChangeTime(wxCommandEvent& event) {
	if (s_timeRE.Matches(m_timeCtrl->GetValue()))
		SeekVideo(String2Time(m_timeCtrl->GetValue()), false);
}

void CellPropDlg::OnTimeSpin(wxSpinEvent& event) {
	SeekVideo(((long)m_timeSpinBt->GetValue())*1000);
}

void CellPropDlg::OnSliderScroll(wxScrollEvent& event) {
	SeekVideo(((long)m_slider->GetValue())*1000);
}

void CellPropDlg::OnEndChoice(wxCommandEvent& event) {
	m_endCtrl->Enable(m_endChoice->GetSelection() > 0);
	m_endSpinBt->Enable(m_endChoice->GetSelection() > 0);
	m_endFrameSpinBt->Enable(m_endChoice->GetSelection() > 0);
}

void CellPropDlg::OnChangeEnd(wxCommandEvent& event) {
	if (s_timeRE.Matches(m_endCtrl->GetValue()))
		m_endSpinBt->SetValue(String2Time(m_endCtrl->GetValue()) / 1000);
}

void CellPropDlg::OnEndSpin(wxSpinEvent& event) {
	m_endCtrl->ChangeValue(Time2String(m_endSpinBt->GetValue() * 1000, true));
}

void CellPropDlg::OnFrameSpin(wxSpinEvent& event) {
	SeekVideo(String2Time(m_timeCtrl->GetValue()) + 1000 / m_mediaCtrl->GetFps());
}

void CellPropDlg::OnFrameSpinDown(wxSpinEvent& event) {
	long pos = String2Time(m_timeCtrl->GetValue()) - 1000 / m_mediaCtrl->GetFps();
	SeekVideo(pos >= 0 ? pos : 0);
}

void CellPropDlg::OnEndFrameSpin(wxSpinEvent& event) {
	m_endCtrl->ChangeValue(Time2String(String2Time(m_endCtrl->GetValue()) + 1000 / m_mediaCtrl->GetFps(), true));
}

void CellPropDlg::OnEndFrameSpinDown(wxSpinEvent& event) {
	long pos = String2Time(m_endCtrl->GetValue()) - 1000 / m_mediaCtrl->GetFps();
	m_endCtrl->ChangeValue(Time2String(pos >= 0 ? pos : 0, true));
}

void CellPropDlg::OnOkBt(wxCommandEvent& event) {
	if (!s_timeRE.Matches(m_timeCtrl->GetValue())) {
		wxLogError(_("'%s' is not valid time"), m_timeCtrl->GetValue().c_str());
		return;
	}
	if (m_endCtrl->GetValue().length() > 0 && !s_timeRE.Matches(m_endCtrl->GetValue())) {
		wxLogError(_("'%s' is not valid time"), m_endCtrl->GetValue().c_str());
		return;
	}
	if (m_endCtrl->GetValue().length() > 0
			&& String2Time(m_timeCtrl->GetValue()) > String2Time(m_endCtrl->GetValue())) {
		wxLogError(_("Start time cannot be after end time"));
		return;
	}
	DVDAction action;
	action.SetCustom(m_commandsCtrl->GetValue());
	if (m_commandsCtrl->GetValue().length() && !action.IsValid(m_dvd, m_tsi, m_pgci, false, wxT(""), true, false)) {
		return;
	}
	m_cell->SetStart(String2Time(m_timeCtrl->GetValue()));
	m_cell->SetEnd(m_endChoice->GetSelection() > 0 && m_endCtrl->GetValue().length()
			? String2Time(m_endCtrl->GetValue()) : -1);
	m_cell->SetPause(m_pauseSpin->GetValue());
	m_cell->SetCommands(m_commandsCtrl->GetValue());
	m_cell->SetChapter(m_chapterBt->GetValue());
	m_cell->SetProgram(m_programBt->GetValue());
	EndModal(wxID_OK);
}
