/*
    Copyright (C) 2000 - 2001 Kai Heitkamp, kai@kde.org

    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.
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

 */

#include <stdlib.h>
#include <string.h>

#include <qpushbutton.h>
#include <qradiobutton.h>
#include <qcheckbox.h>
#include <qcombobox.h>
#include <qlabel.h>
#include <qmultilineedit.h>
#include <qprogressbar.h>

#include <kapplication.h>
#include <klocale.h>
#include <kconfig.h>
#include <kmessagebox.h>

#include "tools.h"
#include "tools.moc"
#include "cddata.h"

Tools::Tools(QWidget *parent, const char *name ) : Tools_GUI(parent, name, true) {
	//Read config
	config = kapp->config();
	config->setGroup( "Config - tools" );

	QCheckBox_Eject->setChecked( config->readBoolEntry("QCheckBox_Eject") );
	QCheckBox_Force->setChecked( config->readBoolEntry("QCheckBox_Force") );
	QCheckBox_generateTOC->setChecked( config->readBoolEntry("QCheckBox_generateTOC") );

	QComboBox_CDRWBlanking->setCurrentItem( config->readNumEntry("QComboBox_CDRWBlanking") );
	QComboBox_WriterSpeed->setCurrentItem( config->readNumEntry("QComboBox_WriterSpeed") );

	//Read program paths into public variables
	config->setGroup("Program paths");
	cdrecord = config->readEntry("cdrecord_path");
}

Tools::~Tools(){
}

//Starts the DeviceControl Tools
void Tools::slot_deviceReset(){
	QString tmp, target;
	KConfig *config = kapp->config();
	CDdata *CD = new CDdata;

	CD->reset( 7 );

	config->setGroup("CD-Writer");
	tmp = config->readEntry("SCSI-Target");
  target = tmp.mid( 6, 1 );
	CD->reset( target.toInt( 0 ) );

	config->setGroup("CD-Reader");
	tmp = config->readEntry("SCSI-Target");
  target = tmp.mid( 6, 1 );
	CD->reset( target.toInt( 0 ) );
}

//---Start cdrecord---
void Tools::slot_start(){
	process.clearArguments();
	process << cdrecord << "-v";

	//Set the CD-Writer first
	config->setGroup("CD-Writer");
	process << config->readEntry("SCSI-Target");

	//Set CD-Writer Options to KProcess
	if( QCheckBox_Eject->isChecked() ) process << "-eject";
	if( QCheckBox_Force->isChecked() ) process << "-force";
	if( QCheckBox_generateTOC->isChecked() ) process << "-fix";

	//Set fifo size
	switch( config->readNumEntry("Fifosize") )
	{
	 	case 0:	process << "fs=4m";
						break;
	 	case 1: process << "fs=8m";
						break;
	 	case 2: process << "fs=12m";
						break;
	 	case 3: process << "fs=16m";
						break;
	 	case 4: process << "fs=20m";
						break;
	 	case 5: process << "fs=24m";
						break;
		case 6: process << "fs=28m";
						break;
		case 7: process << "fs=32m";
						break;
	}

	//Set CD-RW Options to KProcess
	switch( QComboBox_CDRWBlanking->currentItem() )
	{
	 	case 1:	process << "blank=all";
						break;
	 	case 2: process << "blank=fast";
						break;
	 	case 3: process << "blank=track";
						break;
	 	case 4: process << "blank=unreserve";
						break;
	 	case 5: process << "blank=trtrail";
						break;
	 	case 6: process << "blank=unclose";
						break;
		case 7: process << "blank=session";
						break;
	}

	//Set CD-Writer Speed to KProcess
	switch( QComboBox_WriterSpeed->currentItem() )
	{
   	case 0:	process << "speed=1";
						break;
   	case 1:	process << "speed=2";
						break;
   	case 2:	process << "speed=4";
						break;
   	case 3:	process << "speed=6";
						break;
   	case 4:	process << "speed=8";
						break;
   	case 5:	process << "speed=10";
						break;
   	case 6:	process << "speed=12";
						break;
   	case 7:	process << "speed=16";
						break;
   	case 8:	process << "speed=20";
						break;
   	case 9:	process << "speed=24";
						break;
	}

	procoutdlg.StatusLabel->setText( i18n("Prepare for write...") );

	//Connect the Abort-Button from ImgProOut-Dialog to Abort-Handler
	connect( procoutdlg.QPushButton_OK, SIGNAL(clicked()), this, SLOT(abort_handler()));

	//Connect the 'processExited' Signal to the 'slotProcessFinished' Slot
	connect( &process, SIGNAL(processExited(KProcess *)), this, SLOT(slotProcessExited(KProcess *)));

	//Connect with slotRecStderr to update KProgress (Write- / Buffer-Status) and StatusLine
	connect( &process, SIGNAL(receivedStdout (KProcess *, char *, int) ), this, SLOT(slotRecStderr (KProcess *, char *, int) ));
	connect( &process, SIGNAL(receivedStderr (KProcess *, char *, int) ), this, SLOT(slotRecStderr (KProcess *, char *, int) ));

	//Start KProcess
	if( ! process.start( KProcess::NotifyOnExit, KProcess::AllOutput ) ){
		KMessageBox::error( 0, i18n("Could not start cdrecord!"), i18n("KOnCD - Tools - Error") );
		process.disconnect();
		return;
	}

	if ( ! procoutdlg.isVisible() ) procoutdlg.show();
}

