/*
 *
 * $Id: k3bvcddoc.cpp,v 1.13 2004/01/21 10:20:19 trueg Exp $
 * Copyright (C) 2003 Christian Kvasny <chris@k3b.org>
 *
 * This file is part of the K3b project.
 * Copyright (C) 1998-2004 Sebastian Trueg <trueg@k3b.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.
 * See the file "COPYING" for the exact licensing terms.
 */

// QT-includes
#include <qstring.h>
#include <qstringlist.h>
#include <qfile.h>
#include <qdatastream.h>
#include <qdom.h>
#include <qdatetime.h>
#include <qtimer.h>
#include <qtextstream.h>

// KDE-includes
#include <kprocess.h>
#include <kurl.h>
#include <kapplication.h>
#include <kmessagebox.h>
#include <kconfig.h>
#include <klocale.h>
#include <kstandarddirs.h>
#include <kio/global.h>
#include <kdebug.h>

// K3b-includes
#include "k3bvcddoc.h"
#include "k3bvcdview.h"
#include "k3bvcdtrack.h"
#include "k3bvcdburndialog.h"
#include "k3bvcdjob.h"
#include <k3bglobals.h>
#include <k3bmsf.h>


bool desperate_mode = false;
bool preserve_header = false;
bool print_progress = true;
bool aspect_correction = false;
byte forced_sequence_header = 0;

K3bVcdDoc::K3bVcdDoc( QObject* parent )
        : K3bDoc( parent )
{
    m_tracks = 0L;
    m_vcdOptions = new K3bVcdOptions();

    m_docType = VCD;
    m_vcdType = NONE;

    m_urlAddingTimer = new QTimer( this );
    connect( m_urlAddingTimer, SIGNAL( timeout() ), this, SLOT( slotWorkUrlQueue() ) );

  // FIXME: remove the newTracks() signal and replace it with the changed signal
  connect( this, SIGNAL(newTracks()), this, SIGNAL(changed()) );
  connect( this, SIGNAL(trackRemoved(K3bVcdTrack*)), this, SIGNAL(changed()) );
}

K3bVcdDoc::~K3bVcdDoc()
{
    if ( m_tracks ) {
        m_tracks->setAutoDelete( true );
        delete m_tracks;
    }

    delete m_vcdOptions;
}

bool K3bVcdDoc::newDocument()
{
  if( m_tracks )
    while( m_tracks->first() )
      removeTrack( m_tracks->first() );
  else
    m_tracks = new QPtrList<K3bVcdTrack>;
  m_tracks->setAutoDelete( false );

  return K3bDoc::newDocument();
}

KIO::filesize_t K3bVcdDoc::calcTotalSize() const
{
    unsigned long long sum = 0;
    if ( m_tracks ) {
        for ( K3bVcdTrack* track = m_tracks->first(); track; track = m_tracks->next() ) {
            sum += track->size();
        }
    }
    return sum;
}

KIO::filesize_t K3bVcdDoc::size() const
{
    // mode2 -> mode1 int(( n+2047 ) / 2048) * 2352
    // mode1 -> mode2 int(( n+2351 ) / 2352) * 2048
    long tracksize = long( ( calcTotalSize() + 2351 ) / 2352 ) * 2048;
    return tracksize + ISOsize();
}

KIO::filesize_t K3bVcdDoc::ISOsize() const
{
    // 136000b for vcd iso reseved
    long long iso_size = 136000;
    if ( vcdOptions() ->CdiSupport() ) {
        iso_size += vcdOptions() ->CDIsize();
    }

    return iso_size;
}

K3b::Msf K3bVcdDoc::length() const
{
    return K3b::Msf( size() / 2048 );
}


bool K3bVcdDoc::isImage( const KURL& url )
{
    QImage p;
    return p.load( QFile::encodeName( url.path() ) );
}

void K3bVcdDoc::addUrls( const KURL::List& urls )
{
  // make sure we add them at the end even if urls are in the queue
  addTracks( urls, 99 );
}

void K3bVcdDoc::addTracks( const KURL::List& urls, uint position )
{
    for ( KURL::List::ConstIterator it = urls.begin(); it != urls.end(); it++ ) {
        urlsToAdd.enqueue( new PrivateUrlToAdd( *it, position++ ) );
    }

    m_urlAddingTimer->start( 0 );
}

