/////////////////////////////////////////////////////////////////////////////
// Name:        BurnDlg.h
// Purpose:     Burn dialog
// Author:      Alex Thuering
// Created:	23.03.2003
// RCS-ID:      $Id: BurnDlg.cpp,v 1.16 2007/12/28 08:50:25 ntalex Exp $
// Copyright:   (c) Alex Thuering
// Licence:     GPL
/////////////////////////////////////////////////////////////////////////////

#include "BurnDlg.h"
#include "Config.h"
#include <wx/utils.h>
#include <wx/dir.h>
#include <wx/filename.h>
#include <wx/progdlg.h>
#include <wxVillaLib/utils.h>

BEGIN_EVENT_TABLE(BurnDlg, wxDialog)
  EVT_BUTTON(TEMP_DIR_BT_ID, BurnDlg::OnChooseTempDir)
  EVT_RADIOBUTTON(GENERATE_RADIO_BT_ID, BurnDlg::OnRadioBt)
  EVT_RADIOBUTTON(ISO_RADIO_BT_ID, BurnDlg::OnRadioBt)
  EVT_BUTTON(ISO_BT_ID, BurnDlg::OnChooseIsoFile)
  EVT_RADIOBUTTON(BURN_RADIO_BT_ID, BurnDlg::OnRadioBt)
  EVT_BUTTON(RESET_BT_ID, BurnDlg::OnReset)
  EVT_BUTTON(wxID_OK, BurnDlg::OnOk)
END_EVENT_TABLE()

