/***************************************************************************
 *   Copyright (C) 2008 by S. MANKOWSKI / G. DE BURE support@mankowski.fr  *
 *                                                                         *
 *   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, see <http://www.gnu.org/licenses/>  *
 ***************************************************************************/
#ifndef SKGMAINPANEL_H
#define SKGMAINPANEL_H
/** @file
* This file defines a main panel.
*
* @author Stephane MANKOWSKI / Guillaume DE BURE
*/
#include <KParts/MainWindow>
#include <KUrl>
#include <Plasma/Applet>
#include <QSystemTrayIcon>

#include "skgobjectbase.h"
#include "skgtabwidget.h"
#include "skgbasegui_export.h"
#include "skgtabpage.h"
#include "skgbasegui_settings.h"
#include "skginterfaceplugin.h"

#include "ui_skgmainpanel_base.h"
#include "ui_skgmainpanel_pref.h"


class SKGDocument;
class SKGMainPanelPrivate;

class KSplashScreen;
class KMessageWidget;

class QListWidgetItem;

/**
 * This class serves as the main window.  It handles the
 * menus, toolbars, and status bars.
 */
class SKGBASEGUI_EXPORT SKGMainPanel : public KParts::MainWindow
{
    Q_OBJECT
public:
    /**
     * Default Constructor
     * @param iSplashScreen the splash screen
     * @param iDocument the document to manage data
     * @param iArguments the arguments
     */
    explicit SKGMainPanel(KSplashScreen* iSplashScreen, SKGDocument* iDocument, const QStringList& iArguments);

    /**
     * Default Destructor
     */
    virtual ~SKGMainPanel();

    /**
     * Return the document of the main panel
     * @return document of the main panel
     */
    virtual SKGDocument* getDocument() const;

    /**
     * Creates a modal file dialog and returns the selected filename or an empty string if none was chosen.
     * A confirmation message is displayed if needed
     * @param startDir this can either be
     * @li the URL of the directory to start in.
     * @li a KUrl() to start in the current working directory, or the last directory where a file has been selected.
     * @li an URL starting with 'kfiledialog:///\<keyword\>' to start in the directory last used by a filedialog in the same application that specified the same keyword.
     * @li an URL starting with 'kfiledialog:///\<keyword\>?global' to start in the directory last used by a filedialog in any application that specified the same keyword.
     * @param filter a shell glob or a mime-type-filter that specifies which files to display. The preferred option is to set a list of mimetype names, see setMimeFilter() for details. Otherwise you can set the text to be displayed for the each glob, and provide multiple globs, see setFilter() for details.
     * @param iParent the widget the dialog will be centered on initially.
     * @param caption the name of the dialog widget.
     * @param iCodec a valid QString to get the codec.
     * @return the file name
     */
    static QString getSaveFileName(const QString& startDir = KUrl().url(), const QString& filter = QString(), QWidget* iParent = 0,
                                   const QString& caption = QString(), QString* iCodec = NULL);

    /**
     * Display an error message
     * @param iError the error
     * @param iAction the additional action to add
     * @return the message widget
     */
    static KMessageWidget* displayErrorMessage(const SKGError& iError, QAction* iAction = NULL);

    /**
     * Fill a widget with distinct values
     * @param iWidget the widget
     * @param iDoc document
     * @param iTable table
     * @param iAttribut attribute
     * @param iWhereClause where clause
     * @param iAddoperators to add operators (=upper, =lower to the list)
     */
    static void fillWithDistinctValue(
        QWidget* iWidget,
        SKGDocument* iDoc,
        const QString& iTable,
        const QString& iAttribut,
        const QString& iWhereClause,
        bool iAddoperators = false);

    /**
     * Return main panel
     */
    static SKGMainPanel* getMainPanel();

    /**
     * Get main config groupe
     * @return main config groupe
     */
    static KConfigGroup getMainConfigGroup();

public Q_SLOTS:

    /**
     * Display a message
     * @param iMessage the message
     * @param iType the type
     * @return the message widget
     */
    virtual KMessageWidget* displayMessage(const QString& iMessage, SKGDocument::MessageType iType = SKGDocument::Information);


    /**
     * Display an error message
     * @param iMessage the error message. If the message is "", the data of the sender will be used
     * @return the message widget
     */
    virtual KMessageWidget* displayErrorMessage(const QString& iMessage = "");