void K3bVcdDoc::slotWorkUrlQueue()
{
    if ( !urlsToAdd.isEmpty() ) {
        PrivateUrlToAdd* item = urlsToAdd.dequeue();
        lastAddedPosition = item->position;

        // append at the end by default
        if ( lastAddedPosition > m_tracks->count() )
            lastAddedPosition = m_tracks->count();

        if ( !item->url.isLocalFile() ) {
            kdDebug() << item->url.path() << " no local file" << endl;
            return ;
        }

        if ( !QFile::exists( item->url.path() ) ) {
	  kdDebug() << "(K3bVcdDoc) file not found: " << item->url.path() << endl;
            m_notFoundFiles.append( item->url.path() );
            return ;
        }

        if ( K3bVcdTrack* newTrack = createTrack( item->url ) )
            addTrack( newTrack, lastAddedPosition );

        delete item;

        emit newTracks();
    } else {
        m_urlAddingTimer->stop();

        emit newTracks();

        // reorder pbc tracks
        setPbcTracks();

        informAboutNotFoundFiles();
    }
}


K3bVcdTrack* K3bVcdDoc::createTrack( const KURL& url )
{
    char filename[ 255 ];
    strcpy( filename, QFile::encodeName( url.path() ) );
    mpeg* Mpeg = new mpeg( filename, 0 );

    if ( Mpeg ) {
        int mpegVersion = Mpeg->MpegVersion();
        // no mpeg audio files at this time!!
        if ( mpegVersion > 0 && Mpeg->has_video() ) {

            if ( vcdType() == NONE && mpegVersion < 2 ) {
                m_urlAddingTimer->stop();
                setVcdType( vcdTypes( mpegVersion ) );
                vcdOptions() ->setMpegVersion( mpegVersion );
                KMessageBox::information( kapp->mainWidget(),
                                          i18n( "K3b will create a %1 image from the given MPEG "
                                          "files, but these files must already be in %2 "
                                          "format. K3b performs no resample on MPEG files." )
                                          .arg(i18n("VCD"))
                                          .arg(i18n("VCD")),
                                          i18n( "Information" ) );
                m_urlAddingTimer->start( 0 );
            } else if ( vcdType() == NONE ) {
                m_urlAddingTimer->stop();
                vcdOptions() ->setMpegVersion( mpegVersion );
                bool force = false;
                force = ( KMessageBox::questionYesNo( kapp->mainWidget(),
                                                      i18n( "K3b will create a %1 image from the given MPEG "
                                                      "files, but these files must already be in %2 "
                                                      "format. K3b performs no resample on MPEG files yet." )
                                                      .arg(i18n("SVCD"))
                                                      .arg(i18n("SVCD"))
                                                      + "\n\n"
                                                      + i18n( "Note: Forcing mpeg2 as VCD is not supported by "
                                                      "some standalone DVD players." ),
                                                      i18n( "Information" ),
                                                      i18n( "&OK" ),
                                                      i18n( "Forcing VCD" ) ) == KMessageBox::No );
                if ( force ) {
                    setVcdType( vcdTypes( 1 ) );
                    vcdOptions() ->setAutoDetect( false );
                } else
                    setVcdType( vcdTypes( mpegVersion ) );

                m_urlAddingTimer->start( 0 );
            }


            if ( numOfTracks() > 0 && vcdOptions() ->mpegVersion() != mpegVersion ) {
                KMessageBox::error( kapp->mainWidget(), "(" + url.path() + ")\n" +
                                    i18n( "You cannot mix MPEG1 and MPEG2 video files.\nPlease start a new Project for this filetype.\nResample not implemented in K3b yet." ),
                                    i18n( "Wrong File Type for this Project" ) );

                delete Mpeg;
                return 0;
            }
            K3bVcdTrack* newTrack = new K3bVcdTrack( m_tracks, url.path() );
            char HMS[ 30 ];
            QString mt;
            Mpeg->SecsToHMS( HMS, Mpeg->Video->duration );
            newTrack->setMpegType( Mpeg->MpegType );
            newTrack->setMpegVideoVersion( Mpeg->mpeg_version );

            mt.append( " " + i18n( "MPEG%1" ).arg( mpegVersion ) );

            newTrack->setMpegDisplaySize( QString( " %1 x %2" ).arg( Mpeg->Video->hsize ).arg( Mpeg->Video->vsize ) );
            if ( Mpeg->DExt ) {
                newTrack->setMpegDExt( true );
                newTrack->setMpegFormat( Mpeg->DExt->video_format );
                switch ( Mpeg->DExt->video_format ) {
                    case 0 :
                        mt.append( "  " + i18n( "Component" ) );
                        break;
                    case 1 :
                        mt.append( "  " + i18n("PAL") );
                        break;
                    case 2 :
                        mt.append( "  " + i18n("NTSC") );
                        break;
                    case 3 :
                        mt.append( "  " + i18n("SECAM") );
                        break;
                    case 4 :
                        mt.append( "  " + i18n("MAC") );
                        break;
                    case 5 :
                        mt.append( "  " + i18n( "Unspecified" ) );
                        break;
                }
                if ( ( Mpeg->DExt->h_display_size != Mpeg->Video->hsize ) || ( Mpeg->DExt->v_display_size != Mpeg->Video->vsize ) )
                    newTrack->setMpegDisplaySize( QString( " %1 x %2" ).arg( Mpeg->DExt->h_display_size ).arg( Mpeg->DExt->v_display_size ) );
            }

            newTrack->setMpegSize( QString( " %1 x %2" ).arg( Mpeg->Video->hsize ).arg( Mpeg->Video->vsize ) );
            newTrack->setMpegFps( QString( " %1" ).arg( Mpeg->Video->frame_rate ) );
            newTrack->setMpegMbps( QString( " %1" ).arg( Mpeg->Video->bitrate / 2500.0 ) );

            newTrack->setMpegDuration( HMS );
            newTrack->setMpegVersion( mt );

            newTrack->setMpegAspectRatio( Mpeg->Video->aspect_ratio );

            if ( Mpeg->SExt ) {
                newTrack->setMpegSExt( true );
                newTrack->setMpegProgressive( Mpeg->SExt->progressive );
                newTrack->setMpegChromaFormat( Mpeg->SExt->chroma_format );
            }
            // audio
            if ( Mpeg->has_audio() ) {
                Mpeg->SecsToHMS( HMS, Mpeg->Audio->duration );
                newTrack->setHasAudio( true );
                newTrack->setMpegAudioCopyright( Mpeg->Audio->copyright );
                newTrack->setMpegAudioOriginal( Mpeg->Audio->original );
                newTrack->setMpegAudioEmphasis( Mpeg->Audio->emphasis_index );
                newTrack->setMpegAudioType( Mpeg->Audio->mpeg_ver );
                newTrack->setMpegAudioLayer( Mpeg->Audio->layer );
                newTrack->setMpegAudioDuration( HMS );
                newTrack->setMpegAudioKbps( QString( "%1" ).arg( Mpeg->Audio->bitrate ) );
                newTrack->setMpegAudioHz( QString( "%1" ).arg( Mpeg->Audio->sampling_rate ) );
                newTrack->setMpegAudioFrame( QString( "%1" ).arg( Mpeg->Audio->frame_length ) );
                newTrack->setMpegAudioMode( Mpeg->Audio->mode );
                newTrack->setMpegAudioModeExt( Mpeg->Audio->modext );
            }

            // set defaults;
            newTrack->setPlayTime( vcdOptions()->PbcPlayTime() );
            newTrack->setWaitTime( vcdOptions()->PbcWaitTime() );

            // for debugging
            Mpeg->PrintInfos();
            delete Mpeg;
            return newTrack;
        }
    } else if ( isImage( url ) ) { // image track
            // for future use
            // photoalbum starts here
            // return here the new photoalbum track
     }

     // error (unsupported files)
     KMessageBox::error( kapp->mainWidget(), "(" + url.path() + ")\n" +
                         i18n( "Only MPEG1 and MPEG2 video files are supported." ),
                         i18n( "Wrong File Format" ) );
    
     return 0;
}


