#include "configbackendspage.h"
#include "convertpluginloader.h"
#include "replaygainpluginloader.h"
#include "ripperpluginloader.h"
#include "config.h"

#include <tqlayout.h>
#include <tqlabel.h>
#include <tqgroupbox.h>
#include <tqtooltip.h>
#include <tqvbox.h>
#include <tqslider.h>
#include <tqcheckbox.h>

#include <kiconloader.h>
#include <klocale.h>
#include <kcombobox.h>
#include <kscrollview.h>
#include <kstandarddirs.h>


ConfigBackendsPage::ConfigBackendsPage( Config* _config, TQMap<TQString, TQString>* _binaries, TQWidget* parent, const char *name )
    : ConfigPageBase( parent, name )
{
    config = _config;
    binaries = _binaries;

    grid = new TQGridLayout( parent );
    scrollView = new KScrollView( parent, "scrollView" );
    scrollView->setResizePolicy( TQScrollView::AutoOneFit );
    grid->addWidget( scrollView, 0, 0 );
    box = new TQVBox( scrollView->viewport() );
    box->setMargin( 11 );
    box->setSpacing( 6 );
    scrollView->addChild( box );

    TQHBox* legendBox = new TQHBox( box );
    legendBox->setMargin( 0 );
    legendBox->setSpacing( 6 );
    KStandardDirs* stdDirs = new KStandardDirs();
    TQLabel* lLegendLabel = new TQLabel( i18n("Legend")+":", legendBox, "lLegendLabel" );
    TQLabel* lLegendGreen = new TQLabel( "", legendBox, "lLegendGreen" );
    lLegendGreen->setPixmap( TQPixmap(stdDirs->findResource("data","soundkonverter/pics/ledgreen_legend.png")) );
    TQLabel* lLegendFull = new TQLabel( i18n("Full support"), legendBox, "lLegendFull" );
    TQLabel* lLegendYellow = new TQLabel("",legendBox,"lLegendYellow");
    lLegendYellow->setPixmap( TQPixmap(stdDirs->findResource("data","soundkonverter/pics/ledyellow_legend.png")) );
    TQLabel* lLegendMost = new TQLabel( i18n("Most supported"), legendBox, "lLegendMost" );
    TQLabel* lLegendRed = new TQLabel( "", legendBox, "lLegendRed" );
    lLegendRed->setPixmap( TQPixmap(stdDirs->findResource("data","soundkonverter/pics/ledred_legend.png")) );
    TQLabel* lLegendBasic = new TQLabel( i18n("Basic support"), legendBox, "lLegendBasic" );
    legendBox->setStretchFactor( lLegendLabel, 1 );

    TQGroupBox* ripperGroup = new TQGroupBox( 1, Qt::Vertical, box, "ripperGroup" );
    ripperGroup->tqlayout()->setSpacing( 6 );
    ripperGroup->tqlayout()->setMargin( 6 );
    TQLabel* lRipper = new TQLabel( i18n("CD Ripper")+":", ripperGroup, "lRipper" );
    cRipper = new KComboBox( ripperGroup, "cRipper" );
    connect( cRipper, TQT_SIGNAL(activated(int)),
               this, TQT_SLOT(cfgChanged())
             );

    delete stdDirs;

    rebuild();
}

ConfigBackendsPage::~ConfigBackendsPage()
{}