    /**
     * This function is called when the application is launched again with new arguments
     * @param iArgument the arguments
     * @return true if the arguments have been processed
     */
    virtual bool processArguments(const QStringList& iArgument);

    /**
     * Get the current selection
     * @return selected objects
     */
    virtual SKGObjectBase::SKGListSKGObjectBase getSelectedObjects();

    /**
     * Get the number of seleted object
     * @return number of selected objects
     */
    virtual int getNbSelectedObjects();

    /**
     * To know if the closure of the application is authorized
     * @return true if close is authorized else false
     */
    virtual bool queryClose();

    /**
     * To know if the closure of the file is authorized
     * @return true if close is authorized else false
     */
    virtual bool queryFileClose();

    /**
     * Return the plugin number by index
     * @param iIndex the index of the plugin
     * @return the plugin pointer. Can be NULL. Mustn't be deleted
     */
    virtual SKGInterfacePlugin* getPluginByIndex(int iIndex);

    /**
     * Return the plugin number by name
     * @param iName the name of the plugin
     * @return the plugin pointer. Can be NULL. Mustn't be deleted
     */
    virtual SKGInterfacePlugin* getPluginByName(const QString& iName);

    /**
     * Returns a list of all known applets.
     * @return list of applets
     **/
    virtual KPluginInfo::List getPlasmaApplets();

    /**
     * Get the label for normal message in status bar
     * @return the label
     */
    virtual QLabel* statusNormalMessage() const;

    /**
     * Get the current splash screen. NULL is the splash screen is closed.
     * @return the splash screen
     */
    virtual KSplashScreen* splashScreen() const;

    /**
     * Set the main widget
     * @param iWidget the widget to display when all pages are closed
     */
    virtual void setMainWidget(QWidget* iWidget);

    /**
     * Get the tab widget.
     * @return the tab widget
     */
    virtual SKGTabWidget* getTabWidget() const;

    /**
     * Get the history item of the current page
     * @return the history item
     */
    virtual SKGTabPage::SKGPageHistoryItem currentPageHistoryItem() const;

    /**
     * Get the index of the current page
     * @return index of the current page
     */
    virtual int currentPageIndex() const;

    /**
     * Get the current page
     * @return the current page
     */
    virtual SKGTabPage* currentPage() const;

    /**
     * Get a page
     * @param iIndex an index
     * @return the page
     */
    virtual SKGTabPage* page(int iIndex) const;

    /**
     * Get then number of pages
     * @return the number of pages
     */
    virtual int countPages() const;

    /**
     * Set the current page
     * @param iIndex the current page
     */
    virtual void setCurrentPage(int iIndex);

    /**
     * Set the context item visibility
     * @param iPage index of the page in the pages chooser
     * @param iVisibility the visibility
     */
    virtual void setContextVisibility(int iPage, bool iVisibility);

    /**
     * Set the context item visibility
     * @param iItem item in the pages chooser
     * @param iVisibility the visibility
     */
    virtual void setContextVisibility(QListWidgetItem* iItem, bool iVisibility);

    /**
     * Open a plugin in a page
     * @param iUrl the url like this "skg://plugin_name/?param1=value1&param2=value2&..." to open a special page
     * or "skg://action" to trigger an action
     * or "http://..." to open a web page
     * @param iNewPage to open a new page or not
     * @return true if the url has been opened
     */
    virtual bool openPage(const QUrl& iUrl, bool iNewPage = true);

    /**
     * Open a plugin in a page
     * @param iUrl the url like this "skg://plugin_name/?param1=value1&param2=value2&..." to open a special page
     * or "skg://action" to trigger an action
     * or "http://..." to open a web page
     * @param iNewPage to open a new page or not
     * @return true if the url has been opened
     */
    virtual bool openPage(const QString& iUrl = "", bool iNewPage = true);

    /**
     * Open a plugin in a page
     * @param iPage index of the page in the pages chooser
     * @param iNewPage to open a new page or not
     * @return the opened tab
     */
    virtual SKGTabPage* openPage(int iPage, bool iNewPage = true);

    /**
     * Open a plugin in a page
     * @param plugin the plugin
     * @param index index of the tab to replace or -1 to add a new one
     * @param parameters parameters of the plugin
     * @param title title of the page
     * @param iID id of the new page
     * @param iSetCurrent to set the new page as the current one
     * @return the opened tab
     */
    virtual SKGTabPage* openPage(SKGInterfacePlugin* plugin, int index = -1, const QString& parameters = "", const QString& title = "", const QString& iID = "", bool iSetCurrent = true);