void K3bVcdDoc::addTrack( const KURL& url, uint position )
{
    urlsToAdd.enqueue( new PrivateUrlToAdd( url, position ) );

    m_urlAddingTimer->start( 0 );
}


void K3bVcdDoc::addTrack( K3bVcdTrack* track, uint position )
{
    if ( m_tracks->count() >= 98 ) {
        kdDebug() << "(K3bVcdDoc) VCD Green Book only allows 98 tracks." << endl;
        // TODO: show some messagebox
        delete track;
        return ;
    }

    lastAddedPosition = position;

    if ( !m_tracks->insert( position, track ) ) {
        lastAddedPosition = m_tracks->count();
        m_tracks->insert( m_tracks->count(), track );
    }

    emit newTracks();

    setModified( true );
}


void K3bVcdDoc::removeTrack( K3bVcdTrack* track )
{
    if ( !track ) {
        return ;
    }

    // set the current item to track
    if ( m_tracks->findRef( track ) >= 0 ) {
        // take the current item
        track = m_tracks->take();

        // remove all pbc references to us?
        if ( track->hasRevRef() )
            track->delRefToUs();

        // remove all pbc references from us?
        track->delRefFromUs();

        // emit signal before deleting the track to avoid crashes
        // when the view tries to call some of the tracks' methods
        emit trackRemoved(track);

        delete track;

        if ( numOfTracks() == 0 ) {
            setVcdType( NONE );
            vcdOptions() ->setAutoDetect( true );
        }

        // reorder pbc tracks
        setPbcTracks();
    }
}