void ConfigBackendsPage::resetDefaults()
{
    int i;
    int item;
    int rank;

    i = 1;
    rank = 60;
    item = 0;
    TQValueList<RipperPlugin*> rippers = config->allRippers();
    for( TQValueList<RipperPlugin*>::Iterator it = rippers.begin(); it != rippers.end(); ++it )
    {
        if( (*it)->rip.rank > rank ) {
            rank = (*it)->rip.rank;
            item = i;
        }
        i++;
    }
    cRipper->setCurrentItem( item );

    for( TQValueList<FormatOptions>::Iterator a = formatOptions.begin(); a != formatOptions.end(); ++a )
    {
        FormatItem* formatItem = config->getFormatItem( (*a).format );
        if( formatItem == 0 ) continue;

        i = item = rank = 0;
        for( TQValueList<ConvertPlugin*>::Iterator b = formatItem->encoders.begin(); b != formatItem->encoders.end(); ++b ) {
            if( (*b)->enc.rank > rank ) {
                rank = (*b)->enc.rank;
                item = i;
            }
            i++;
        }
        (*a).cEncoder->setCurrentItem( item );

        i = item = rank = 0;
        for( TQValueList<ConvertPlugin*>::Iterator b = formatItem->decoders.begin(); b != formatItem->decoders.end(); ++b ) {
            if( (*b)->dec.rank > rank ) {
                rank = (*b)->dec.rank;
                item = i;
            }
            i++;
        }
        (*a).cDecoder->setCurrentItem( item );

        i = item = rank = 0;
        for( TQValueList<ReplayGainPlugin*>::Iterator b = formatItem->replaygains.begin(); b != formatItem->replaygains.end(); ++b ) {
            if( (*b)->replaygain.rank > rank ) {
                rank = (*b)->replaygain.rank;
                item = i;
            }
            i++;
        }
        (*a).cReplayGain->setCurrentItem( item );
    }

    encoderChanged();

    for( TQValueList<FormatOptions>::Iterator a = formatOptions.begin(); a != formatOptions.end(); ++a )
    {
        FormatItem* formatItem = config->getFormatItem( (*a).format );
        if( formatItem == 0 ) continue;

        TQString encoder = (*a).cEncoder->currentText();

        (*a).cInternalReplayGain->setChecked( false );

        for( TQValueList<ConvertPlugin*>::Iterator b = formatItem->encoders.begin(); b != formatItem->encoders.end(); ++b ) {
            if( (*b)->enc.bin == encoder && (*b)->enc.strength.enabled ) {
                if( (*b)->enc.strength.range_max >= (*b)->enc.strength.range_min )
                    (*a).sStrength->setValue( (*b)->enc.strength.default_value / (*b)->enc.strength.step );
                else
                    (*a).sStrength->setValue( ( (*b)->enc.strength.range_min - (*b)->enc.strength.default_value ) / (*b)->enc.strength.step );
            }
            if( (*b)->enc.bin == encoder && (*b)->enc.replaygain.enabled ) {
                if( formatItem->replaygain != 0 && formatItem->replaygain->replaygain.rank > (*b)->enc.replaygain.rank ) {
                    (*a).cInternalReplayGain->setChecked( false );
                }
                else {
                    (*a).cInternalReplayGain->setChecked( true );
                }
            }
        }
    }

    strengthChanged();
    cfgChanged();
}

void ConfigBackendsPage::saveSettings()
{
    config->setCurrentRipper( 0 );
    TQValueList<RipperPlugin*> rippers = config->allRippers();
    for( TQValueList<RipperPlugin*>::Iterator it = rippers.begin(); it != rippers.end(); ++it )
    {
        if( (*it)->rip.bin == cRipper->currentText() ) {
            config->setCurrentRipper( *it );
        }
    }

    for( TQValueList<FormatOptions>::Iterator a = formatOptions.begin(); a != formatOptions.end(); ++a )
    {
        FormatItem* formatItem = config->getFormatItem( (*a).format );
        if( formatItem == 0 ) continue;

        for( TQValueList<ConvertPlugin*>::Iterator b = formatItem->encoders.begin(); b != formatItem->encoders.end(); ++b ) {
            if( (*b)->enc.bin == (*a).cEncoder->currentText() ) {
                formatItem->encoder = (*b);
                if( (*b)->enc.strength.enabled ) {
                    formatItem->compressionLevel = (*a).sStrength->value();
                }
                if( (*b)->enc.replaygain.enabled ) {
                    formatItem->internalReplayGain = (*a).cInternalReplayGain->isChecked();
                }
            }
        }

        for( TQValueList<ConvertPlugin*>::Iterator b = formatItem->decoders.begin(); b != formatItem->decoders.end(); ++b ) {
            if( (*b)->dec.bin == (*a).cDecoder->currentText() ) {
                formatItem->decoder = (*b);
            }
        }

        for( TQValueList<ReplayGainPlugin*>::Iterator b = formatItem->replaygains.begin(); b != formatItem->replaygains.end(); ++b ) {
            if( (*b)->replaygain.bin == (*a).cReplayGain->currentText() ) {
                formatItem->replaygain = (*b);
            }
        }
    }
}

