/*
  Copyright (c) 2000 Caldera Systems

  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 "wizard.h"
#include "wizard.moc"
#include "quickhelp.h"
#include "kxpage.h"

#include <qlayout.h>
#include <qframe.h>
#include <qpushbutton.h>
#include <qpixmap.h>
#include <qlabel.h>
#include <qfont.h>
#include <qvariant.h>

#include <klocale.h>
#include <kiconloader.h>
#include <kdebug.h>
#include <kdialog.h>
#include <kaccel.h>

#include <assert.h>

Wizard::Wizard( QWidget *parent, const char *name )
    : QWidget( parent, name )
{
    QVBoxLayout *m_topLayout = new QVBoxLayout( this, KDialog::marginHint(), KDialog::spacingHint());
    QHBoxLayout *m_headerLayout = new QHBoxLayout( m_topLayout );

    m_headerIcon = new QLabel( this );
    m_headerIcon->setPixmap( KGlobal::iconLoader()->loadIcon( "unknown", KIcon::Desktop ) );
    m_headerIcon->setFixedSize( 35, 35 ); // ### hack
    m_headerLayout->addWidget( m_headerIcon );

    m_headerText = new QLabel( "header", this );
    QFont f = m_headerText->font();
    f.setBold( true );
    m_headerText->setFont( f );
    m_headerText->setFixedHeight( 35 ); // ### hack
    m_headerLayout->addWidget( m_headerText );

    m_headerLayout->addStretch();

    QFrame *hline = new QFrame( this );
    hline->setFrameStyle( QFrame::HLine | QFrame::Sunken );
    m_topLayout->addWidget( hline );

    QHBoxLayout *m_middleLayout = new QHBoxLayout( m_topLayout );

    m_stack = new QWidgetStack( this );

    m_middleLayout->addWidget( m_stack, 30 );

    m_quickHelp = new QuickHelp( this );
    m_quickHelp->setSizePolicy( QSizePolicy( QSizePolicy::Preferred, QSizePolicy::Preferred ) );


    m_middleLayout->addWidget( m_quickHelp, 10 );

    hline = new QFrame( this );
    hline->setFrameStyle( QFrame::HLine | QFrame::Sunken );
    m_topLayout->addWidget( hline );

    QHBoxLayout *m_buttonLayout = new QHBoxLayout( m_topLayout );

    m_cancel = new QPushButton( i18n( "&Cancel" ), this );
    m_buttonLayout->addWidget( m_cancel );

    m_buttonLayout->addStretch();

    m_status = new QLabel( this );
    m_buttonLayout->addWidget( m_status );

    m_buttonLayout->addStretch();

    m_back = new QPushButton( QString::fromLatin1( "< " ) + i18n( "&Back" ), this );
    m_buttonLayout->addWidget( m_back );

    m_forward = new QPushButton( i18n( "&Forward" ) + QString::fromLatin1( " >" ), this );
    m_buttonLayout->addWidget( m_forward );

    // Since "Finish" doesn't save anymore, it actually is a "Forward"
    m_finish = new QPushButton( i18n( "&Forward" ) + QString::fromLatin1( " >" ), this );
    m_buttonLayout->addWidget( m_finish );

    connect( m_cancel, SIGNAL( clicked() ),
             this, SIGNAL( reject() ) );

    connect( m_back, SIGNAL( clicked() ),
             this, SLOT( slotBack() ) );

    connect( m_forward, SIGNAL( clicked() ),
             this, SLOT( slotForward() ) );

    connect( m_finish, SIGNAL( clicked() ),
             this, SLOT( slotFinish() ) );

    setBackEnabled(false);
    setBackVisible(false);
    setForwardEnabled(false);
    setForwardVisible(false);
    setFinishVisible(true);
    setFinishEnabled(true);

    m_escapeAccel = new KAccel( this, "wizard escape accel" );
    m_escapeAccel->insertItem( i18n( "Cancel Wizard" ), "Escape", Key_Escape );
    m_escapeAccel->connectItem( "Escape", this, SIGNAL( reject() ) );
}

Wizard::~Wizard()
{
}

void Wizard::appendPage( QWidget *page )
{
    kdDebug() << "appendPage" << endl;

    // don't reset the current item
    int curr = m_pages.at();

    m_pages.append( page );

    if ( curr > -1 )
        m_pages.at( curr );

    if ( m_pages.count() > 1 )
    {
        setBackEnabled(false);
        setBackVisible(true);
        setForwardEnabled(true);
        setForwardVisible(true);
        setFinishVisible(false);
    }
    setActivePage( 0 );
}

void Wizard::setActivePage( unsigned int pg )
{
    kdDebug() << "setActivePage " << pg << endl;

    assert( pg < m_pages.count() );

    QWidget *page = m_pages.at( pg );

    m_stack->raiseWidget( page );

    if ( page->icon() )
        m_headerIcon->setPixmap( *page->icon() );
    else
        m_headerIcon->setPixmap( QPixmap() );

    m_headerText->setText( page->caption() );

    QVariant quickHelpProp = page->property( "quickHelp" );
    if ( quickHelpProp.type() == QVariant::String )
        m_quickHelp->setText( quickHelpProp.toString() );
    else
        m_quickHelp->setText( QString::null );
}

void Wizard::setBackEnabled( bool enable )
{
    m_back->setEnabled( enable );
}

void Wizard::setForwardEnabled( bool enable )
{
//    kdDebug() << "Wizard::setForwardEnable(): " << (enable ? "yes" : "no") << endl;

    m_forward->setEnabled( enable );

    setFinishEnabled( enable );

    if ( m_pages.current() )
    {
        KXPage *page = dynamic_cast<KXPage *>( m_pages.current() );
        if ( page )
        {
//            kdDebug() << "Saving enabled state to " << m_pages.current()->className() << endl;
            page->setForwardEnabled( enable );
        }
        else
            kdDebug() << "grmbllll : " << m_pages.current()->className() << " doesn't inherit from KXPage" << endl;
    }
}

void Wizard::setFinishEnabled( bool enable )
{
    m_finish->setEnabled( enable );
}

void Wizard::setStatus( const QString &text )
{
    m_status->setText( text );
}

void Wizard::slotBack()
{
// KXPage now tracks, if its forward button is enabled or not. That means the wizard
// must not set it globally as below.
//    setForwardEnabled( true );
    go( -1 );
}

void Wizard::slotForward()
{
    setBackEnabled( true );
    go( 1 );
}

void Wizard::slotFinish()
{
    kdDebug() << "Wizard::slotFinish()" << endl;
    emit accept();
}

void Wizard::go( int step )
{
    // Clear status message
    setStatus( "" );

    setActivePage( m_pages.at() + step );

    unsigned int pos = m_pages.at();

    if ( pos == m_pages.count() - 1 ) { // last page?
        setForwardVisible(false);
        setFinishVisible(true);
    }
    else {
        if ( pos == 0 )  // first page
            setBackEnabled(false);

        setForwardVisible(true);
        setFinishVisible(false);
    }
}
