// KreateCD - CD recording software for the K desktop environment
//
// 1999 by Alexander Feigl <Alexander.Feigl@gmx.de>
//
// This file is subject to the terms and conditions of the GNU General      
// Public License.  See the file COPYING in the main directory of the       
// KreateCD distribution for more details.                                     

#include "TrackWindow.h"
#include "CDTrack.h"
#include "AudioFile.h"
#include "DriveAccess.h"
#include "TrackDialog.h"
#include "AudioOptions.h"
#include "IsoOptions.h"
#include "IsoWindow.h"
#include "IsoImage.h"

#include <qlabel.h>
#include <qcheckbox.h>
#include <qsize.h>
#include <qpushbutton.h>
#include <qgroupbox.h>
#include <qwindowdefs.h>
#include <qstring.h>
#include <qlayout.h>


#include <kcombo.h>
#include <kconfig.h>
#include <kapp.h>
#include <klocale.h>
#include <klined.h>
#include <kfiledialog.h>
#include <kmsgbox.h>
#include <kurl.h>


extern KLocale *locale;


TrackWindow::TrackWindow( QWidget *parent, const char *name,CDTrack *track):QWidget(parent,name)
 {
  char buffer[32];
  KConfig *config;
  QRect DefaultRect(100,50,500,300);
  class QVBoxLayout *winlayout;
  class QHBoxLayout *mainlayout;
  class QVBoxLayout *leftlayout; 
  class QVBoxLayout *rightlayout;
  class QGridLayout *leftgridlayout;

 
  ignsigs=0;
  ThisTrack=track;
  config=kapp->getConfig();
  AudioOptWindow=0;
  ISOTreeWindow=0;
  ISOOptWindow=0;

  setCaption(locale->translate("KreateCD - track window"));

  winlayout=new QVBoxLayout(this,10); 
  mainlayout=new QHBoxLayout();
  winlayout->addLayout(mainlayout,1);
  leftlayout=new QVBoxLayout();
  mainlayout->addLayout(leftlayout,1);

  leftgridlayout=new QGridLayout(7,2);
  leftlayout->addLayout(leftgridlayout);

  // Build track description widget & label

  DescriptionLabel=new QLabel(locale->translate("Description"),this,"description label");
  DescriptionLabel->setMinimumSize(DescriptionLabel->sizeHint());
  DescriptionEdit=new KLined(this,"description edit");
  DescriptionEdit->setMaxLength(39);
  DescriptionEdit->setMinimumSize(DescriptionEdit->sizeHint());
  leftgridlayout->addWidget(DescriptionLabel,1,0,1);
  leftgridlayout->addWidget(DescriptionEdit,1,1,1);

  // Build track type widget & label
  LabTrackType=new QLabel(locale->translate("Track type"),this,"track type label");
  LabTrackType->setMinimumSize(LabTrackType->sizeHint());
  CombTrackType=new KCombo(this,"track type");
  CDTrack::getTypeString(CDTrack::Track_Audio,buffer);
  CombTrackType->insertItem(buffer,-1);
  CDTrack::getTypeString(CDTrack::Track_AudioPreEmph,buffer);
  CombTrackType->insertItem(buffer,-1);
  CDTrack::getTypeString(CDTrack::Track_DataMode1,buffer);
  CombTrackType->insertItem(buffer,-1);
  CDTrack::getTypeString(CDTrack::Track_DataMode2,buffer);
  CombTrackType->insertItem(buffer,-1);
  CDTrack::getTypeString(CDTrack::Track_XA1,buffer);
  CombTrackType->insertItem(buffer,-1);
  CDTrack::getTypeString(CDTrack::Track_XA2,buffer);
  CombTrackType->insertItem(buffer,-1);
  CDTrack::getTypeString(CDTrack::Track_CDI,buffer);
  CombTrackType->insertItem(buffer,-1);
  CombTrackType->setMinimumSize(CombTrackType->sizeHint());
  leftgridlayout->addWidget(LabTrackType,3,0,1);
  leftgridlayout->addWidget(CombTrackType,3,1,1);

  // Build source type widget & label
  LabSourceType=new QLabel(locale->translate("Track source"),this,"track source label");
  LabSourceType->setMinimumSize(LabSourceType->sizeHint());
  CombSourceType=new KCombo(this,"track type");
  CombSourceType->insertItem(locale->translate("None"),-1);
  CombSourceType->insertItem(locale->translate("CD track"),-1);
  CombSourceType->insertItem(locale->translate("File"),-1);
  CombSourceType->insertItem(locale->translate("Filesystem"),-1);
  CombSourceType->setMinimumSize(CombSourceType->sizeHint());
  leftgridlayout->addWidget(LabSourceType,5,0,1);
  leftgridlayout->addWidget(CombSourceType,5,1,1);

  // Build checkbox wheather to use image file 
  CheckUseImage=new QCheckBox(locale->translate("Use image file"),this,"use file image");
  CheckUseImage->setFixedSize(CheckUseImage->sizeHint());
  leftlayout->addWidget(CheckUseImage);
  
  // Build button for reselection of source
  ButtonSelectSource=new QPushButton(locale->translate("Select source"),this,"source select");
  ButtonSelectSource->setMinimumSize(ButtonSelectSource->sizeHint());
  leftlayout->addWidget(ButtonSelectSource);

  // Build options button
  ButtonOptions=new QPushButton(locale->translate("Options ..."),this,"track options");
  ButtonOptions->setMinimumSize(ButtonOptions->sizeHint());
  leftlayout->addWidget(ButtonOptions);

  PropertyFrame=new QGroupBox(locale->translate("Properties"),this,"props frame");
  PropertyFrame->setAlignment(AlignHCenter);
  rightlayout=new QVBoxLayout(PropertyFrame,30);  

  mainlayout->addWidget(PropertyFrame,2);
  PropertyLabel=new QLabel(PropertyFrame,"props label");
  PropertyFrame->setMinimumSize(80,80);


  rightlayout->addWidget(PropertyLabel);


  connect(CombTrackType,SIGNAL(activated(int)),this,SLOT(changeTrackMode(int)));
  connect(CombSourceType,SIGNAL(activated(int)),this,SLOT(changeSourceType(int)));
#if QT_VERSION >= 200
  connect(DescriptionEdit,SIGNAL(textChanged(const QString &)),
          this,SLOT(changeDescription(const QString &)));
#else
  connect(DescriptionEdit,SIGNAL(textChanged(const char *)),
          this,SLOT(changeDescription(const char*)));
#endif
  connect(CheckUseImage,SIGNAL(toggled(bool)),this,SLOT(changeUseImage(bool)));
  connect(ButtonSelectSource,SIGNAL(clicked()),this,SLOT(changeSource()));
  connect(ButtonOptions,SIGNAL(clicked()),this,SLOT(openOptions()));

  OkButton=new QPushButton(locale->translate("OK"),this);
  OkButton->setMinimumSize(OkButton->sizeHint());

  winlayout->addWidget(OkButton);

  connect(OkButton,SIGNAL(clicked()),this,SLOT(hide()));


  config->setGroup("Geometry");
  this->setGeometry(config->readRectEntry("TrackWindowGeo",&DefaultRect));
  winlayout->activate();

  updateWindow();
  
 }