void ConfigBackendsPage::rebuild()
{
    for( TQValueList<FormatOptions>::Iterator it = formatOptions.begin(); it != formatOptions.end(); ++it )
    {
        delete (*it).lEncoder;
        disconnect( (*it).cEncoder, TQT_SIGNAL(activated(int)), 0, 0 );
        delete (*it).cEncoder;
        delete (*it).lStrength;
        disconnect( (*it).sStrength,TQT_SIGNAL(valueChanged(int)), 0, 0 );
        delete (*it).sStrength;
        delete (*it).lStrengthDisplay;
        delete (*it).lDecoder;
        disconnect( (*it).cDecoder, TQT_SIGNAL(activated(int)), 0, 0 );
        delete (*it).cDecoder;
        delete (*it).lReplayGain;
        disconnect( (*it).cReplayGain, TQT_SIGNAL(activated(int)), 0, 0 );
        delete (*it).cReplayGain;
        disconnect( (*it).cInternalReplayGain, TQT_SIGNAL(toggled(bool)), 0, 0 );
        delete (*it).cInternalReplayGain;
        delete (*it).grid;
        delete (*it).group;
    }

    formatOptions.clear();

    // TODO show all extensions

    TQStringList formats = config->allFormats();

    for( TQStringList::Iterator it = formats.begin(); it != formats.end(); ++it )
    {
        FormatOptions options;
        options.format = *it;

        FormatItem *formatItem = config->getFormatItem( options.format );
        TQString title;
        if( formatItem ) {
            for( TQStringList::Iterator at = formatItem->extensions.begin(); at != formatItem->extensions.end(); ++at ) {
                if( !title.contains((*at).lower()) ) title += (*at).lower() + ", ";
            }
            title = title.left( title.length() - 2 );
/*            title += " [";
            for( TQStringList::Iterator bt = formatItem->mime_types.begin(); bt != formatItem->mime_types.end(); ++bt ) {
                if( !title.contains((*bt).lower()) ) title += (*bt).lower() + ", ";
            }
            title = title.left( title.length() - 2 ) + "]";*/
        }
        else {
            title = options.format;
        }

        options.group = new TQGroupBox( title, box, options.format );
        options.group->setColumnLayout( 0, Qt::Vertical );
        options.group->tqlayout()->setSpacing( 6 );
        options.group->tqlayout()->setMargin( 6 );
        options.group->show();
        options.grid = new TQGridLayout( options.group->tqlayout() );

        options.lEncoder = new TQLabel( i18n("Encoder")+":", options.group, options.format );
        options.lEncoder->show();
        options.grid->addWidget( options.lEncoder, 0, 0 );
        options.cEncoder = new KComboBox( options.group, options.format );
        options.cEncoder->show();
        connect( options.cEncoder, TQT_SIGNAL(activated(int)),
                   this, TQT_SLOT(cfgChanged())
                 );
        connect( options.cEncoder, TQT_SIGNAL(activated(int)),
                   this, TQT_SLOT(encoderChanged())
                 );
        options.grid->addWidget( options.cEncoder, 0, 1 );

        options.lStrength = new TQLabel( i18n("Strength")+":", options.group, options.format );
        options.lStrength->setAlignment( TQt::AlignRight | TQt::AlignVCenter );
        options.lStrength->show();
        options.grid->addWidget( options.lStrength, 0, 2 );
        options.sStrength = new TQSlider( Qt::Horizontal, options.group, options.format );
        options.sStrength->setTickmarks( TQSlider::Below );
        options.sStrength->show();
        TQToolTip::add( options.sStrength, i18n("Set the compression strength:\n\nLeft = fast conversion\nRight = good resultant file") );
        options.grid->addWidget( options.sStrength, 0, 3 );
        connect( options.sStrength, TQT_SIGNAL(valueChanged(int)),
                   this, TQT_SLOT(cfgChanged())
                 );
        connect( options.sStrength, TQT_SIGNAL(valueChanged(int)),
                   this, TQT_SLOT(strengthChanged())
                 );

        options.lDecoder = new TQLabel( i18n("Decoder")+":", options.group, options.format );
        options.lDecoder->show();
        options.grid->addWidget( options.lDecoder, 1, 0 );
        options.cDecoder = new KComboBox( options.group, options.format );
        options.cDecoder->show();
        options.grid->addWidget( options.cDecoder, 1, 1 );
        connect( options.cDecoder, TQT_SIGNAL(activated(int)),
                   this, TQT_SLOT(cfgChanged())
                 );
        options.lStrengthDisplay = new TQLabel( "", options.group, options.format );
        options.lStrengthDisplay->setAlignment( TQt::AlignRight | TQt::AlignVCenter );
        options.lStrengthDisplay->setEnabled( false );
        options.grid->addWidget( options.lStrengthDisplay, 1, 3 );

        options.lReplayGain = new TQLabel( i18n("Replay Gain")+":", options.group, options.format );
        options.lReplayGain->show();
        options.grid->addWidget( options.lReplayGain, 2, 0 );
        options.cReplayGain = new KComboBox( options.group, options.format );
        options.cReplayGain->show();
        options.grid->addWidget( options.cReplayGain, 2, 1 );
        connect( options.cReplayGain, TQT_SIGNAL(activated(int)),
                   this, TQT_SLOT(cfgChanged())
                 );
        options.cInternalReplayGain = new TQCheckBox( i18n("Use internal Replay Gain"), options.group, options.format );
        TQToolTip::add( options.cInternalReplayGain, i18n("Use the internal Replay Gain calculator of the encoder") );
        options.grid->addWidget( options.cInternalReplayGain, 2, 3 );
        connect( options.cInternalReplayGain, TQT_SIGNAL(toggled(bool)),
                   this, TQT_SLOT(cfgChanged())
                 );

        options.grid->setColStretch( 0, 0 );
        options.grid->setColStretch( 1, 1 );
        options.grid->setColStretch( 2, 1 );
        options.grid->setColStretch( 3, 1 );

        formatOptions.append( options );
    }

    refill();
}

