/***************************************************************************
 *   Copyright (C) 2005 by Max Howell <max.howell@methylblue.com>          *
 *                                                                         *
 *   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 Steet, Fifth Floor, Boston, MA  02110-1301, USA.             *
 ***************************************************************************/

#ifndef KDE_STATUSBAR_H
#define KDE_STATUSBAR_H

#include "progressBar.h" //convenience
#include "amarok_export.h"
#include <tqwidget.h>     //baseclass
#include <tqmap.h>        //stack allocated
#include <tqvaluelist.h>  //stack allocated

class TQLabel;
class TQTimer;

namespace TDEIO { class Job; }

//TODO
// * concept of a temporary message that is removed when a qobject parent is deleted

namespace KDE
{
    class OverlayWidget;
    typedef TQMap<const TQObject*, ProgressBar*> ProgressMap;

    /**
     * @class KDE::StatusBar
     * @short advanced statusBar
     * @author Max Howell <max.howell@methylblue.com>
     *
     * Like a normal TQStatusBar, but add widgets directly:
     *
     *    new TQLabel( text, statusbar );
     *
     * The statusbar has some handy progress monitoring behaviour, use like so:
     *
     *    statusbar->newProgressOperation( myObject )
     *          .setDescription( i18n("MyProgressOperation") )
     *          .setStatus( i18n("Stage1") )
     *          .setAbortSlot( myObject, TQ_SLOT(abort()) )
     *          .setTotalSteps( 100 );
     *
     * The newProgressOperation function returns a KDE::ProgressBar, which is
     * a TQProgressBar with some additional functions that return ProgressBar&,
     * so you can chain the mutators like above. @see KDE::ProgressBar
     *
     * After this point you can use setProgress( TQObject*, int steps ) to update
     * the progress for this progress operation. Only one progress operation per
     * TQObject!
     *
     * You can also follow TDEIO::Jobs, with built in error handling, and
     * ThreadManager::Jobs have built in thread-safe progress handling.
     *
     * You can show long status/error messages using longMessage(), these are
     * meant to be instead of showing an irritating, interuptory KMessageBox.
     *
     * Caveats:
     * This only looks sensible if the statusbar is at the bottom of the screen
     *
     * @see KDE::ProgressBar
     */

    class LIBAMAROK_EXPORT StatusBar : public TQWidget
    {
        TQ_OBJECT
  

    public:
        StatusBar( TQWidget *parent, const char *name = "mainStatusBar" );

        enum MessageType { Information, Question, Sorry, Warning, Error, ShowAgainCheckBox, None };

        /**
         * Start a progress operation, if owner is 0, the return value is
         * undefined - the application will probably crash.
         * @param owner controls progress for this operation
         * @return the progressBar so you can configure its parameters
         * @see setProgress( TQObject*, int )
         * @see incrementProgress( TQObject* )
         * @see setProgressStatus( const TQObject*, const TQString& )
         */
        ProgressBar &newProgressOperation( TQObject *owner );

        /**
         * Monitor progress for a TDEIO::Job, very handy.
         */
        ProgressBar &newProgressOperation( TDEIO::Job* );

        void incrementProgressTotalSteps( const TQObject *owner, int inc = 1 );
        void incrementProgress( const TQObject *owner );
        void setProgressStatus( const TQObject *owner, const TQString &text );

    public slots:
        /**
         * The statusbar has a region where you can display a mainMessage.
         * It persists after all other message-types are displayed
         */
        void setMainText( const TQString &text );

        /// resets mainText if you've done a shortMessage
        void resetMainText();

        /**
         * Shows a non-invasive messgeBox style message that the user has to dismiss
         * but it doesn't interupt whatever he is doing at the current time.
         * Generally you should use these, as it is very easy for a user to not notice
         * statusBar messages.
         */
        void longMessage( const TQString &text, int type = Information );

        void longMessageThreadSafe( const TQString &text, int type = Information );


        /**
         * Shows a short message, with a button that can be pushed to show a long
         * message
         */
        void shortLongMessage( const TQString &_short, const TQString &_long, int type = Information );

        /**
         * Set a temporary message over the mainText label, for 5 seconds.
         * ONLY USE FOR STATUS MESSAGES! ie "Buffering...", "Connecting to source..."
         */
        void shortMessage( const TQString &text, bool longShort = false );

        /** Stop anticipating progress from sender() */
        void endProgressOperation();

        /** Stop anticipating progress from @param owner */
        void endProgressOperation( TQObject *owner );

        /**
         * Convenience function works like setProgress( TQObject*, int )
         * Uses the return value from sender() to determine the owner of
         * the progress bar in question
         */
        void setProgress( int steps );
        void setProgress( const TQObject *owner, int steps );
        /**
         * Convenience function works like setTotalSteps( TQObject*, int )
         * Uses the return value from sender() to determine the owner of
         * the progress bar in question
         */
        //void setTotalSteps( int totalSteps );

        /**
         * Convenience function works like incrementProgress( TQObject* )
         * Uses the return value from sender() to determine the owner of
         * the progress bar in question
         */
        void incrementProgress();

    public slots:
        void toggleProgressWindow( bool show );
        void abortAllProgressOperations();

    private slots:
        /** For internal use against TDEIO::Jobs */
        void setProgress( TDEIO::Job*, unsigned long percent );
        void showMainProgressBar();
        void hideMainProgressBar();
        void updateProgressAppearance();
        void showShortLongDetails();
        void popupDeleted( TQObject* );

    protected:
        virtual void polish();
        virtual void customEvent( TQCustomEvent* );
        virtual void paintEvent( TQPaintEvent* );
        virtual bool event( TQEvent* );

        /**
         * You must parent the widget to the statusbar, we won't do that
         * for you! The widget will be added to the right of the layout.
         * Currently you must add widgets before the statusbar gets shown
         * for the first time, because we are not currently very flexible.
         */
        void addWidget( TQWidget *widget );

        TQLabel *m_mainTextLabel;

    private:
        struct Message
        {
            Message() : type( KDE::StatusBar::None ), offset( 0 ) {}
            Message( const TQString &_text, const MessageType _type ) : text( _text ), type( _type ), offset( 0 ) {}

            TQString text;
            MessageType type;

            int offset;
        };

        void updateTotalProgress();
        bool allDone(); ///@return true if all progress operations are complete
        void pruneProgressBars(); /// deletes old progress bars
        void writeLogFile( const TQString &text );

        int  m_logCounter;

        TQWidget *cancelButton() { return static_cast<TQWidget*>( child( "cancelButton" ) ); }
        TQWidget *toggleProgressWindowButton() { return static_cast<TQWidget*>( child( "showAllProgressDetails" ) ); }
        TQWidget *progressBox() { return static_cast<TQWidget*>( child( "progressBox" ) ); }
        TQWidget *shortLongButton() { return static_cast<TQWidget*>( child( "shortLongButton" ) ); }

        OverlayWidget *m_popupProgress;
        TQProgressBar  *m_mainProgressBar;

        ProgressMap          m_progressMap;
        TQValueList<TQWidget*> m_messageQueue;
        TQString              m_mainText;
        TQString              m_shortLongText;
        int                  m_shortLongType;

        TQLayout *m_otherWidgetLayout;
    };
}
#endif
