/**************************************************************************
*   Copyright (C) 2005 by Jean-Michel Petit                               *
*   jm_petit@laposte.net                                                  *
*                                                                         *
*   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.,                                       *
*   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.             *
***************************************************************************/

#include "k9burndvd.h"
#include "k9burndvd.moc"
#include "k9tools.h"
#include <tqdir.h>
#include <tdemessagebox.h>
#include <tdefiledialog.h>
#include <klibloader.h>
#include <kprocess.h>
#include <tqapplication.h>
#include <kstandarddirs.h>

k9BurnDVD::k9BurnDVD()
        : TQObject(NULL,"") {
    cancelled=false;
    useK3b=false;
    autoBurn=false;
    volId="K9Copy";
    iso=false;
    m_filename="";
    progress=new k9Progress(NULL,"progress",NULL);
    TQString s= TDEGlobal::dirs()->findResource( "data", "k9copy/anim.mng");
    progress->setMovie(s);
    m_cdrkit=k9Tools::checkProgram("genisoimage") && k9Tools::checkProgram("wodim");
}



k9BurnDVD::~k9BurnDVD() {
}

/** Read property of TQString burnDevice. */
const TQString& k9BurnDVD::getburnDevice() {
    return burnDevice;
}
/** Write property of TQString burnDevice. */
void k9BurnDVD::setburnDevice( const TQString& _newVal) {
    burnDevice = _newVal;
}
/** Write property of TQString workDir. */
void k9BurnDVD::setworkDir( const TQString& _newVal) {
    workDir = _newVal;
    if (workDir.right(1)!="/")
        workDir +='/';
}

void k9BurnDVD::makeIso(TQString _filename) {
    iso=true;
    m_filename=_filename;
}

void k9BurnDVD::setvolId(TQString _newVal) {
    volId=_newVal.replace(" ","_");
}

void k9BurnDVD::setUseK3b(bool _newVal) {
    useK3b=_newVal;
}

void k9BurnDVD::setAutoBurn(bool _newVal) {
    autoBurn=_newVal;
}
void k9BurnDVD::burn() {
    if (!useK3b) {
        if (! m_cdrkit)
            burnWithGrowisofs();
        else
            burnWithGenisoimage();
    } else
        burnWithK3b();
}

void k9BurnDVD::burnWithK3b() {
    TDEProcess *k3b = new TDEProcess();

    *k3b << "k3b";
    *k3b << TQDir::cleanDirPath(workDir +"/dvd/VIDEO_TS");
    *k3b << "-videodvd";
    k3b->start();
    k3b->detach();
    delete k3b;
}

void k9BurnDVD::mkisoSizeStderr(TDEProcess *proc, char *buffer, int buflen) {
    TQString c=TQString::fromLatin1( buffer,buflen);//   (proc2->readStderr());
    imageSize=c.replace("\n","");
    ;
}

void k9BurnDVD::mkisoSizeStdout(TDEProcess *proc, char *buffer, int buflen) {
    TQString c=TQString::fromLatin1(buffer,buflen);// (proc2->readStdout());
    imageSize=c.replace("\n","");
    ;
}

const TQString k9BurnDVD::getImageSize() {
    TQString c;
    c="mkisofs";
    proc2=new k9Process;
    *proc2 << c;
    *proc2 <<"-quiet";
    *proc2 <<"-print-size";
    *proc2 <<"-dvd-video";
    *proc2 <<"-udf";
    *proc2 <<"-r";
    *proc2 <<"-V "+volId;
    *proc2 << TQDir::cleanDirPath(workDir +"/dvd");

    connect( proc2, TQ_SIGNAL(receivedStderr(TDEProcess *, char *, int )),this, TQ_SLOT(mkisoSizeStderr(TDEProcess *, char *, int)) );
    connect( proc2, TQ_SIGNAL(receivedStdout(TDEProcess *, char *, int)),this, TQ_SLOT(mkisoSizeStdout(TDEProcess *, char *, int)) );
    if (proc2->start(TDEProcess::NotifyOnExit,TDEProcess::All)) {
//        while (proc2->isRunning()) {
//            tqApp->processEvents();
//        }
        proc2->sync();
        if (proc2->exitStatus()==0) {
            delete proc2;
            return imageSize;
        }
    }
    delete proc2;
    return "";
}