void ConfigBackendsPage::refill()
{
    KStandardDirs* stdDirs = new KStandardDirs();
    int i, item;

    cRipper->clear();
    i = item = 0;
    cRipper->insertItem( TQPixmap(stdDirs->findResource("data","soundkonverter/pics/ledyellow.png")), i18n("KDE audio CD protocol") );
    i++;
    TQValueList<RipperPlugin*> rippers = config->allRippers();
    for( TQValueList<RipperPlugin*>::Iterator it = rippers.begin(); it != rippers.end(); ++it )
    {
        if( (*binaries)[(*it)->rip.bin] == "" ) continue;

        if( (*it)->rip.rank >= 70 ) cRipper->insertItem( TQPixmap(stdDirs->findResource("data","soundkonverter/pics/ledgreen.png")), (*it)->rip.bin );
        else if( (*it)->rip.rank >= 40 ) cRipper->insertItem( TQPixmap(stdDirs->findResource("data","soundkonverter/pics/ledyellow.png")), (*it)->rip.bin );
        else cRipper->insertItem( TQPixmap(stdDirs->findResource("data","soundkonverter/pics/ledred.png")), (*it)->rip.bin );
        if( (*it) == config->getCurrentRipper() ) item = i;
        i++;
    }
    cRipper->setCurrentItem( item );

    for( TQValueList<FormatOptions>::Iterator a = formatOptions.begin(); a != formatOptions.end(); ++a )
    {
        FormatItem* formatItem = config->getFormatItem( (*a).format );
        (*a).cEncoder->clear();
        (*a).cDecoder->clear();
        (*a).cReplayGain->clear();
        if( formatItem == 0 ) continue;

        i = item = 0;
        for( TQValueList<ConvertPlugin*>::Iterator b = formatItem->encoders.begin(); b != formatItem->encoders.end(); ++b ) {
            if( (*binaries)[(*b)->enc.bin] == "" ) continue;

            if( (*b)->enc.rank >= 70 ) (*a).cEncoder->insertItem( TQPixmap(stdDirs->findResource("data","soundkonverter/pics/ledgreen.png")), (*b)->enc.bin );
            else if( (*b)->enc.rank >= 40 ) (*a).cEncoder->insertItem( TQPixmap(stdDirs->findResource("data","soundkonverter/pics/ledyellow.png")), (*b)->enc.bin );
            else (*a).cEncoder->insertItem( TQPixmap(stdDirs->findResource("data","soundkonverter/pics/ledred.png")), (*b)->enc.bin );
            if( (*b) == formatItem->encoder ) item = i;
            i++;
        }
        (*a).cEncoder->setCurrentItem( item );

        i = item = 0;
        for( TQValueList<ConvertPlugin*>::Iterator b = formatItem->decoders.begin(); b != formatItem->decoders.end(); ++b ) {
            if( (*binaries)[(*b)->dec.bin] == "" ) continue;

            if( (*b)->dec.rank >= 70 ) (*a).cDecoder->insertItem( TQPixmap(stdDirs->findResource("data","soundkonverter/pics/ledgreen.png")), (*b)->dec.bin );
            else if( (*b)->dec.rank >= 40 ) (*a).cDecoder->insertItem( TQPixmap(stdDirs->findResource("data","soundkonverter/pics/ledyellow.png")), (*b)->dec.bin );
            else (*a).cDecoder->insertItem( TQPixmap(stdDirs->findResource("data","soundkonverter/pics/ledred.png")), (*b)->dec.bin );
            if( (*b) == formatItem->decoder ) item = i;
            i++;
        }
        (*a).cDecoder->setCurrentItem( item );

        i = item = 0;
        for( TQValueList<ReplayGainPlugin*>::Iterator b = formatItem->replaygains.begin(); b != formatItem->replaygains.end(); ++b ) {
            if( (*binaries)[(*b)->replaygain.bin] == "" ) continue;

            if( (*b)->replaygain.rank >= 70 ) (*a).cReplayGain->insertItem( TQPixmap(stdDirs->findResource("data","soundkonverter/pics/ledgreen.png")), (*b)->replaygain.bin );
            else if( (*b)->replaygain.rank >= 40 ) (*a).cReplayGain->insertItem( TQPixmap(stdDirs->findResource("data","soundkonverter/pics/ledyellow.png")), (*b)->replaygain.bin );
            else (*a).cReplayGain->insertItem( TQPixmap(stdDirs->findResource("data","soundkonverter/pics/ledred.png")), (*b)->replaygain.bin );
            if( (*b) == formatItem->replaygain ) item = i;
            i++;
        }
        (*a).cReplayGain->setCurrentItem( item );
    }

    delete stdDirs;

    encoderChanged();
}

