/***************************************************************************
                          NewAudioCdDialog.cpp  -  description
                             -------------------
    begin                : Fri Apr 5 2002
    copyright            : (C) 2002 by alexpod
    email                : alexpod@localhost.localdomain
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/
//#include <iostream.h>

#include <qstring.h>
#include <qcombobox.h>
#include <qtooltip.h>
#include <qslider.h>
#include <qspinbox.h>
#include <qdir.h>
#include <qlabel.h>
#include <qcheckbox.h>
#include <qstringlist.h>
#include <qradiobutton.h>
#include <qlistview.h>
#include <qevent.h>
#include <qdatetime.h>
#include <qlcdnumber.h>
#include <qregexp.h>
#include <qlineedit.h>

#include <kiconloader.h>
#include <kprocess.h>
#include <kmessagebox.h>
#include <kfiledialog.h>
#include <klocale.h>
#include <kconfig.h>
#include <kurl.h>
#include <kdebug.h>

#include "CdboDialogBase.h"
#include "CdboDialogActionFactory.h"

#include "NewAudioCdDialogBase.h"
#include "NewAudioCdDialog.h"
#include "NewAudioCdDialog.moc"

#include "EraseDialog.h"
#include "PreviewDialog.h"

#include "dialogParts/DriveInfoPnl.h"
#include "dialogParts/SpeedPnl.h"
#include "dialogParts/DialogCntPnl.h"


//---------------------------------------------------------------------------------------------
NewAudioCdDialog::NewAudioCdDialog(QStringList *flist, QWidget *parent, const char *name) :
	NewAudioCdDialogBase(parent,name,true),
	CdboDialogBase(CdboDialogBase::NewAudioCdDialogType){
	
	fileList = flist;
	//createImage = true;
	
	init();
	output(CdboDialogBase::InfoMessage, QString::number(fileList->count()) + " track(s) on this list");
}
//---------------------------------------------------------------------------------------------
NewAudioCdDialog::~NewAudioCdDialog(){
	delete factory;
	if(config)
		delete config;
}
//---------------------------------------------------------------------------------------------
void NewAudioCdDialog::init(){

	factory = new CdboDialogActionFactory(this, "NewAudioCdDialogFactory");
	stillDecoding = false;
	stillBurning = false;
	stillChecking = false;
	//stillCreatingOnTheFly = false;
	config = 0;
	
	
	///////////////////////////////////////////////////
	targetDevicePnl->setType(DriveInfoPnl::Target);
	targetDevicePnl->setUsrBtnTitle( i18n("&Erase"));
	/////////////////////////////////////////////////
	dialogCntPnl->setStartBtnTitle( i18n("&Create!"));
	QToolTip::add(dialogCntPnl->getStartBtn(), i18n( "Create!" ) );
	dialogCntPnl->resizeOutputViewColomns(80,550);
	/////////////////////////////////////////////////
	readOptions();
	initBtns();
	targetDevicePnl->closeTray();
	
	// connecting to the Drive Info Panel
	connect( targetDevicePnl->getDetectBtn(), SIGNAL( clicked() ), this, SLOT( detectDestSlot() ) );
	connect( targetDevicePnl->getUsrBtn(), SIGNAL( clicked() ), this, SLOT( eraseSlot() ) );
	
	// connecting to the Dialog Control Panel
	connect( dialogCntPnl->getStartBtn(), SIGNAL( clicked() ), this, SLOT( startBtnSlot() ) );
	connect( dialogCntPnl->getCancelBtn(), SIGNAL( clicked() ), this, SLOT( cancelSlot() ) );
	connect( dialogCntPnl->getSettingsBtn(), SIGNAL( clicked() ), this, SLOT( settingsSlot() ) );
	connect( dialogCntPnl->getQuitBtn(), SIGNAL( clicked() ), this, SLOT( quitSlot() ) );
	
	// connecting to the factory
	connect( factory, SIGNAL( processDone(bool) ), this, SLOT( taskDone(bool) ) );
	connect( factory, SIGNAL( failedToLunchProcess() ), this, SLOT( taskFailedToStart() ) );
	connect( factory, SIGNAL( processCancelled() ), this, SLOT( cancelledByUser() ) );
	

}
//---------------------------------------------------------------------------------------------
void NewAudioCdDialog::saveOptions(){
	if(!config)
		return;
	//////////////////////////////////////////////////////////
	config->setGroup("Audio Create Options");
	config->writeEntry("Type of Create", actionCmb->currentItem());
	config->writeEntry("Number of Copies", numberSpn->value());
	if(saveChk->isChecked()){
		config->writeEntry("Save Audio CD Text", true);
		config->writeEntry("Audio CD Title", titleTxt->text());
		config->writeEntry("Audio CD Artist", perfomTxt->text());
	}
	else{
		config->writeEntry("Audio CD Title", "");
		config->writeEntry("Audio CD Artist", "");
		config->writeEntry("Save Audio CD Text", false);
	}
	config->writeEntry("Type of Audio Create", actionCmb->currentItem());
	speedPnl->saveOptions();
 	targetDevicePnl->saveOptions();
 	
	config->setGroup("Recording Options");
	config->writeEntry("Fixate CD", finalizeChk->isChecked());
	config->setGroup("Audio Create Options");
	config->sync();
}
//---------------------------------------------------------------------------------------------
void NewAudioCdDialog::readOptions(){
	saveOptions();
	if(config)
		delete config;
	config = new KConfig("cdbakeovenrc");
     ///////////////////////////////////////////////////////////////////
	config->setGroup("Audio Create Options");
     	numberSpn->setValue(config->readNumEntry("Number of Copies", 0));
	saveChk->setChecked(config->readBoolEntry("Save Audio CD Text", false));
	titleTxt->setText(config->readEntry("Audio CD Title", ""));
	perfomTxt->setText(config->readEntry("Audio CD Artist", ""));
	actionCmb->setCurrentItem( config->readNumEntry("Type of Audio Create", 0));
	config->setGroup("Recording Options");
	finalizeChk->setChecked(config->readBoolEntry("Fixate CD", true));
	config->setGroup("Audio Create Options");
     	
     speedPnl->readOptions();
     targetDevicePnl->readOptions();
	
}

//---------------------------------------------------------------------------------------------
void NewAudioCdDialog::initBtns(){
	if(targetDevicePnl->isReady()){
       	blockBtns(false);
       	dialogCntPnl->getStartBtn()->setEnabled(true);
       	
       	blockActionBtns(false);
       		
       	dialogCntPnl->status(i18n("Ready"));
	}
      else{
      	blockBtns(true);
      	dialogCntPnl->getCancelBtn()->setEnabled(false);
      	dialogCntPnl->status(i18n("No recording device!" ));
      }
}
//---------------------------------------------------------------------------------------------
void NewAudioCdDialog::blockActionBtns(bool yes){
	numberSpn->setEnabled(!yes);
	customBurnBtn->setEnabled(!yes);
	numOfCopiesLbl->setEnabled(!yes);
}
//----------------------------------------------------------------------------------------------
void NewAudioCdDialog::blockBtns(bool yes) const{
	dialogCntPnl->getStartBtn()->setEnabled(!yes);
	dialogCntPnl->getCancelBtn()->setEnabled(yes);
	speedPnl->setEnabled(!yes);
	detailsPnl->setEnabled(!yes);
	targetDevicePnl->blockBtns(yes);
	if(stillDecoding || stillChecking || stillBurning/* || stillCreatingOnTheFly*/){
		targetDevicePnl->getDetectBtn()->setEnabled(false);
		dialogCntPnl->getSettingsBtn()->setEnabled(false);
		dialogCntPnl->getDumpBtn()->setEnabled(false);
	}
	else{
		targetDevicePnl->getDetectBtn()->setEnabled(true);
		dialogCntPnl->getSettingsBtn()->setEnabled(true);		
		dialogCntPnl->getDumpBtn()->setEnabled(true);
	}
}
//--------------------- used by burn only ----------------------------------------
QString NewAudioCdDialog::getActionType() const{
	int pos = actionCmb->currentItem();
	switch(pos){
		case 1:
			if(copiesDone == 0)
				return "dummy";
			else
				return "burn";
		case 2:
			return "dummy";
		
		default:
			return "burn";		
	}
	return "";
}