void k9BurnDVD::getGenisoimageCmd(k9Process *proc,TQString _fileName,bool _printSize) {
    TQString progname="genisoimage";
    *proc << progname;
    *proc << "-gui";
    *proc << "-graft-points";
    *proc << "-volid" << volId;
    *proc  <<"-appid" << "k9copy";
    *proc << "-volset-size" << "1";
    *proc << "-volset-seqno" << "1";
    *proc << "-no-cache-inodes" << "-udf";
    *proc << "-iso-level" << "1";
    *proc << "-dvd-video";
    if (!_printSize) {
        if (_fileName !="") {
            *proc <<"-o";
            *proc <<_fileName;
        }
        connect( proc, TQ_SIGNAL(receivedStderr(TDEProcess *, char *, int)),this, TQ_SLOT(growisoStderr(TDEProcess *, char *, int)) );
        connect( proc, TQ_SIGNAL(receivedStdout(TDEProcess *, char *, int)),this, TQ_SLOT(growisoStdout(TDEProcess *, char *, int)) );
    } else {
        *proc << "-print-size" << "-quiet";
        connect( proc, TQ_SIGNAL(receivedStderr(TDEProcess *, char *, int )),this, TQ_SLOT(mkisoSizeStderr(TDEProcess *, char *, int)) );
        connect( proc, TQ_SIGNAL(receivedStdout(TDEProcess *, char *, int)),this, TQ_SLOT(mkisoSizeStdout(TDEProcess *, char *, int)) );
    }
    *proc <<TQDir::cleanDirPath(workDir +"/dvd");

}

void k9BurnDVD::getWodimCmd(k9Process *proc) {
    *proc <<"|wodim";
    *proc <<"-dao";
    *proc <<"-overburn";
    *proc <<"-data";

    if (m_speed !=i18n("default"))
        *proc << TQString("speed=%1").arg(m_speed);
    *proc <<TQString("dev=%1").arg(burnDevice);
    *proc <<TQString("tsize=%1s").arg(imageSize);
    *proc << "-";
}

void k9BurnDVD::burnWithGenisoimage() {
    time = new TQTime(0,0);
    time->start();
    progress->setCaption(i18n("k9Copy - Burning DVD"));
    progress->setTitle(i18n("Burning DVD"));
    proc=progress->getProcess();

    bool bok=false;

    while (!cancelled && !bok) {
        burnSpeed=0;
        TQString fileName="";
        if (iso) {
            fileName=m_filename;
            if (fileName =="")
                fileName=KFileDialog::getSaveFileName (TQDir::homeDirPath(),"*.iso", 0,i18n("Save image to disk"));
            if (fileName =="") {
                cancelled=true;
            } 
        }
        proc->clearArguments();
        getGenisoimageCmd(proc,fileName,false);
        if (!iso) {
            k9Process *proc2=new k9Process(NULL,NULL);
            getGenisoimageCmd(proc2,"",true);
            proc2->start(TDEProcess::NotifyOnExit,TDEProcess::All);
            proc2->sync();
            getWodimCmd(proc);
            proc->setUseShell(true);
            if (!autoBurn) {
                if ( KMessageBox::warningContinueCancel ( 0,i18n("Insert a recordable DVD"), i18n("DVD burning"))!=KMessageBox::Continue)
                    cancelled=true;
            }
            tqDebug("%s", proc->debug().ascii());
        }


        if (!cancelled) {
            int res=progress->execute();
            if ( res==-1 ) {
                KMessageBox::error( 0, i18n("Error burning DVD :\n")+i18n("Unable to run %1").arg("genisoimage"), i18n("DVD burning") );
                cancelled=true;
            } else {
                if (proc->exitStatus()==0) {
                    bok=true;
                    KMessageBox::information( 0, i18n("DVD Burning finished"), i18n("DVD burning") );
                    //delete temporary files
                    //        clearOutput(workDir+"dvd");
                } else {
                    TQString c;

                    c=i18n("An error occured while Burning DVD: %1").arg(lastMsg) +"\n" +i18n("Insert an other DVD");
                    if ( KMessageBox::warningContinueCancel ( 0,c, i18n("authoring"))!=KMessageBox::Continue) {
                        cancelled=true;
                    }
                }
            }
        }
    }
}