void K3bVcdDoc::moveTrack( const K3bVcdTrack* track, const K3bVcdTrack* after )
{
    if ( track == after )
        return ;

    // set the current item to track
    m_tracks->findRef( track );
    // take the current item
    track = m_tracks->take();

    // if after == 0 findRef returnes -1
    int pos = m_tracks->findRef( after );
    m_tracks->insert( pos + 1, track );

    // reorder pbc tracks
    setPbcTracks();

    emit changed();
}


K3bView* K3bVcdDoc::newView( QWidget* parent )
{
    return new K3bVcdView( this, parent );
}


QString K3bVcdDoc::documentType() const
{
    return "vcd";
}


K3bBurnJob* K3bVcdDoc::newBurnJob()
{
    return new K3bVcdJob( this );
}

void K3bVcdDoc::informAboutNotFoundFiles()
{
    if ( !m_notFoundFiles.isEmpty() ) {
        KMessageBox::informationList( view(), i18n( "Could not find the following files:" ),
                                      m_notFoundFiles, i18n( "Not Found" ) );

        m_notFoundFiles.clear();
    }
}

void K3bVcdDoc::setVcdType( int type )
{
    m_vcdType = type;
    switch ( type ) {
        case 0:
            //vcd 1.1
            vcdOptions() ->setVcdClass( "vcd" );
            vcdOptions() ->setVcdVersion( "1.1" );
            break;
        case 1:
            //vcd 2.0
            vcdOptions() ->setVcdClass( "vcd" );
            vcdOptions() ->setVcdVersion( "2.0" );
            break;
        case 2:
            //svcd 1.0
            vcdOptions() ->setVcdClass( "svcd" );
            vcdOptions() ->setVcdVersion( "1.0" );
            break;
        case 3:
            //hqvcd 1.0
            vcdOptions() ->setVcdClass( "hqvcd" );
            vcdOptions() ->setVcdVersion( "1.0" );
            break;

    }
}