//---------------------------------------------------------------------------------------------
void NewAudioCdDialog::customBtnSlot(){
	KShellProcess *cdboProc = new KShellProcess();
	*cdboProc << "kcmshell cdboburnopt";
	connect(cdboProc, SIGNAL(processExited(KProcess*)), this, SLOT(kcmshellDone(KProcess*)));
	if(!cdboProc->start(KProcess::NotifyOnExit))
		kdDebug() << "Failed to start" << endl;
}
//---------------------------------------------------------------------------------------------
void NewAudioCdDialog::settingsSlot(){
	KShellProcess *cdboProc = new KShellProcess();
	*cdboProc << "kcmshell cdbodefaultopt";
	connect(cdboProc, SIGNAL(processExited(KProcess*)), this, SLOT(kcmshellDone(KProcess*)));
	if(!cdboProc->start(KProcess::NotifyOnExit))
		kdDebug() << "Failed to start" << endl;
}
//---------------------------------------------------------------------------------------------
void NewAudioCdDialog::detectDestSlot(){
	KShellProcess *cdboProc = new KShellProcess();
	*cdboProc << "kcmshell cdbocdromdevices kcmdf";
	connect(cdboProc, SIGNAL(processExited(KProcess*)), this, SLOT(kcmshellDone(KProcess*)));
	if(!cdboProc->start(KProcess::NotifyOnExit))
		kdDebug() << "Failed to start" << endl;
}
//---------------------------------------------------------------------------------------------
void NewAudioCdDialog::kcmshellDone(KProcess *proc){
	delete proc;
	readOptions();
	if(!(stillDecoding || stillChecking || stillBurning/* || stillCreatingOnTheFly*/))
		initBtns();
}
//---------------------------------------------------------------------------------------------
void NewAudioCdDialog::eraseSlot(){
	if(config)
		delete config;
	config = new KConfig("cdbakeovenrc");
     ///////////////////////////////////////////////////////////////////
	config->setGroup("Audio Create Options");
	config->writeEntry("Audio CD Title", titleTxt->text());
	config->writeEntry("Audio CD Artist", perfomTxt->text());
	hide();
	EraseDialog *ed = new EraseDialog((QWidget *)parent(),"eraseD");
	ed->exec();
	delete ed;
	readOptions();
	initBtns();
	exec();
}
//---------------------------------------------------------------------------------------------
void NewAudioCdDialog::cancelSlot(){
	if((stillBurning || stillDecoding) && !confermExit())
		return;
	else{
		factory->killCurrentTask();
		cleanUp();
		output(CdboDialogBase::StatusNotOkMessage, i18n("Cancelled by user."));
		
		dialogCntPnl->stopForwardTimer();
		factory->resetSessionType();
		stillDecoding = false;
		stillBurning = false;
		blockBtns(false);
		readOptions();
		initBtns();
		status(i18n("Ready"));
	}
}
//---------------------------------------------------------------------------------------------
void NewAudioCdDialog::quitSlot(){
	if(stillBurning || stillDecoding/* || stillCreatingOnTheFly*/){
		if(!confermExit()) return;
		else{
			factory->killCurrentTask();
			cleanUp();
			saveOptions();
			accept();
		}
	}
	else{
		saveOptions();
		accept();
	}
}
//---------------------------------------------------------------------------------------------
void NewAudioCdDialog::closeEvent(QCloseEvent *e){
	if(stillBurning || stillDecoding/* || stillCreatingOnTheFly*/){
		if(!confermExit())
			e->ignore();
		else{
			factory->killCurrentTask();
			cleanUp();
			e->accept();
		}
	}
	else
		e->accept();
}