void k9BurnDVD::burnWithGrowisofs() {
    time = new TQTime(0,0);
    time->start();

    //KLibFactory *factory;
    //factory = KLibLoader::self()->factory("libk9copy");

//    progress=static_cast<k9Progress  *>(factory->create(tqApp->mainWidget(),"progress", "k9Progress"));

    progress->setCaption(i18n("k9Copy - Burning DVD"));
    progress->setTitle(i18n("Burning DVD"));
    bool bok=false;


    while (!cancelled && !bok) {
        burnSpeed=0;
        TQString c,progname;
        if (iso)
            progname="mkisofs";
        else
            progname="growisofs";
        proc=progress->getProcess();
        *proc << progname;

        if (!iso) {
            *proc <<"-overburn";
            *proc <<"-Z";
            *proc <<burnDevice;
            *proc <<"-use-the-force-luke=tty";
            *proc <<"-use-the-force-luke=tracksize:"+getImageSize();
            *proc <<"-use-the-force-luke=dao:" + imageSize;
            *proc <<"-dvd-compat";
            if (m_speed !=i18n("default"))
                *proc <<"-speed=" + m_speed;

        } else {
            TQString fileName=m_filename;
            if (fileName =="")
                fileName=KFileDialog::getSaveFileName (TQDir::homeDirPath(),"*.iso", 0,i18n("Save image to disk"));
            if (fileName !="") {
                *proc <<"-o";
                *proc <<fileName;
            } else
                cancelled=true;

        }

        *proc <<"-dvd-video";
        *proc <<"-udf";
        *proc << "-r";
        *proc <<"-V "+volId;
        *proc <<TQDir::cleanDirPath(workDir +"/dvd");

        connect( proc, TQ_SIGNAL(receivedStderr(TDEProcess *, char *, int)),this, TQ_SLOT(growisoStderr(TDEProcess *, char *, int)) );
        connect( proc, TQ_SIGNAL(receivedStdout(TDEProcess *, char *, int)),this, TQ_SLOT(growisoStdout(TDEProcess *, char *, int)) );
        if (!autoBurn && !iso) {
            c=i18n("Insert a recordable DVD");
            if ( KMessageBox::warningContinueCancel ( 0,c, i18n("DVD burning"))!=KMessageBox::Continue)
                cancelled=true;
        }
        if (!cancelled) {
            int res=progress->execute();
            if ( res==-1 ) {
                KMessageBox::error( 0, i18n("Error burning DVD :\n")+i18n("Unable to run %1").arg(progname), i18n("DVD burning") );
                cancelled=true;
            } else {
                if (proc->exitStatus()==0) {
                    bok=true;
                    KMessageBox::information( 0, i18n("DVD Burning finished"), i18n("DVD burning") );
                    //delete temporary files
                    //        clearOutput(workDir+"dvd");
                } else {
                    TQString c;

                    c=i18n("An error occured while Burning DVD: %1").arg(lastMsg) +"\n" +i18n("Insert an other DVD");
                    if ( KMessageBox::warningContinueCancel ( 0,c, i18n("authoring"))!=KMessageBox::Continue) {
                        cancelled=true;
                    }
                }
            }
        }
    }
    delete time;

}

/** No descriptions */
void k9BurnDVD::growisoStderr(TDEProcess *proc, char *buffer, int buflen) {
    TQString c=TQString::fromLatin1( buffer,buflen);// (proc->readStderr());
    char s[255];
    int a,b;
    int pos;
    lastMsg=c;
    if (c.contains("Current Write Speed")) {
        sscanf(c.latin1(),"%s \"Current Write Speed\" is %d.%d",s,&a,&b);
        burnSpeed=a+b/10;
    }
    if (c.contains("Speed set to")) {
        sscanf(c.latin1(),"Speed set to %d",&a);
        burnSpeed=a/1385;
    }

    progress->setTitle(i18n("Burning DVD"));
    progress->setLabelText(i18n("Current write speed :%1 x").arg(burnSpeed));
    if (c.contains("% done")) {
        pos=c.find("%");
        if (pos!=-1) {
            c=c.mid(1,pos-4);
            //progress->setLabelText(c);
            progress->setProgress(c.toInt(),100);
            float m_percent=c.toFloat()/100;
            TQTime time2(0,0);
            time2=time2.addMSecs(time->elapsed());
            if (m_percent>0) {
                TQTime time3(0,0);
		TQString m_remain;
                time3=time3.addMSecs((uint32_t)(time->elapsed()*(1/m_percent)));
                m_remain=time3.toString("hh:mm:ss");
                progress->setElapsed(time2.toString("hh:mm:ss") +" / " +m_remain);

            }



        }
    }
}
void k9BurnDVD::growisoStdout(TDEProcess *proc, char *buffer, int buflen) {
    TQString c=TQString::fromLatin1( buffer,buflen);// (proc->readStdout());
    int pos;
    pos=c.find("STAT");
    if (pos!=-1) {
        c=c.mid(pos);
        progress->setLabelText(c);
    }
}