void K3bVcdDoc::setPbcTracks()
{
    // reorder pbc tracks
    /*
    if ( !vcdOptions()->PbcEnabled() )
        return;
    */

    if ( m_tracks ) {
        int count = m_tracks->count();
        kdDebug() << QString( "K3bVcdDoc::setPbcTracks() - we have %1 tracks in list." ).arg( count ) << endl;

        QPtrListIterator<K3bVcdTrack> iterTrack( *m_tracks );
        K3bVcdTrack* track;
        while ( ( track = iterTrack.current() ) != 0 ) {
            ++iterTrack;
            for ( int i = 0; i < K3bVcdTrack::_maxPbcTracks; i++ ) {
                // do not change userdefined tracks
                if ( !track->isPbcUserDefined( i ) ) {
                    if ( track->getPbcTrack( i ) )
                        track->getPbcTrack( i ) ->delFromRevRefList( track );

                    K3bVcdTrack* t = 0L;
                    int index = track->index();

                    // we are the last track
                    if ( index == count - 1 ) {
                        switch ( i ) {
                            case K3bVcdTrack::PREVIOUS:
                                // we are not alone :)
                                if ( count > 1 ) {
                                    t = at( index - 1 );
                                    t->addToRevRefList( track );
                                    track->setPbcTrack( i, t );
                                } else {
                                    track->setPbcTrack( i );
                                    track->setPbcNonTrack( i, K3bVcdTrack::VIDEOEND );
                                }
                                break;
                            case K3bVcdTrack::AFTERTIMEOUT:
                            case K3bVcdTrack::NEXT:
                                track->setPbcTrack( i );
                                track->setPbcNonTrack( i, K3bVcdTrack::VIDEOEND );
                                break;
                            case K3bVcdTrack::RETURN:
                                track->setPbcTrack( i );
                                track->setPbcNonTrack( i, K3bVcdTrack::VIDEOEND );
                                break;
                            case K3bVcdTrack::DEFAULT:
                                track->setPbcTrack( i );
                                track->setPbcNonTrack( i, K3bVcdTrack::DISABLED );
                                break;
                        }
                    }
                    // we are the first track
                    else if ( index == 0 ) {
                        switch ( i ) {
                            case K3bVcdTrack::PREVIOUS:
                                track->setPbcTrack( i );
                                track->setPbcNonTrack( i, K3bVcdTrack::VIDEOEND );
                                break;
                            case K3bVcdTrack::AFTERTIMEOUT:
                            case K3bVcdTrack::NEXT:
                                t = at( index + 1 );
                                t->addToRevRefList( track );
                                track->setPbcTrack( i, t );
                                break;
                            case K3bVcdTrack::RETURN:
                                track->setPbcTrack( i );
                                track->setPbcNonTrack( i, K3bVcdTrack::VIDEOEND );
                                break;
                            case K3bVcdTrack::DEFAULT:
                                track->setPbcTrack( i );
                                track->setPbcNonTrack( i, K3bVcdTrack::DISABLED );
                                break;
                        }
                    }
                    // we are one of the other tracks and have PREVIOUS and NEXT Track
                    else {
                        switch ( i ) {
                            case K3bVcdTrack::PREVIOUS:
                                t = at( index - 1 );
                                t->addToRevRefList( track );
                                track->setPbcTrack( i, t );
                                break;
                            case K3bVcdTrack::AFTERTIMEOUT:
                            case K3bVcdTrack::NEXT:
                                t = at( index + 1 );
                                t->addToRevRefList( track );
                                track->setPbcTrack( i, t );
                                break;
                            case K3bVcdTrack::RETURN:
                                track->setPbcTrack( i );
                                track->setPbcNonTrack( i, K3bVcdTrack::VIDEOEND );
                                break;
                            case K3bVcdTrack::DEFAULT:
                                track->setPbcTrack( i );
                                track->setPbcNonTrack( i, K3bVcdTrack::DISABLED );
                                break;
                        }
                    }
                }
            }
        }
    }
}

void K3bVcdDoc::loadDefaultSettings( KConfig* c )
{
  K3bDoc::loadDefaultSettings(c);

  // FIXME: This are userdefined k3b defaults. should this move to general vcd options?

  c->setGroup( "Video project settings" );
  vcdOptions()->setPbcEnabled( c->readBoolEntry("Use Playback Control", false) );
  vcdOptions()->setPbcNumKeys( c->readBoolEntry("Use numeric keys to navigate chapters", false) );
  vcdOptions()->setPbcPlayTime( c->readNumEntry( "Play each Sequence/Segment", 1 ) );
  vcdOptions()->setPbcWaitTime( c->readNumEntry( "Time to wait after each Sequence/Segment", 2 ) );
}