void TrackWindow::hide()
 {
  emit closed();
 }

TrackWindow::~TrackWindow(void)
 {
  KConfig *config;
  QRect SaveRect(this->pos(),this->size());
  config=kapp->getConfig();
  config->setGroup("Geometry");
  config->writeEntry("TrackWindowGeo",SaveRect);
  if (AudioOptWindow!=0) delete(AudioOptWindow);
  if (ISOTreeWindow!=0) delete(ISOTreeWindow);
  if (ISOOptWindow!=0) delete(ISOOptWindow);
 }
  


void TrackWindow::changeTrackMode(int modeindex)
 {
  if (ignsigs) return;
  if (AudioOptWindow!=0) AudioOptWindow->hide();
  if (ISOTreeWindow!=0) ISOTreeWindow->hide();
  if (ISOOptWindow!=0) ISOOptWindow->hide();

  switch (modeindex)
   {
    case 0:
      ThisTrack->setTrackType(CDTrack::Track_Audio);
      break;
    case 1:
      ThisTrack->setTrackType(CDTrack::Track_AudioPreEmph);
      break;
    case 2:
      ThisTrack->setTrackType(CDTrack::Track_DataMode1);
      break;
    case 3:
      ThisTrack->setTrackType(CDTrack::Track_DataMode2);
      break;
    case 4:
      ThisTrack->setTrackType(CDTrack::Track_XA1);
      break;
    case 5:
      ThisTrack->setTrackType(CDTrack::Track_XA2);
      break;
    case 6:
      ThisTrack->setTrackType(CDTrack::Track_CDI);
      break;
   }
  updateWindow();
 }

void TrackWindow::changeSource(void)
 {
  changeSourceType(CombSourceType->currentItem());
 }