//---------------------------------------------------------------------------------------------
void NewAudioCdDialog::keyPressEvent(QKeyEvent *e){
	if(e->key() == Key_Escape){
        	if(stillBurning || stillDecoding){
        		if(!confermExit()){
        			//e->ignore();
        			return;
        		}
        		else{
        			factory->killCurrentTask();
				cleanUp();
           			accept();
         			
			}
        	}
        	accept();
	}
	if(e->key() == Key_F2){
		settingsSlot();
	}
}
//----------------------------------------------------------------------------------------------
bool NewAudioCdDialog::confermExit(){
	QString message;
	if(stillBurning)
		 message = i18n("Aborting now may damage your media or hang your system!  Click \"Quit\" to abort.");
	else
		message = i18n("This will abort CD creation process! Click \"Quit\" to abort.");
	int result = KMessageBox::warningContinueCancel(this,
	   message,
        i18n("This may hang your system!"),
        i18n("&Quit"));
    	switch(result) {
    		case KMessageBox::Continue:
    			return true;
		
		case KMessageBox::Cancel:
        		return false;
    	}
    	return false;
}
//---------------------------------------------------------------------------------------------
void NewAudioCdDialog::startBtnSlot(){
	saveOptions();
	dialogCntPnl->clearOutput();
	dialogCntPnl->startForwardTimer();
	
	stillDecoding = true;
	tmpList.clear();
	tracksList.clear();
	factory->decompressAudio(fileList, &tracksList, &tmpList);
	
}	