bool K3bVcdDoc::loadDocumentData( QDomElement* root )
{
    newDocument();

    QDomNodeList nodes = root->childNodes();

    if ( nodes.length() < 3 )
        return false;

    if ( nodes.item( 0 ).nodeName() != "general" )
        return false;
    if ( !readGeneralDocumentData( nodes.item( 0 ).toElement() ) )
        return false;

    if ( nodes.item( 1 ).nodeName() != "vcd" )
        return false;

    if ( nodes.item( 2 ).nodeName() != "contents" )
        return false;


    // vcd Label
    QDomNodeList vcdNodes = nodes.item( 1 ).childNodes();

    for ( uint i = 0; i < vcdNodes.count(); i++ ) {
        QDomNode item = vcdNodes.item( i );
        QString name = item.nodeName();

        kdDebug() << QString("(K3bVcdDoc::loadDocumentData) nodeName = '%1'").arg( name ) << endl;

        if ( name == "volumeId" )
            vcdOptions() ->setVolumeId( item.toElement().text() );
        else if ( name == "albumId" )
            vcdOptions() ->setAlbumId( item.toElement().text() );
        else if ( name == "volumeSetId" )
            vcdOptions() ->setVolumeSetId( item.toElement().text() );
        else if ( name == "preparer" )
            vcdOptions() ->setPreparer( item.toElement().text() );
        else if ( name == "publisher" )
            vcdOptions() ->setPublisher( item.toElement().text() );
        else if ( name == "vcdType" )
            setVcdType( vcdTypes(item.toElement().text().toInt()) );
        else if ( name == "mpegVersion" )
            vcdOptions() ->setMpegVersion( item.toElement().text().toInt() );
        else if ( name == "PreGapLeadout" )
            vcdOptions() ->setPreGapLeadout( item.toElement().text().toInt() );
        else if ( name == "PreGapTrack" )
            vcdOptions() ->setPreGapTrack( item.toElement().text().toInt() );
        else if ( name == "FrontMarginTrack" )
            vcdOptions() ->setFrontMarginTrack( item.toElement().text().toInt() );
        else if ( name == "RearMarginTrack" )
            vcdOptions() ->setRearMarginTrack( item.toElement().text().toInt() );
        else if ( name == "FrontMarginTrackSVCD" )
            vcdOptions() ->setFrontMarginTrackSVCD( item.toElement().text().toInt() );
        else if ( name == "RearMarginTrackSVCD" )
            vcdOptions() ->setRearMarginTrackSVCD( item.toElement().text().toInt() );
        else if ( name == "volumeCount" )
            vcdOptions() ->setVolumeCount( item.toElement().text().toInt() );
        else if ( name == "volumeNumber" )
            vcdOptions() ->setVolumeNumber( item.toElement().text().toInt() );
        else if ( name == "AutoDetect" )
            vcdOptions() ->setAutoDetect( item.toElement().text().toInt() );
        else if ( name == "CdiSupport" )
            vcdOptions() ->setCdiSupport( item.toElement().text().toInt() );
        else if ( name == "NonCompliantMode" )
            vcdOptions() ->setNonCompliantMode( item.toElement().text().toInt() );
        else if ( name == "Sector2336" )
            vcdOptions() ->setSector2336( item.toElement().text().toInt() );
        else if ( name == "UpdateScanOffsets" )
            vcdOptions() ->setUpdateScanOffsets( item.toElement().text().toInt() );
        else if ( name == "RelaxedAps" )
            vcdOptions() ->setRelaxedAps( item.toElement().text().toInt() );
        else if ( name == "UseGaps" )
            vcdOptions() ->setUseGaps( item.toElement().text().toInt() );
        else if ( name == "PbcEnabled" )
            vcdOptions() ->setPbcEnabled( item.toElement().text().toInt() );
        else if ( name == "PbcNumKeys" )
            vcdOptions() ->setPbcNumKeys( item.toElement().text().toInt() );
        else if ( name == "SegmentFolder" )
            vcdOptions() ->setSegmentFolder( item.toElement().text().toInt() );
        else if ( name == "Restriction" )
            vcdOptions() ->setRestriction( item.toElement().text().toInt() );
    }

    // vcd Tracks
    QDomNodeList trackNodes = nodes.item( 2 ).childNodes();

    for ( uint i = 0; i < trackNodes.length(); i++ ) {

        // check if url is available
        QDomElement trackElem = trackNodes.item( i ).toElement();
        QString url = trackElem.attributeNode( "url" ).value();
        if ( !QFile::exists( url ) )
            m_notFoundFiles.append( url );
        else {
            KURL k;
            k.setPath( url );
            if ( K3bVcdTrack* track = createTrack( k ) ) {
                track ->setPlayTime( trackElem.attribute( "playtime", "1" ).toInt() );
                track ->setWaitTime( trackElem.attribute( "waittime", "2" ).toInt() );
                track ->setReactivity( trackElem.attribute( "reactivity", "0" ).toInt() );

                addTrack( track, m_tracks->count() );
            }
        }
    }

    emit newTracks();

    // do not add saved pbcTrack links when one ore more files missing.
    // TODO: add info message to informAboutNotFoundFiles();
    if ( m_notFoundFiles.isEmpty() ) {
        int type;
        int val;
        bool pbctrack;
        for ( uint trackId = 0; trackId < trackNodes.length(); trackId++ ) {
            QDomElement trackElem = trackNodes.item( trackId ).toElement();
            QDomNodeList trackNodes = trackElem.childNodes();
            kdDebug() << "PBC Element Type: " << trackElem.attribute ("type") << endl;
            kdDebug() << "PBC Element PbcTrack: " << trackElem.attribute ("pbctrack") << endl;
            kdDebug() << "PBC Element Value: " << trackElem.attribute ("val") << endl;
            kdDebug() << "------------------------------------" << endl;
            for ( uint i = 0; i < trackNodes.length(); i++ ) {
                QDomElement trackElem = trackNodes.item( i ).toElement();
                if ( trackElem.hasAttribute ("type") ) {
                    type = trackElem.attribute ("type").toInt();
                    if ( trackElem.hasAttribute ("pbctrack") ) {
                        pbctrack = ( trackElem.attribute ("pbctrack") == "yes" );
                        if ( trackElem.hasAttribute ("val") ) {
                            val = trackElem.attribute ("val").toInt();
                            K3bVcdTrack* track = m_tracks->at( trackId );
                            K3bVcdTrack* pbcTrack = m_tracks->at( val );
                            if ( pbctrack ) {
                                pbcTrack->addToRevRefList( track );
                                track->setPbcTrack( type, pbcTrack );
                                track->setUserDefined( type, true );
                            } else {
                                track->setPbcTrack( type );
                                track->setPbcNonTrack( type, val );
                                track->setUserDefined( type, true );
                            }
                        }
                    }
                }
            }
        }
        setPbcTracks();
        setModified( false );
    }

    informAboutNotFoundFiles();

    return true;
}