    /**
     * Switch the pin state of the page
     * @param iWidget the page to remove (NULL means current one)
     */
    virtual void switchPinPage(QWidget* iWidget = NULL);

    /**
     * Close a page
     * @param iWidget the page to remove (NULL means current one)
     * @param iForce to close pinned pages too
     */
    virtual void closePage(QWidget* iWidget = NULL, bool iForce = false);

    /**
     * Close all other pages
     * @param iWidget the page to keep (NULL means current one)
     */
    virtual void closeAllOtherPages(QWidget* iWidget = NULL);

    /**
     * Close all pages
     * @param iForce to close pinned pages too
     */
    virtual void closeAllPages(bool iForce = false);

    /**
     * Register a global action
     * @param iIdentifier identifier of the action
     * @param iAction action pointer
     * @param iAddInCollection to add or not the action in the main panel collection
     */
    virtual void registerGlobalAction(const QString& iIdentifier, QAction* iAction, bool iAddInCollection = true);

    /**
     * Unregister a global action
     * @param iAction action pointer
     */
    virtual void unRegisterGlobalAction(QObject* iAction);


    /**
     * Get a registered global action
     * @param iIdentifier identifier of the action
     * @param iWarnIfNotExist warn if the action does not exist
     * @return action pointer
     */
    virtual QAction* getGlobalAction(const QString& iIdentifier, bool iWarnIfNotExist = true);

    /**
     * Get all registered global actions
     * @return actions
     */
    virtual QMap<QString, QPointer<QAction> > getGlobalActions() const;

    /**
     * Get the temporary filename containing the tips of days
     * @return the file name
     */
    virtual QString getTipOfDayFileName();
    /**
     * Define if the document must be saved when closed
     * @param iSaveOnClose the save on close mode
     */
    virtual void setSaveOnClose(bool iSaveOnClose);

    /**
     * Force the refresh of the object.
     */
    virtual void refresh();

    /**
     * Send notifications corresponding to the transaction.
     * @param iTransaction the transaction identifier
     */
    virtual void notify(int iTransaction = 0);

    /**
     * Open settings panel on dedicated page.
     * @param iPluginName the name of the plugin (pluginInterface->objectName())
     */
    virtual void optionsPreferences(const QString& iPluginName = "");

    /**
     * Get all advice
     * @return the list of advice
     */
    virtual SKGAdviceList getAdvice() const;

Q_SIGNALS:
    /**
     * This signal is sent when a new page is opened.
     */
    void pageOpened();

    /**
     * This signal is sent when a new page is opened.
     */
    void pageClosed();

    /**
     * This signal is sent when the current page change.
     */
    void currentPageChanged();

    /**
     * This signal is sent when settings change.
     */
    void settingsChanged();

protected:
    /**
     * event
     * @param e event
     */
    virtual void changeEvent(QEvent* e);
    /**
     * Event filtering
     * @param iObject object
     * @param iEvent event
     * @return In your reimplementation of this function, if you want to filter the event out, i.e. stop it being handled further, return true; otherwise return false.
     */
    virtual bool eventFilter(QObject* iObject, QEvent* iEvent);

private Q_SLOTS:
    void showMenu(const QPoint& iPos);

    void onSettingsChanged();
    void onCancelCurrentAction();
    void onQuitAction();

    void addTab();
    void onBeforeOpenContext();
    void onOpenContext(Qt::MouseButtons iMouse = Qt::LeftButton, Qt::KeyboardModifiers iKeyboard = Qt::NoModifier);
    void onTipOfDay();
    void onTrayActivated(QSystemTrayIcon::ActivationReason reason);
    void saveDefaultState();
    void resetDefaultState();
    void overwriteBookmarkState();
    void enableEditor();

    void onPrevious();
    void onNext();
    void onReopenLastClosed();
    void onFullScreen();

    void onShowPreviousMenu();
    void onShowNextMenu();
    void onZoomChanged();

    void onShowMenuBar();
    void onShowButtonMenu();

    void onHideContextItem();
    void onShowAllContextItems();

    void onLockDocks();
    void onUnlockDocks();

    void onConfigureNotifications();

    void onClearMessages();

private:
    Q_DISABLE_COPY(SKGMainPanel)
    void setupActions();

    SKGMainPanelPrivate* const d;
};

#endif  // SKGMAINPANEL_H