//---------------------------------------------------------------------------------------------
void NewAudioCdDialog::startBurn(){
	targetDevicePnl->closeTray();
	
	stillBurning = true;
	
	copiesDone = 0;
	if(actionCmb->currentItem() == 2)
		copiesWanted = 0;
	else if(actionCmb->currentItem() == 1)
		copiesWanted = numberSpn->value() + 1;
	else
		copiesWanted = numberSpn->value();
	
	/////////////////////////////////////////			
	config->setGroup("Recording Options");
	stillChecking = config->readBoolEntry("Check Drive First", false);
	if(stillChecking)
		factory->checkDrive();
	else{
		QString s = "'" + tracksList.join("' '");
		factory->burn(s + "'", true);
	}
}
//---------------------------------------------------------------------------------------------
void NewAudioCdDialog::taskDone(bool success){
	if(!success){
		dialogCntPnl->stopForwardTimer();
		cleanUp();
		
		stillDecoding = false;
		stillBurning = false;
		stillChecking = false;
		readOptions();
		initBtns();
		factory->resetSessionType();
		return;
	}
	
	if(stillDecoding){
		stillDecoding = false;
		startBurn();
		return;

///////////////////////////////////////////////////////////////////////////////////////////////////////////////
/*		dialogCntPnl->stopForwardTimer();
		factory->resetSessionType();
		readOptions();
		initBtns();
		return;
	*/	
	}
	else if(stillChecking){
		stillChecking = false;
     	/////////////////////////////////////////			
      	config->setGroup("Recording Options");
		if(config->readBoolEntry("Eject Media At End", true))
			targetDevicePnl->setEjected();
		QString s = "'" + tracksList.join("' '");
		factory->burn(s + "'", true);
	}
	else if(stillBurning){
		copiesDone++;
  		if(copiesDone < copiesWanted){
			int fix = 0;
			if(copiesDone == 1 && actionCmb->currentItem() == 1){
				output(CdboDialogBase::StatusOkMessage, i18n("Dummy run completed successfully!"));
					/////////////////////////////////////
					
				int result = KMessageBox::questionYesNo(this,
						i18n("Dummy run completed successfully! Continue with burn?"),
        					i18n("Continue with Burn?"));
				switch(result) {
    					case KMessageBox::No:{
    						///////////////////////=====================
						dialogCntPnl->stopForwardTimer();
						stillBurning = false;
						cleanUp();/////////////////////////////////////////////////////////////
						blockBtns(false);
						factory->resetSessionType();
						readOptions();
						initBtns();
						return;
					}///////////////////////=====================
					case KMessageBox::Yes:{
						QString s = "'" + tracksList.join("' '");
						factory->burn(s + "'", true);
						return;
					}
				}
			}
			else
				fix = 1;
			
			output(CdboDialogBase::StatusOkMessage, "" + QString::number(copiesDone - fix) +
				i18n(" of ") + QString::number(copiesWanted - fix) +
				i18n(" burned successfully!"));
			KMessageBox::information(this,
				"" + QString::number(copiesDone - fix) + i18n(" of ") +
				QString::number(copiesWanted - fix) + i18n("  requested copies are done! " \
	   			"Please insert the next CD-R(W) and click 'OK'."),
	   			i18n("Please Insert Next CD-R(W)"));

	   		/////////////////////////////////////////			
			config->setGroup("Recording Options");
     			if(config->readBoolEntry("Eject Media At End", true))
     				targetDevicePnl->setEjected();
     			
     			QString s = "'" + tracksList.join("' '");
			factory->burn(s + "'", true);
		}
		else{
			dialogCntPnl->stopForwardTimer();
			stillBurning = false;
			if(actionCmb->currentItem() == 2)
				output(CdboDialogBase::StatusOkMessage, i18n("Dummy run completed successfully!"));
			else
				output(CdboDialogBase::StatusOkMessage, i18n("Operation completed successfully!"));
				
			cleanUp();
			blockBtns(false);
			factory->resetSessionType();
			readOptions();
			initBtns();
		}
	}
}
//---------------------------------------------------------------------------------------------
void NewAudioCdDialog::taskFailedToStart(){
	dialogCntPnl->stopForwardTimer();
	stillDecoding = false;
	stillBurning = false;
	cleanUp();
	stillChecking = false;
	readOptions();
	initBtns();
}
//---------------------------------------------------------------------------------------------
void NewAudioCdDialog::cancelledByUser(){
	dialogCntPnl->stopForwardTimer();
	stillDecoding = false;
	readOptions();
	initBtns();
	stillChecking = false;
	stillBurning = false;
}
//---------------------------------------------------------------------------------------------
void NewAudioCdDialog::cleanUp(){
	if(tmpList.count() == 0)
		return;
	for(unsigned int i = 0; i < tmpList.count(); i++)
		factory->removeOneFile(tmpList[i]);
}