//'RecStderr' for cdrecord
void Tools::slotRecStderr( KProcess *, char *buffer, int buflen ){
	char buf[1024];

	if( !buflen ) {
		return;
	}
	memset( buf, 0, sizeof( buf ) );
	strncpy( buf, buffer, buflen > (int) sizeof( buf ) ? sizeof(buf) - 1 : buflen );

	//Add cdrecord messages to the output window
	procoutdlg.Output->append( buf );
	//Go to the end of the output text
	procoutdlg.Output->setCursorPosition( procoutdlg.Output->length(), 0 );

	if( strstr( buf, "Blanking" )) {
		procoutdlg.StatusLabel->setText( i18n("Blanking the CDRW...") );
	}

	if( strstr( buf, "Blanking time" )) {
		procoutdlg.StatusLabel->setText( i18n("Blanking-Process complete.") );
	}

	if( strstr( buf, "Fixating..." )) {
		procoutdlg.StatusLabel->setText( i18n("Writing TOC...") );
	}

	if( strstr( buf, "Fixating time:" )) {
		procoutdlg.StatusLabel->setText( i18n("Burn-Process complete.") );
   	}
}

//Process exited
void Tools::slotProcessExited( KProcess *rcproc ){
	process.disconnect();

	//KProcess did not exit normally
	if( rcproc->exitStatus() == 0 ) {
		procoutdlg.QPushButton_OK->setText( i18n( "&OK" ) );
	}
	else {
		QString statusout;
		statusout.sprintf( I18N_NOOP( "\nError, exit status: %d\n" ), rcproc->exitStatus() );
		procoutdlg.Output->append( statusout );
		procoutdlg.Output->setCursorPosition( procoutdlg.Output->length(), 0 );
		procoutdlg.StatusLabel->setText( i18n( "An error has occurred!" ) );
		procoutdlg.QPushButton_OK->setText( i18n( "&OK" ) );
		KMessageBox::sorry( 0, i18n("The process was aborted!"), i18n("KOnCD - Tools - Info") );
	}
}

//Abort-Handler
void Tools::abort_handler(){
  if ( process.isRunning() ){
    int pid = process.getPid();
    process.kill();
    waitpid( pid, 0, 0 );
  }

	procoutdlg.setCaption( i18n( "KOnCD - Writing CD..." ) );
	procoutdlg.StatusLabel->setText( i18n( "Prepare for write..." ) );
	procoutdlg.Output->setText( "" );
	procoutdlg.WriteProgress->setProgress( 0 );
	procoutdlg.BufferProgress->setProgress( 0 );
	if ( procoutdlg.isVisible() ) procoutdlg.close();

	process.disconnect();
}

//'Quit-Button' clicked
void Tools::slot_quit(){
	//Write config
	KConfig *config = kapp->config();
	config->setGroup( "Config - tools" );
	config->writeEntry( "QCheckBox_Eject", QCheckBox_Eject->isChecked() );
	config->writeEntry( "QCheckBox_Force", QCheckBox_Force->isChecked() );
	config->writeEntry( "QCheckBox_generateTOC", QCheckBox_generateTOC->isChecked() );

	config->writeEntry( "QComboBox_CDRWBlanking", QComboBox_CDRWBlanking->currentItem() );
	config->writeEntry( "QComboBox_WriterSpeed", QComboBox_WriterSpeed->currentItem() );

	close( true );
}