void TrackWindow::changeSourceType(int sourcetype)
 {
  KConfig *config;

  config=kapp->getConfig();
  if (ignsigs) return;
  if (AudioOptWindow!=0) AudioOptWindow->hide();
  if (ISOTreeWindow!=0) ISOTreeWindow->hide();
  if (ISOOptWindow!=0) ISOOptWindow->hide();

  switch (sourcetype)
   {
    case 0:
      ThisTrack->clearSource();
      break;
    case 1:
      {
       DriveAccess da;      
       int seltrack;
       if (!da.readTOC())
        {
#if QT_VERSION >= 200
         KMsgBox::message(this,QString::null,locale->translate("No disc in drive!"),KMsgBox::EXCLAMATION);
#else
         KMsgBox::message(this,0,locale->translate("No disc in drive!"),KMsgBox::EXCLAMATION);
#endif
         break;
        }
      
        {
         TrackDialog *dd;
         dd=new TrackDialog(this,0,&da);
         seltrack=dd->exec();
         delete(dd);
         if (seltrack!=0)
          {
           ThisTrack->setTrackType(ThisTrack->getTOCType(da.getTOCType(seltrack),da.getTOCMode(seltrack)));
           ThisTrack->setSourceTrack(seltrack,da.getTOCSum(),da.getTOCDuration(seltrack),
                                     da.getTOCLBA(seltrack));
          }

        }
       break;
      }
    case 2:
      {
       QString qs;
       config->setGroup("Path");
       qs=KFileDialog::getOpenFileName(config->readEntry("PathDatafile",""));
       if (qs.isEmpty()) break;
       KURL::decodeURL(qs);
       ThisTrack->setSourceFile(qs.data());
       config->setGroup("Path");
       config->writeEntry("PathDatafile",qs.data());
       break;
      }
    case 3:
      {
       class ISOImage *isoim;
       isoim=ThisTrack->getISOImage();
       ThisTrack->setSourceFileSystem(isoim);
       if (ThisTrack->getISOImage()==0) break;
       if (isoim==0)
        {
         connect(ThisTrack->getISOImage(),SIGNAL(imageChanged()),
                 this,SLOT(makeImageDirty()));
        }
       ISOTreeWindow=new ISOWindow(0,0,ThisTrack->getISOImage());
       connect(ISOTreeWindow,SIGNAL(closed()),this,SLOT(closedISOTree()));
       connect(ISOTreeWindow,SIGNAL(needUpdate()),this,SLOT(updateWindowContents()));
       ISOTreeWindow->show();
       connect(ISOTreeWindow,SIGNAL(imageChanged()),
                 this,SLOT(makeImageDirty()));

       break;
      }
   }
  updateWindow();
 }

void TrackWindow::changeUseImage(bool useimage)
 {
  if (ignsigs) return;
  if (useimage)
   {
    ThisTrack->enableImage();
   }
   else
   {
    ThisTrack->disableImage();
   }
  updateWindow();
 }

void TrackWindow::changeDescription(const char *descr)
 {
  ThisTrack->setDescription(descr);
  updateWindow();
 }

void TrackWindow::changeDescription(const QString &descr)
 {
  ThisTrack->setDescription(descr.data());
  updateWindow();
 }


void TrackWindow::updateWindowContents(void)
 {
  emit (updateTrack());
  updateWindow();
 }