BurnDlg::BurnDlg(wxWindow* parent):
 wxDialog(parent, -1, wxEmptyString, wxDefaultPosition, wxDefaultSize,
 wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER)
{
    // begin wxGlade: BurnDlg::BurnDlg
    m_tempDirLabel = new wxStaticText(this, -1, _("Temp directory:"));
    m_tempDirText = new wxTextCtrl(this, -1, wxT(""));
    m_tempDirBt = new wxButton(this, TEMP_DIR_BT_ID, _("..."));
    m_previewCheck = new wxCheckBox(this, PREVIEW_CHECK_ID, _("preview"));
    m_generateRadioBt = new wxRadioButton(this, GENERATE_RADIO_BT_ID, _("just generate"), wxDefaultPosition, wxDefaultSize, wxRB_GROUP);
    m_isoRadioBt = new wxRadioButton(this, ISO_RADIO_BT_ID, _("create iso image"));
    m_isoLabel = new wxStaticText(this, -1, _("Save to:"));
    m_isoText = new wxTextCtrl(this, -1, wxT(""));
    m_isoBt = new wxButton(this, ISO_BT_ID, _("..."));
    m_burnRadioBt = new wxRadioButton(this, BURN_RADIO_BT_ID, _("burn"));
    m_formatCheck = new wxCheckBox(this, -1, _("format DVD-RW"));
    m_deviceLabel = new wxStaticText(this, -1, _("Device:"));
    const wxString m_deviceChoice_choices[] = {
        
    };
    m_deviceChoice = new wxComboBox(this, -1, wxT(""), wxDefaultPosition, wxDefaultSize, 0, m_deviceChoice_choices, wxCB_DROPDOWN);
    m_speedLabel = new wxStaticText(this, -1, _("Speed:"));
    const wxString m_speedChoice_choices[] = {
        
    };
    m_speedChoice = new wxComboBox(this, -1, wxT(""), wxDefaultPosition, wxDefaultSize, 0, m_speedChoice_choices, wxCB_DROPDOWN);
    m_devPanel = new wxPanel(this, -1);
    m_addECCCheck = new wxCheckBox(this, -1, _("add error correction data"));
    m_spacer = new wxPanel(this, -1);
    m_startBt = new wxButton(this, wxID_OK, _("Start"));
    m_cancelBt = new wxButton(this, wxID_CANCEL, _("Cancel"));
    m_resetBt = new wxButton(this, RESET_BT_ID, _("Reset"));

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

void BurnDlg::set_properties()
{
    // begin wxGlade: BurnDlg::set_properties
    SetTitle(_("Burn"));
    m_tempDirBt->SetSize(wxSize(21, 21));
    m_isoBt->SetSize(wxSize(21, 21));
    m_deviceChoice->SetSelection(-1);
    m_speedChoice->SetSelection(-1);
    m_startBt->SetDefault();
    // end wxGlade
	
	int h = m_tempDirText->GetSize().GetHeight() > 21 ?
	  m_tempDirText->GetSize().GetHeight() : 21;
	m_tempDirBt->SetSizeHints(h, h, h, h);
	m_isoBt->SetSizeHints(h, h, h, h);
	
	// set devices
	wxArrayString devices;
#ifdef __WXMSW__
	for (int i=0; i<26; i++) {
        char buf[] = { i+64, 0 };
        wxString drive = wxString(buf, wxConvISO8859_1) + wxT(":");
        if (GetDriveType(drive) == DRIVE_CDROM)
            devices.Add(drive);
	}
#else
    wxDir d(wxT("/dev"));
    wxString fname;
    if (d.GetFirst(&fname, wxT("dvd*"), wxDIR_FILES))
    	do { devices.Add(wxT("/dev/") + fname); } while (d.GetNext(&fname));
    if (d.GetFirst(&fname, wxT("cdrom*"), wxDIR_FILES))
    	do { devices.Add(wxT("/dev/") + fname); } while (d.GetNext(&fname));
    if (d.GetFirst(&fname, wxT("sg*"), wxDIR_FILES))
    	do { devices.Add(wxT("/dev/") + fname); } while (d.GetNext(&fname));
    devices.Sort();
#endif
    wxString scanCmd = s_config.GetBurnScanCmd();
    if (scanCmd.length())
    {
      wxProgressDialog* pdlg = new wxProgressDialog(_("Scan devices"),
        _("Please wait..."), devices.GetCount()-1, GetParent(),
        wxPD_AUTO_HIDE | wxPD_APP_MODAL | wxPD_CAN_ABORT);
      pdlg->Show();
      pdlg->SetFocus();
      for (unsigned int i=0; i<devices.GetCount(); i++)
      {
        wxString cmd = scanCmd;
        cmd.Replace(wxT("$DEVICE"), devices[i]);
#ifdef __WXMSW__
        cmd = wxGetAppPath() + wxString(wxFILE_SEP_PATH) + _T("..") +
            wxString(wxFILE_SEP_PATH) + _T("dvdauthor") +
            wxString(wxFILE_SEP_PATH) + cmd;
#endif
        wxArrayString output;
        wxExecute(cmd, output, wxEXEC_SYNC | wxEXEC_NODISABLE);
        if (output.Count() > 0 && output[0].length() > 7
              && output[0].SubString(0,7) == wxT("INQUIRY:"))
        {
            wxString dev = output[0].AfterFirst(wxT('[')).BeforeLast(wxT(']'));
            dev = devices[i] + wxT(" ") + dev.BeforeFirst(wxT(']')).Trim() + wxT(" ")
                + dev.AfterFirst(wxT('[')).BeforeFirst(wxT(']')).Trim();
            m_devices.Add(devices[i]);
            m_deviceChoice->Append(dev);
        }
        if (!pdlg->Update(i))
          break;
      }
      pdlg->Hide();
    }
    if (m_devices.Count() == 0)
        for (unsigned int i=0; i<devices.GetCount(); i++)
            m_deviceChoice->Append(devices[i]);

	m_speedChoice->Append(_T("auto"));
	for (int speed = 1; speed <= 8; speed = speed*2)
	  m_speedChoice->Append(wxString::Format(_T("%dx"), speed));
  
	UpdateCtrls();
    if (!s_config.GetPreviewCmd().length())
	  m_previewCheck->Enable(false);
	// check if dvdisaster is installed
	wxString cmd = s_config.GetAddECCCmd();
    if (cmd.length() > 0)
      cmd = cmd[0] == wxT('"') ? cmd.Mid(0, cmd.Mid(1).Find(wxT('"'))+2) : cmd.BeforeFirst(wxT(' '));
	bool eccCheckEnable = false;
	if (cmd.length() > 0) {
      wxLogNull log;
      wxArrayString output;
	  if (wxExecute(cmd + wxT(" --version"), output, wxEXEC_SYNC | wxEXEC_NODISABLE) == 0)
        eccCheckEnable = true;
    }
    m_addECCCheck->Enable(eccCheckEnable);
}

void BurnDlg::do_layout()
{
    // begin wxGlade: BurnDlg::do_layout
    wxBoxSizer* mainSizer = new wxBoxSizer(wxVERTICAL);
    wxBoxSizer* btSizer = new wxBoxSizer(wxHORIZONTAL);
    wxBoxSizer* panelSizer = new wxBoxSizer(wxVERTICAL);
    wxBoxSizer* deviceSizer = new wxBoxSizer(wxHORIZONTAL);
    wxBoxSizer* formatSizer = new wxBoxSizer(wxHORIZONTAL);
    wxBoxSizer* isoSizer = new wxBoxSizer(wxHORIZONTAL);
    wxBoxSizer* tempDirSizer = new wxBoxSizer(wxHORIZONTAL);
    tempDirSizer->Add(m_tempDirLabel, 0, wxRIGHT|wxALIGN_CENTER_VERTICAL, 4);
    tempDirSizer->Add(m_tempDirText, 1, 0, 0);
    tempDirSizer->Add(4, 16, 0, 0, 0);
    tempDirSizer->Add(m_tempDirBt, 0, 0, 0);
    panelSizer->Add(tempDirSizer, 1, wxTOP|wxBOTTOM|wxEXPAND, 4);
    panelSizer->Add(m_previewCheck, 0, wxBOTTOM, 6);
    panelSizer->Add(m_generateRadioBt, 0, 0, 0);
    panelSizer->Add(m_isoRadioBt, 0, 0, 0);
    isoSizer->Add(16, 8, 0, 0, 0);
    isoSizer->Add(m_isoLabel, 0, wxRIGHT|wxALIGN_CENTER_VERTICAL, 4);
    isoSizer->Add(m_isoText, 1, 0, 0);
    isoSizer->Add(4, 16, 0, 0, 0);
    isoSizer->Add(m_isoBt, 0, 0, 0);
    panelSizer->Add(isoSizer, 1, wxTOP|wxBOTTOM|wxEXPAND, 4);
    panelSizer->Add(m_burnRadioBt, 0, 0, 0);
    formatSizer->Add(16, 8, 0, 0, 0);
    formatSizer->Add(m_formatCheck, 0, wxEXPAND, 0);
    panelSizer->Add(formatSizer, 1, wxEXPAND, 0);
    deviceSizer->Add(16, 8, 0, 0, 0);
    deviceSizer->Add(m_deviceLabel, 0, wxRIGHT|wxALIGN_CENTER_VERTICAL, 4);
    deviceSizer->Add(m_deviceChoice, 0, 0, 0);
    deviceSizer->Add(12, 20, 0, 0, 0);
    deviceSizer->Add(m_speedLabel, 0, wxRIGHT|wxALIGN_CENTER_VERTICAL, 12);
    deviceSizer->Add(m_speedChoice, 0, 0, 0);
    deviceSizer->Add(m_devPanel, 1, wxEXPAND, 0);
    panelSizer->Add(deviceSizer, 1, wxTOP|wxBOTTOM|wxEXPAND, 4);
    panelSizer->Add(m_addECCCheck, 0, wxBOTTOM, 6);
    mainSizer->Add(panelSizer, 0, wxALL|wxEXPAND, 6);
    mainSizer->Add(m_spacer, 1, wxEXPAND, 0);
    btSizer->Add(50, 20, 1, wxEXPAND, 0);
    btSizer->Add(m_startBt, 0, wxALIGN_CENTER_VERTICAL, 0);
    btSizer->Add(10, 20, 0, 0, 0);
    btSizer->Add(m_cancelBt, 0, wxALIGN_CENTER_VERTICAL, 0);
    btSizer->Add(10, 20, 0, 0, 0);
    btSizer->Add(m_resetBt, 0, wxALIGN_CENTER_VERTICAL, 0);
    btSizer->Add(50, 20, 1, wxEXPAND, 0);
    mainSizer->Add(btSizer, 0, wxLEFT|wxRIGHT|wxBOTTOM|wxEXPAND|wxALIGN_BOTTOM, 10);
    SetAutoLayout(true);
    SetSizer(mainSizer);
    mainSizer->Fit(this);
    mainSizer->SetSizeHints(this);
    Layout();
    Centre();
    // end wxGlade
}

wxString BurnDlg::GetDevice()
{
  if (m_devices.Count() && m_deviceChoice->GetSelection() >= 0)
    return m_devices[m_deviceChoice->GetSelection()];
  else
    return m_deviceChoice->GetValue();
}

void BurnDlg::SetDevice(wxString device)
{
  if (m_devices.Count())
  {
    int n = device.length() > 0 ? m_devices.Index(device) : 0;
    if (n >= 0)
      m_deviceChoice->SetSelection(n);
    else
      m_deviceChoice->SetValue(device);
  }
  else
    m_deviceChoice->SetValue(device);
}

int BurnDlg::GetSpeed()
{
  long speed = 0;
  if (m_speedChoice->GetSelection() > 0)
	m_speedChoice->GetStringSelection().BeforeFirst(wxT('x')).ToLong(&speed);
  return speed;
}

void BurnDlg::SetSpeed(int speed)
{
  if (speed == 0)
	m_speedChoice->SetSelection(0);
  else
	m_speedChoice->SetStringSelection(wxString::Format(_T("%dx"), speed));
}

void BurnDlg::UpdateCtrls(bool def)
{
  m_tempDirText->SetValue(s_config.GetTempDir(def));
  m_previewCheck->SetValue(s_config.GetPreviewDo(def));
  m_generateRadioBt->SetValue(s_config.GetGenerateDo(def));
  m_isoRadioBt->SetValue(s_config.GetIsoDo(def));
  m_isoText->SetValue(s_config.GetIsoSaveTo(def));
  m_addECCCheck->SetValue(s_config.GetAddECCDo(def));
  m_burnRadioBt->SetValue(s_config.GetBurnDo(def));
  m_formatCheck->SetValue(s_config.GetFormatDo(def));
  SetDevice(s_config.GetBurnDevice(def));
  SetSpeed(s_config.GetBurnSpeed(def));
  wxCommandEvent evt;
  OnRadioBt(evt);
}

void BurnDlg::OnChooseTempDir(wxCommandEvent& event)
{
  wxDirDialog dlg(this, _("Choose a directory"), GetTempDir(),
    wxDD_NEW_DIR_BUTTON);
  if (dlg.ShowModal() != wxID_OK)
    return;
  wxString dir = dlg.GetPath();
  dir += wxFILE_SEP_PATH + wxString(_T("dvd")) + wxFILE_SEP_PATH;
  m_tempDirText->SetValue(dir);  
}

void BurnDlg::OnRadioBt(wxCommandEvent& event)
{
  m_isoLabel->Enable(DoCreateIso());
  m_isoText->Enable(DoCreateIso());
  m_isoBt->Enable(DoCreateIso());
  m_formatCheck->Enable(DoBurn());
  m_deviceLabel->Enable(DoBurn());
  m_deviceChoice->Enable(DoBurn());
  m_speedLabel->Enable(DoBurn());
  m_speedChoice->Enable(DoBurn());
}

void BurnDlg::OnChooseIsoFile(wxCommandEvent& event)
{
  wxFileDialog dlg(this, _("Choose a file to save iso image"),
   wxPathOnly(GetIsoFile()), _T("dvd.iso"), _T("*.iso"), wxSAVE);
  if (dlg.ShowModal() != wxID_OK)
     return;
  m_isoText->SetValue(dlg.GetPath());
}

void BurnDlg::OnReset(wxCommandEvent& event)
{
  UpdateCtrls(true);
}

void BurnDlg::OnOk(wxCommandEvent& event)
{
  wxString device = GetDevice().Trim().Trim(false);
  if (m_burnRadioBt->GetValue()) {
    if (device.length() == 0) {
      wxMessageBox(_("Please enter device name"),
	      _("Burn"), wxOK|wxICON_ERROR, this);
      return;
    }
#ifdef __WXMSW__
    if (device.Find(wxT(':')) != 1 || device.length() > 3
         || device.length() == 3 && device.GetChar(2) != wxT('\\')) {
      wxMessageBox(_("Invalid device name"),
	      _("Burn"), wxOK|wxICON_ERROR, this);
      return;
    }
    SetDevice(device.SubString(0,1).MakeUpper());
#endif 
  }
  s_config.SetTempDir(m_tempDirText->GetValue());
  s_config.SetPreviewDo(m_previewCheck->GetValue());
  s_config.SetGenerateDo(m_generateRadioBt->GetValue());
  s_config.SetIsoDo(m_isoRadioBt->GetValue());
  s_config.SetIsoSaveTo(m_isoText->GetValue());
  s_config.SetAddECCDo(m_addECCCheck->GetValue());
  s_config.SetBurnDo(m_burnRadioBt->GetValue());
  s_config.SetFormatDo(m_formatCheck->GetValue());
  s_config.SetBurnDevice(GetDevice());
  s_config.SetBurnSpeed(GetSpeed());
  s_config.Flush();
  EndModal(wxID_OK);
}