void ConfigBackendsPage::encoderChanged()
{
    bool recalc;

    for( TQValueList<FormatOptions>::Iterator a = formatOptions.begin(); a != formatOptions.end(); ++a )
    {
        FormatItem* formatItem = config->getFormatItem( (*a).format );
        (*a).lStrength->hide();
        (*a).sStrength->hide();
        (*a).lStrengthDisplay->hide();
        (*a).cInternalReplayGain->hide();
        if( formatItem == 0 ) continue;

        TQString encoder = (*a).cEncoder->currentText();

        for( TQValueList<ConvertPlugin*>::Iterator b = formatItem->encoders.begin(); b != formatItem->encoders.end(); ++b ) {
            if( TQT_BASE_OBJECT_NAME::sender() && (*a).format == TQT_TQOBJECT(const_cast<TQT_BASE_OBJECT_NAME*>((TQT_BASE_OBJECT_NAME::sender())))->name() ) recalc = true;
            else if( !TQT_BASE_OBJECT_NAME::sender() ) recalc = true;
            else recalc = false;
            if( (*b)->enc.bin == encoder && (*b)->enc.strength.enabled ) {
                (*a).lStrength->show();
                if( (*b)->enc.strength.range_max >= (*b)->enc.strength.range_min ) {
                    (*a).sStrength->setMinValue( (int)((*b)->enc.strength.range_min/(*b)->enc.strength.step) );
                    (*a).sStrength->setMaxValue( (int)((*b)->enc.strength.range_max/(*b)->enc.strength.step) );
                }
                else {
                    (*a).sStrength->setMinValue( (int)((*b)->enc.strength.range_max/(*b)->enc.strength.step) );
                    (*a).sStrength->setMaxValue( (int)((*b)->enc.strength.range_min/(*b)->enc.strength.step) );
                }
                (*a).sStrength->setPageStep( 1 );
                if( TQT_BASE_OBJECT_NAME::sender() && (*a).format == TQT_TQOBJECT(const_cast<TQT_BASE_OBJECT_NAME*>(TQT_BASE_OBJECT_NAME::sender()))->name() ) {
                    if( (*b)->enc.strength.range_max >= (*b)->enc.strength.range_min )
                        (*a).sStrength->setValue( (*b)->enc.strength.default_value / (*b)->enc.strength.step );
                    else
                        (*a).sStrength->setValue( ( (*b)->enc.strength.range_min - (*b)->enc.strength.default_value ) / (*b)->enc.strength.step );
                }
                else if( !TQT_BASE_OBJECT_NAME::sender() ) {
                    (*a).sStrength->setValue( formatItem->compressionLevel );
                }
                (*a).sStrength->show();
                (*a).lStrengthDisplay->show();
            }
            if( (*b)->enc.bin == encoder && (*b)->enc.replaygain.enabled ) {
                (*a).cInternalReplayGain->show();
                if( recalc ) (*a).cInternalReplayGain->setChecked( formatItem->internalReplayGain );
            }
        }
    }

    strengthChanged();
}