bool K3bVcdDoc::saveDocumentData( QDomElement* docElem )
{
    QDomDocument doc = docElem->ownerDocument();
    saveGeneralDocumentData( docElem );

    // save Vcd Label
    QDomElement vcdMain = doc.createElement( "vcd" );

    QDomElement vcdElem = doc.createElement( "volumeId" );
    vcdElem.appendChild( doc.createTextNode( vcdOptions() ->volumeId() ) );
    vcdMain.appendChild( vcdElem );

    vcdElem = doc.createElement( "albumId" );
    vcdElem.appendChild( doc.createTextNode( vcdOptions() ->albumId() ) );
    vcdMain.appendChild( vcdElem );

    vcdElem = doc.createElement( "volumeSetId" );
    vcdElem.appendChild( doc.createTextNode( vcdOptions() ->volumeSetId() ) );
    vcdMain.appendChild( vcdElem );

    vcdElem = doc.createElement( "preparer" );
    vcdElem.appendChild( doc.createTextNode( vcdOptions() ->preparer() ) );
    vcdMain.appendChild( vcdElem );

    vcdElem = doc.createElement( "publisher" );
    vcdElem.appendChild( doc.createTextNode( vcdOptions() ->publisher() ) );
    vcdMain.appendChild( vcdElem );

// applicationId()
// systemId()

    vcdElem = doc.createElement( "vcdType" );
    vcdElem.appendChild( doc.createTextNode( QString::number( vcdType() ) ) );
    vcdMain.appendChild( vcdElem );

    vcdElem = doc.createElement( "mpegVersion" );
    vcdElem.appendChild( doc.createTextNode( QString::number( vcdOptions() ->mpegVersion() ) ) );
    vcdMain.appendChild( vcdElem );

    vcdElem = doc.createElement( "PreGapLeadout" );
    vcdElem.appendChild( doc.createTextNode( QString::number( vcdOptions() ->PreGapLeadout() ) ) );
    vcdMain.appendChild( vcdElem );

    vcdElem = doc.createElement( "PreGapTrack" );
    vcdElem.appendChild( doc.createTextNode( QString::number( vcdOptions() ->PreGapTrack() ) ) );
    vcdMain.appendChild( vcdElem );

    vcdElem = doc.createElement( "FrontMarginTrack" );
    vcdElem.appendChild( doc.createTextNode( QString::number( vcdOptions() ->FrontMarginTrack() ) ) );
    vcdMain.appendChild( vcdElem );

    vcdElem = doc.createElement( "RearMarginTrack" );
    vcdElem.appendChild( doc.createTextNode( QString::number( vcdOptions() ->RearMarginTrack() ) ) );
    vcdMain.appendChild( vcdElem );

    vcdElem = doc.createElement( "FrontMarginTrackSVCD" );
    vcdElem.appendChild( doc.createTextNode( QString::number( vcdOptions() ->FrontMarginTrackSVCD() ) ) );
    vcdMain.appendChild( vcdElem );

    vcdElem = doc.createElement( "RearMarginTrackSVCD" );
    vcdElem.appendChild( doc.createTextNode( QString::number( vcdOptions() ->RearMarginTrackSVCD() ) ) );
    vcdMain.appendChild( vcdElem );

    vcdElem = doc.createElement( "volumeCount" );
    vcdElem.appendChild( doc.createTextNode( QString::number( vcdOptions() ->volumeCount() ) ) );
    vcdMain.appendChild( vcdElem );

    vcdElem = doc.createElement( "volumeNumber" );
    vcdElem.appendChild( doc.createTextNode( QString::number( vcdOptions() ->volumeNumber() ) ) );
    vcdMain.appendChild( vcdElem );

    vcdElem = doc.createElement( "AutoDetect" );
    vcdElem.appendChild( doc.createTextNode( QString::number( vcdOptions() ->AutoDetect() ) ) );
    vcdMain.appendChild( vcdElem );

    vcdElem = doc.createElement( "CdiSupport" );
    vcdElem.appendChild( doc.createTextNode( QString::number( vcdOptions() ->CdiSupport() ) ) );
    vcdMain.appendChild( vcdElem );

    vcdElem = doc.createElement( "NonCompliantMode" );
    vcdElem.appendChild( doc.createTextNode( QString::number( vcdOptions() ->NonCompliantMode() ) ) );
    vcdMain.appendChild( vcdElem );

    vcdElem = doc.createElement( "Sector2336" );
    vcdElem.appendChild( doc.createTextNode( QString::number( vcdOptions() ->Sector2336() ) ) );
    vcdMain.appendChild( vcdElem );

    vcdElem = doc.createElement( "UpdateScanOffsets" );
    vcdElem.appendChild( doc.createTextNode( QString::number( vcdOptions() ->UpdateScanOffsets() ) ) );
    vcdMain.appendChild( vcdElem );

    vcdElem = doc.createElement( "RelaxedAps" );
    vcdElem.appendChild( doc.createTextNode( QString::number( vcdOptions() ->RelaxedAps() ) ) );
    vcdMain.appendChild( vcdElem );

    vcdElem = doc.createElement( "UseGaps" );
    vcdElem.appendChild( doc.createTextNode( QString::number( vcdOptions() ->UseGaps() ) ) );
    vcdMain.appendChild( vcdElem );

    vcdElem = doc.createElement( "PbcEnabled" );
    vcdElem.appendChild( doc.createTextNode( QString::number( vcdOptions() ->PbcEnabled() ) ) );
    vcdMain.appendChild( vcdElem );

    vcdElem = doc.createElement( "PbcNumKeys" );
    vcdElem.appendChild( doc.createTextNode( QString::number( vcdOptions() ->PbcNumKeys() ) ) );
    vcdMain.appendChild( vcdElem );

    vcdElem = doc.createElement( "SegmentFolder" );
    vcdElem.appendChild( doc.createTextNode( QString::number( vcdOptions() ->SegmentFolder() ) ) );
    vcdMain.appendChild( vcdElem );

    vcdElem = doc.createElement( "Restriction" );
    vcdElem.appendChild( doc.createTextNode( QString::number( vcdOptions() ->Restriction() ) ) );
    vcdMain.appendChild( vcdElem );

    docElem->appendChild( vcdMain );

    // save the tracks
    // -------------------------------------------------------------
    QDomElement contentsElem = doc.createElement( "contents" );

    QPtrListIterator<K3bVcdTrack> iterTrack( *m_tracks );
    K3bVcdTrack* track;

    while ( ( track = iterTrack.current() ) != 0 ) {
        ++iterTrack;

        QDomElement trackElem = doc.createElement( "track" );
        trackElem.setAttribute( "url", KIO::decodeFileName( track->absPath() ) );
        trackElem.setAttribute( "playtime", track->getPlayTime() );
        trackElem.setAttribute( "waittime", track->getWaitTime() );
        trackElem.setAttribute( "reactivity", track->Reactivity() );
                                
        for ( int i = 0; i < K3bVcdTrack::_maxPbcTracks; i++ ) {
            if ( track->isPbcUserDefined( i ) ) {
                // save pbcTracks
                QDomElement pbcElem = doc.createElement( "pbc" );
                pbcElem.setAttribute( "type", i );
                if ( track->getPbcTrack( i ) ) {
                    pbcElem.setAttribute( "pbctrack", "yes" );
                    pbcElem.setAttribute( "val", track->getPbcTrack( i )->index() );
                }
                else {
                    pbcElem.setAttribute( "pbctrack", "no" );
                    pbcElem.setAttribute( "val", track->getNonPbcTrack( i ) );
                }
                trackElem.appendChild( pbcElem );
            }
        }

        contentsElem.appendChild( trackElem );
    }
    // -------------------------------------------------------------

    docElem->appendChild( contentsElem );

    return true;
}


K3bProjectBurnDialog* K3bVcdDoc::newBurnDialog( QWidget* parent, const char* name )
{
  return new K3bVcdBurnDialog( this, parent, name, true );
}

#include "k3bvcddoc.moc"
