/***************************************************************************
                          profiledlg.cpp  -  description
                             -------------------
    begin                : Sat Nov 20 2004
    copyright            : (C) 2004 by Dominik Seichter
    email                : domseichter@web.de
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   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 "profiledlg.h"
#include "krenameimpl.h"
#include "kmyhistorycombo.h"
#include "pluginloader.h"
#include "kmylistbox.h"

#include <tdeapplication.h>
#include <kcombobox.h>
#include <tdeconfig.h>
#include <kiconloader.h>
#include <kinputdialog.h> 
#include <tdelistbox.h>
#include <tdelocale.h>
#include <tdemessagebox.h>
#include <kpushbutton.h>
#include <kstandarddirs.h>
#include <kurlrequester.h>

#include <tqcheckbox.h>
#include <tqdom.h>
#include <tqfile.h>
#include <tqlayout.h>
#include <tqpainter.h>
#include <tqradiobutton.h>
#include <tqtooltip.h>

#ifdef HAVE_CONFIG_H
    #include <config.h>
#endif

#ifndef VERSION
    #define VERSION "unknown"
#endif

#define PROFILE_WIZARD_INDEX 0
#define PROFILE_TABBED_INDEX 1 

#define PROFILE_WIZARD_NAME i18n("KRename: Wizard default profile")
#define PROFILE_TABBED_NAME i18n("KRename: Tabbed default profile")

class ProfileListBoxText : public TQListBoxText {

public:
    ProfileListBoxText( const TQString & text = TQString() )
	: TQListBoxText( text )
	{
	    m_default = false;
	}

    inline bool isDefault() const {
	return m_default;
    }

    inline void setDefault( const bool b ) {
	m_default = b;
    }

protected:
    void paint( TQPainter* painter )
	{
	    TQFont f = painter->font();
	    f.setBold( m_default );
	    painter->setFont( f );
	    
	    TQListBoxText::paint( painter );
	}
    
private:
    bool m_default;

};

ProfileManager::ProfileManager( KRenameImpl* krename )
    : m_krename( krename )
{

}

const TQString ProfileManager::readProfilePath( const TQString & name )
{
    TQString path;
    TDEConfig* conf = kapp->config();
    
    conf->setGroup( "Profiles" );
    path = conf->readEntry( name, TQString() );
    
    return path;    
}

const TQString ProfileManager::getProfilePath( const TQString & name )
{
    TQStringList list;

    if( name == PROFILE_WIZARD_NAME )
	return locate( "data", "krename/krename_system_default_wizard.xml" );
    else if( name == PROFILE_TABBED_NAME )
        return locate( "data", "krename/krename_system_default_tabbed.xml" );

    TQString path = locateLocal( "data", TQString( "krename/%1.xml" ).arg( name ) );
    
    TDEConfig* conf = kapp->config();
    
    conf->setGroup( "ProfilesHeader" );
    list = conf->readListEntry( "list" );
    if( !list.contains( name ) )
	list.append( name );
    conf->writeEntry( "list", list );
    
    conf->setGroup( "Profiles" );
    conf->writeEntry( name, path );
    conf->sync();
    
    return path;    
}

void ProfileManager::writeXML( const TQString & name )
{
    TQString path = getProfilePath( name );
    TQFile file( path );
    
    if( !file.open( IO_WriteOnly ) )
    {
        tqDebug("Cannot write to: %s", path.latin1() );
        return;
    }
    
    TQDomDocument doc( "KRenameProfile" );
    TQDomElement root = doc.createElement( "krename" );
    doc.appendChild( root );

    TQDomElement v = doc.createElement( "version" );
    v.setAttribute( "version", VERSION );
    root.appendChild( v );
    
    // General settings of Krename
    TQDomElement settings = doc.createElement( "settings" );
    settings.setAttribute( "wizard", m_krename->m_wizard );
    settings.setAttribute( "fileplugins", m_krename->plugin->filePluginsLoaded() );
    root.appendChild( settings );
    
    // Filename settings
    TQDomElement filename = doc.createElement( "filename" );
    filename.setAttribute( "filename", m_krename->filename->text() );
    filename.setAttribute( "extension", m_krename->extemplate->text() );
    filename.setAttribute( "extension_enabled", m_krename->checkExtension->isChecked() );
    filename.setAttribute( "extension_start", m_krename->comboExtension->currentItem() );
    
    TQDomElement numbering = doc.createElement( "numbering" );
    numbering.setAttribute( "start", m_krename->m_index );
    numbering.setAttribute( "step", m_krename->m_step );
    numbering.setAttribute( "skip", listToString( m_krename->skip ) );
    numbering.setAttribute( "reset", m_krename->m_reset );

    TQDomElement replace = doc.createElement( "replace" );
    for( unsigned int i=0;i<m_krename->rep.count();i++)
    {
        TQDomElement r = doc.createElement( "item" );
        r.setAttribute( "find", m_krename->rep[i].find );
        r.setAttribute( "replace", m_krename->rep[i].replace );
        r.setAttribute( "reg", m_krename->rep[i].reg );
        
        replace.appendChild( r );
    }
    
    // destination settings
    TQDomElement dest = doc.createElement( "destination" );
    dest.setAttribute( "mode", m_krename->currentRenameMode() );
    dest.setAttribute( "overwrite", TQString::number( m_krename->checkOverwrite->isChecked() ) );
    dest.setAttribute( "directory", m_krename->dirname->text() );
    dest.setAttribute( "undo", TQString::number( m_krename->checkUndoScript->isChecked() ) );
    dest.setAttribute( "undoscript", m_krename->undorequester->url() );
    
    // file adding settings
    TQDomElement files = doc.createElement( "files" );
    files.setAttribute( "sorting", TQString::number( m_krename->comboSort->currentItem() ) );
    files.setAttribute( "preview", TQString::number( m_krename->checkPreview->isChecked() ) );
    files.setAttribute( "names", TQString::number( m_krename->checkName->isChecked() ) );
    
    filename.appendChild( replace );
    filename.appendChild( numbering );
    root.appendChild( settings );
    root.appendChild( filename );
    root.appendChild( dest );
    root.appendChild( files );
    
    TQCString xml = doc.toCString();
    file.writeBlock( xml, xml.length() );
    file.close();
}

bool ProfileManager::loadXML( const TQString & path )
{
    TQFile file( path );
    
    if( !file.open( IO_ReadOnly ) )
    {
        tqDebug("Cannot read from: %s", path.latin1() );
        return false;
    }

    TQDomDocument doc( "KRenameProfile" );
    if ( !doc.setContent( &file ) ) 
    {
        file.close();
        return false;
    }

    TQDomNode n = doc.documentElement().firstChild();
    while( !n.isNull() ) 
    {
        TQDomElement e = n.toElement(); // try to convert the node to an element.
        if( !e.isNull() )
        {
            if( e.tagName() == "settings" ) 
            {
                bool wiz, plug;
                wiz = (bool)e.attribute( "wizard", 
                            TQString( "%1" ).arg( m_krename->m_wizard ) ).toInt();

                m_krename->setWizardMode( wiz );
//                if( wiz != m_krename->m_wizard )
                {
                    m_krename->m_wizard = wiz;
                    m_krename->changeGUIMode();
                }
                    
                plug = (bool)e.attribute( "fileplugins", 
                             TQString( "%1" ).arg( m_krename->plugin->filePluginsLoaded() ) ).toInt(); 
                if( plug && !m_krename->plugin->filePluginsLoaded() )
                    m_krename->plugin->loadPlugins( true );
            }
            else if( e.tagName() == "filename" )
            {
                m_krename->filename->setText( e.attribute("filename", m_krename->filename->text() ) );
                m_krename->extemplate->setText( e.attribute("extension", m_krename->extemplate->text() ) );
                m_krename->checkExtension->setChecked( 
                           (bool)e.attribute("extension_enabled",
                           TQString("%1").arg(m_krename->checkExtension->isChecked() ) ).toInt() );
                m_krename->comboExtension->setCurrentItem( 
                            e.attribute("extension_start", 
                            TQString::number( m_krename->comboExtension->currentItem() ) ).toInt() );
                            
                TQDomNode n = e.firstChild();
                while( !n.isNull() ) 
                {
                    TQDomElement e = n.toElement(); // try to convert the node to an element.
                    if( !e.isNull() )
                    {
                        if( e.tagName() == "numbering" )
                        {
                            m_krename->m_index = e.attribute( "start", TQString::number( m_krename->m_index ) ).toInt();
                            m_krename->m_step = e.attribute( "step", TQString::number( m_krename->m_step ) ).toInt();
                            m_krename->skip = stringToList( e.attribute("skip", listToString( m_krename->skip ) ) );
			    m_krename->m_reset = (bool)e.attribute( "reset", TQString::number( (int)m_krename->m_reset ) ).toInt();
                        }
                        else if( e.tagName() == "replace" )
                        {
                            m_krename->rep.clear();
                            TQDomNode n = e.firstChild();
                            while( !n.isNull() ) 
                            {
                                TQDomElement e = n.toElement(); // try to convert the node to an element.
                                if( !e.isNull() && e.tagName() == "item" )
                                {
                                    replacestrings r;
                                    r.find = e.attribute( "find", TQString() );
                                    r.replace = e.attribute( "replace", TQString() );
                                    r.reg = (bool)e.attribute( "reg", "0" ).toInt();
                                    m_krename->rep.append( r );
                                }
                                n = n.nextSibling();
                            }
                        }
                    }
                    n = n.nextSibling();
                }
            }
            else if( e.tagName() == "destination" )
            {
                int mode = e.attribute( "mode", TQString::number( m_krename->currentRenameMode() ) ).toInt();
                m_krename->optionRename->setChecked( false );
                m_krename->optionCopy->setChecked( false );
                m_krename->optionMove->setChecked( false );
                m_krename->optionLink->setChecked( false );
                
                switch( mode )
                {
                    default:
                    case RENAME:
                        m_krename->optionRename->setChecked( true ); break;
                    case COPY:
                        m_krename->optionCopy->setChecked( true ); break;
                    case MOVE:
                        m_krename->optionMove->setChecked( true ); break;
                    case LINK:
                        m_krename->optionLink->setChecked( true ); break;
                }
                    
                m_krename->checkOverwrite->setChecked( e.attribute( "overwrite", 
                           TQString::number( m_krename->checkOverwrite->isChecked() ) ).toInt() );
                m_krename->dirname->setText( e.attribute( "directory", m_krename->dirname->text() ) );
                m_krename->checkUndoScript->setChecked( e.attribute( "undo",
                            TQString::number( m_krename->checkUndoScript->isChecked() ) ).toInt() );
                m_krename->undorequester->setURL( e.attribute( "undoscript", m_krename->undorequester->url() ) );
            }
            else if( e.tagName() == "files" )
            {
                m_krename->comboSort->setCurrentItem( e.attribute( "sorting", 
                            TQString::number( m_krename->comboSort->currentItem() ) ).toInt() );
                m_krename->checkPreview->setChecked( e.attribute( "preview", 
                            TQString::number( m_krename->checkPreview->isChecked() ) ).toInt() );
                m_krename->checkName->setChecked( e.attribute( "names",
                            TQString::number( m_krename->checkName->isChecked() ) ).toInt() );
            }
        }
        n = n.nextSibling();
    }
    
    if( m_krename->m_wizard )
        m_krename->parseWizardMode();
        
    file.close();
    return true;
}

const TQString ProfileManager::listToString( TQValueList<int> & list )
{
    TQString data;
    for( unsigned int i = 0; i < list.count(); i++ )
        data += TQString( "%1;" ).arg( list[i] );
        
    return data;
}

const TQValueList<int> ProfileManager::stringToList( const TQString & data )
{
    TQValueList<int> list;
    int c = data.contains( ";" );
    if( c > 0 )
    {
        for( int i = 0;i<c;i++)
            list.append( data.section( ';', i, i ).toInt() );
    }
    
    return list;
}

bool ProfileManager::hasDefaultProfile()
{
    TDEConfig* conf = kapp->config();
    conf->setGroup( "ProfilesHeader" );

    TQString def = conf->readEntry( "defprofile", TQString() );

    return (!def.isEmpty());
}

void ProfileManager::loadDefaultProfile( KRenameImpl* krename )
{
    TDEConfig* conf = kapp->config();
    conf->setGroup( "ProfilesHeader" );

    TQString def = conf->readEntry( "defprofile", TQString() );

    if( !def.isEmpty() )
	ProfileManager::loadProfile( def, krename );
}

void ProfileManager::loadProfile( const TQString & name, KRenameImpl* krename )
{
    ProfileManager manager( krename );
    manager.loadXML( manager.getProfilePath( name ) );
}

///////////////////////////////////////////////////////////////////////////////

ProfileDlg::ProfileDlg(KRenameImpl* krename, TQWidget *parent, const char *name)
    : KDialogBase( KDialogBase::Plain, i18n("Profiles"),
      KDialogBase::Close, KDialogBase::Close, parent, name, true, true ), ProfileManager( krename )
{
    int i;

    TQHBoxLayout* layout = new TQHBoxLayout( plainPage(), 6, 6 );
    TQVBoxLayout* button = new TQVBoxLayout( 0, 6, 6 );
    
    profiles = new TDEListBox( plainPage() );
    profiles->insertItem( new ProfileListBoxText( PROFILE_WIZARD_NAME ), PROFILE_WIZARD_INDEX );
    profiles->insertItem( new ProfileListBoxText( PROFILE_TABBED_NAME ), PROFILE_TABBED_INDEX );
    
    createProfile = new KPushButton( i18n("&Save As Profile..."), plainPage() );
    loadProfile = new KPushButton( i18n("&Load Profile"), plainPage() );
    deleteProfile = new KPushButton( i18n("&Delete Profile"), plainPage() );
    checkDefault = new TQCheckBox( i18n("&Use as default profile on startup"), plainPage() );

    createProfile->setIconSet( SmallIconSet( "document-save-as") );
    loadProfile->setIconSet( SmallIconSet( "document-open" ) );
    deleteProfile->setIconSet( SmallIconSet( "edittrash" ) );
    
    TQSpacerItem* spacer = new TQSpacerItem( 20, 20, TQSizePolicy::Expanding, TQSizePolicy::Expanding );
    button->addWidget( createProfile );
    button->addWidget( loadProfile );
    button->addWidget( deleteProfile );
    button->addItem( spacer );
    button->addWidget( checkDefault );

    layout->addWidget( profiles );
    layout->addLayout( button );
    layout->setStretchFactor( profiles, 2 );
    
    TQToolTip::add( createProfile, i18n("<qt>Save KRename's current settings as a new profile. " 
                                       "The settings are saved and can be restored with Load Profile later.</qt>" ) );
    TQToolTip::add( loadProfile, i18n("<qt>Load all settings stored in this profile.</qt>") );
    
    enableControls();
    
    connect( createProfile, TQ_SIGNAL( clicked() ), this, TQ_SLOT( slotCreateProfile() ) );
    connect( loadProfile, TQ_SIGNAL( clicked() ), this, TQ_SLOT( slotLoadProfile() ) );
    connect( deleteProfile, TQ_SIGNAL( clicked() ), this, TQ_SLOT( slotDeleteProfile() ) );
    connect( profiles, TQ_SIGNAL( selectionChanged () ), this, TQ_SLOT( enableControls() ) );
    connect( checkDefault, TQ_SIGNAL( clicked() ), this, TQ_SLOT( slotSetDefault() ) );
    connect( this, TQ_SIGNAL( hidden() ), this, TQ_SLOT( slotHidden() ) );

    TDEConfig* conf = kapp->config();
    conf->setGroup( "ProfilesHeader" );
    ProfileListBoxText* item;

    TQStringList list = conf->readListEntry( "list" );    
    TQString def = conf->readEntry( "defprofile", TQString() );
    for( i=0;i<(int)list.count();i++ )
	profiles->insertItem( new ProfileListBoxText( list[i] ) );

    for( i=0;i<(int)profiles->count();i++ )
    {
	item = static_cast<ProfileListBoxText*>(profiles->item(i));
	if( item->text() == def  )
	{
	    item->setDefault( true);
	    break;
	}
    }

    profiles->repaintContents();
}


ProfileDlg::~ProfileDlg()
{
}


void ProfileDlg::enableControls()
{
    ProfileListBoxText* item;

    loadProfile->setEnabled( profiles->selectedItem() );
    // Do not allow to delete the two default profiles
    deleteProfile->setEnabled( profiles->selectedItem() && 
			       profiles->currentItem() != PROFILE_TABBED_INDEX && profiles->currentItem() != PROFILE_WIZARD_INDEX );
    checkDefault->setEnabled( profiles->selectedItem() );
    
    item = static_cast<ProfileListBoxText*>(profiles->selectedItem());
    checkDefault->setChecked( item && item->isDefault() );
}

void ProfileDlg::slotSetDefault()
{
    int i;
    ProfileListBoxText* item;

    for( i=0;i<(int)profiles->count();i++ )
    {
	item = static_cast<ProfileListBoxText*>(profiles->item( i ));
	item->setDefault( false );
    }

    item = static_cast<ProfileListBoxText*>(profiles->selectedItem());
    if( item )
	item->setDefault( checkDefault->isChecked() );

    profiles->repaintContents();
}

void ProfileDlg::slotLoadProfile()
{
    TQString profile = profiles->currentText();
    TQString msg = i18n("Do you really want to load the profile and overwrite the current settings: %1").arg( profile );

    TQString path = getProfilePath( profile );

    if( path.isEmpty() )
    {
        KMessageBox::error( this, i18n("The profile \"%1\" could not be found.").arg( profile ) );
        return;
    }
    
    if( KMessageBox::questionYesNo( this, msg ) == KMessageBox::Yes )
    {
        if( loadXML( path ) )
	    this->close();

        enableControls();
        
        m_krename->enableControls();
        m_krename->updatePre();
    }
}

void ProfileDlg::slotCreateProfile()
{
    bool ok = false;
    const char* mask = "xXXXXXXXXXXXXXXXXXXX"; // allows for 20 characters
    TQString name = KInputDialog::getText( i18n("Profile Name"), i18n("Please enter a name for the new profile:"), 
                   "KRename", &ok, this, 0, 0, mask );
                   
    if( !ok )
        return;
        
    if( profiles->findItem( name, TQt::ExactMatch ) )
    {
        KMessageBox::error( this, i18n("This profile does already exist. Please choose another name.") );
        slotCreateProfile();
        return;
    }
    
    profiles->insertItem( new ProfileListBoxText( name ) );
    writeXML( name );
    
    enableControls();
}

void ProfileDlg::slotDeleteProfile()
{
    if( profiles->currentItem() == PROFILE_WIZARD_INDEX || profiles->currentItem() == PROFILE_TABBED_INDEX )
    {
        KMessageBox::error( this, i18n("You cannot delete default profiles!") );
        return;
    }

    TQString profile = profiles->currentText();
    TQString msg = i18n("Do you really want to delete the profile: %1").arg( profile );

    if( KMessageBox::questionYesNo( this, msg ) == KMessageBox::Yes )
    {
        TQString path = readProfilePath( profile );
        TQFile::remove( path );
        
        TQListBoxItem* item = profiles->findItem( profile, TQt::ExactMatch );
        if( item )
            delete item;
        
        TDEConfig* conf = kapp->config();
        
        conf->setGroup( "ProfilesHeader" );
        TQStringList list = conf->readListEntry( "list" );
        list.remove( profile );
        conf->writeEntry( "list", list );
        conf->sync();
            
        enableControls();
    }
}

void ProfileDlg::slotHidden()
{
    int i;
    TDEConfig* conf = kapp->config();
    TQString def = TQString();
    ProfileListBoxText* item;

    for( i=0;i<(int)profiles->count();i++ )
    {
	item = static_cast<ProfileListBoxText*>(profiles->item( i ));
	if( item->isDefault() )
	{
	    def = profiles->text( i );
	    break;
	}
    }

    conf->setGroup( "ProfilesHeader" );
    conf->writeEntry( "defprofile", def );
    conf->sync();
}

#include "profiledlg.moc"