void ConfigBackendsPage::strengthChanged()
{
    for( TQValueList<FormatOptions>::Iterator a = formatOptions.begin(); a != formatOptions.end(); ++a )
    {
        FormatItem* formatItem = config->getFormatItem( (*a).format );
        if( formatItem == 0 ) continue;

        TQString encoder = (*a).cEncoder->currentText();

        for( TQValueList<ConvertPlugin*>::Iterator b = formatItem->encoders.begin(); b != formatItem->encoders.end(); ++b ) {
            if( (*b)->enc.bin == encoder && (*b)->enc.strength.enabled ) {
                TQString strength = (*b)->enc.strength.param;
                int compressionLevel = (*a).sStrength->value();
                if( (*b)->enc.strength.profiles.empty() ) {
                    if( (*b)->enc.strength.step < 1 ) {
                        if( (*b)->enc.strength.range_max >= (*b)->enc.strength.range_min )
                            strength.replace( "%c", TQString::number( compressionLevel * (*b)->enc.strength.step ) );
                        else
                            strength.replace( "%c", TQString::number( (*b)->enc.strength.range_min - compressionLevel * (*b)->enc.strength.step ) );
                    }
                    else {
                        if( (*b)->enc.strength.range_max >= (*b)->enc.strength.range_min )
                            strength.replace( "%c", TQString::number( (int)(compressionLevel * (*b)->enc.strength.step) ) );
                        else
                            strength.replace( "%c", TQString::number( (int)((*b)->enc.strength.range_min - compressionLevel * (*b)->enc.strength.step) ) );
                    }
                    if( (*b)->enc.strength.separator != '.' ) strength.replace( TQChar('.'), (*b)->enc.strength.separator );
                }
                else {
                    TQStringList::Iterator it = (*b)->enc.strength.profiles.at( (int)compressionLevel );
                    strength.replace( "%c", *it );
                }
                (*a).lStrengthDisplay->setText( "( \"" + strength + "\" )" );
            }
        }
    }
}