void TrackWindow::updateWindow(void)
 {
  char properties[2048];
  char tempstring[512];
  int item=0;

  ignsigs=1;
  switch (ThisTrack->getTrackType()) 
   {
    case CDTrack::Track_Audio:
      item=0;
      break;
    case CDTrack::Track_AudioPreEmph:
      item=1;
      break;
    case CDTrack::Track_DataMode1:
      item=2;
      break;
    case CDTrack::Track_DataMode2:
      item=3;
      break;
    case CDTrack::Track_XA1:
      item=4;
      break;
    case CDTrack::Track_XA2:
      item=5;
      break;
    case CDTrack::Track_CDI:
      item=6;
      break;
   }
  CombTrackType->setCurrentItem(item);
  switch(ThisTrack->getTrackSource())
   {
    case CDTrack::Source_None:
      item=0;
      break;
    case CDTrack::Source_CD:
      item=1;
      break;
    case CDTrack::Source_File:
      item=2;
      break;
    case CDTrack::Source_Filesystem: 
      item=3;
      break;
   }
  CombSourceType->setCurrentItem(item);
  ThisTrack->getTrackDescription(tempstring);
  DescriptionEdit->setText(tempstring);
  CheckUseImage->setChecked(ThisTrack->getUseImage());
  ignsigs=0;

  ButtonSelectSource->setEnabled(ThisTrack->getTrackSource()!=CDTrack::Source_None);
  ButtonOptions->setEnabled(
       (ThisTrack->getTrackSource()!=CDTrack::Source_None) &&
       (ThisTrack->isAudio()) ||
       (ThisTrack->getTrackSource()==CDTrack::Source_Filesystem)
                           );


  emit updateTrack();
  
  if (ThisTrack->getTrackSource()==CDTrack::Source_None)
   {
    PropertyLabel->setText("");
    return;
   }

  if (ThisTrack->isAudio())
   {
    AudioFile *afile;
    strcpy(properties,locale->translate("Audio track\n"));
    afile=ThisTrack->getAudioFile();
    if (afile==0)
     {
      strcat(properties,locale->translate("WARNING: unknown format!\n\n"));
     }
     else
     {
      char format[32];
      enum AudioFile::Sample_Endian endi;
      enum AudioFile::Sample_Size sasi;
      int realsiz;

      afile->getFormat(format);
      sprintf(tempstring,locale->translate("Format : %s\n\n"),format);
      strcat(properties,tempstring);
      endi=afile->getEndian();
      if (endi==AudioFile::Endian_Little)
       {
        strcat(properties,locale->translate("Intel byte order\n"));
       }
       else
       {
        strcat(properties,locale->translate("Motorola byte order\n"));
       }
      sasi=afile->getSampleSize();
      realsiz=8;
      if (sasi==AudioFile::Samples_16Bit) realsiz=16;
      if (sasi==AudioFile::Samples_32Bit) realsiz=32;
      sprintf(tempstring,locale->translate("%d Channels - %d Bits\n"),afile->getChannels(),realsiz);
      strcat(properties,tempstring);
      sprintf(tempstring,locale->translate("Sample rate : %ld\n\n"),afile->getSampleRate());
      CDTrack::getDurationHMSB(format,afile->getAbsoluteDuration());
      strcat(properties,tempstring);
      sprintf(tempstring,locale->translate("Absolute length : %s\n"),format);
      strcat(properties,tempstring);
      CDTrack::getDurationHMSB(format,afile->getSelectedDuration());
      sprintf(tempstring,locale->translate("Selected length : %s\n\n"),format);
      strcat(properties,tempstring);
      sprintf(tempstring,locale->translate("Boost factor    : %f\n\n"),
           afile->getBoost());
      strcat(properties,tempstring);
      sprintf(tempstring,locale->translate("Balance         : %f\n\n"),
           afile->getBalance());
      strcat(properties,tempstring);

     }
   }
   else
   {
    strcpy(properties,"Data track\n\n");     
   }
  
  PropertyLabel->setText(properties);
 }

void TrackWindow::openOptions(void)
 {
  if (ThisTrack->isAudio())
   {
    if (AudioOptWindow!=0) return;
    if (ThisTrack->getAudioFile()==0)
     {
      ThisTrack->validateTrack();
      if (ThisTrack->getAudioFile()==0)
       {
#if QT_VERSION >= 200
        KMsgBox::message(this,QString::null,locale->translate("Cannot read source track!"),KMsgBox::EXCLAMATION);
#else
        KMsgBox::message(this,0,locale->translate("Cannot read source track!"),KMsgBox::EXCLAMATION);
#endif
        return;
       }
      updateWindow();
      emit(updateTrack());
     }
    AudioOptWindow=new AudioOptions(0,0,ThisTrack);
    connect(AudioOptWindow,SIGNAL(closed()),this,SLOT(closedAudioOptions()));
    connect(AudioOptWindow,SIGNAL(needUpdate()),this,SLOT(updateWindowContents()));
    connect(AudioOptWindow,SIGNAL(needUpdate()),this,SLOT(makeImageDirty()));
    AudioOptWindow->show();
   }
   else
   {
    if (ThisTrack->getTrackSource()!=CDTrack::Source_Filesystem) return;
    if (ISOOptWindow!=0) return;
    if (ThisTrack->getISOImage()==0) return;
    ISOOptWindow=new ISOOptions(0,0,ThisTrack->getISOImage());
    connect(ISOOptWindow,SIGNAL(closed()),this,SLOT(closedISOOptions()));
    connect(ISOOptWindow,SIGNAL(needUpdate()),this,SLOT(updateWindowContents()));
    ISOOptWindow->show();
   }
 }

void TrackWindow::closedAudioOptions(void)
 {
  delete(AudioOptWindow);
  AudioOptWindow=0;
 }

void TrackWindow::closedISOTree(void)
 {
  delete(ISOTreeWindow);
  ISOTreeWindow=0;
 }

void TrackWindow::closedISOOptions(void)
 {
  delete(ISOOptWindow);
  ISOOptWindow=0;
 }

void TrackWindow::makeImageDirty(void)
 {
  ThisTrack->clearImage();
 }