/***************************************************************************
 *   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 "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"

#include <kparts/mainwindow.h>
#include <ktabwidget.h>
#include <kurl.h>
#include <ksystemtrayicon.h>
#include <ktemporaryfile.h>

class SKGDocument;
class SKGZoomSelector;

class QPrinter;
class QListWidgetItem;

class KToggleAction;
class KUrl;
class KAction;
class KSplashScreen;
class KListWidget;
class KComboBox;
class KToolBarPopupAction;
class KMenu;

/**
 * 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
     */
    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 parent 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* parent = 0,
                                   const QString& caption = QString(), QString* iCodec = NULL);

    /**
     * Display an error message
     * @param iError the error
     */
    static void displayErrorMessage(const SKGError& iError);

    /**
     * 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:
    /**
     * This function is called when the application is launched again with new arguments
     * @param iArgument the arguments
     */
    virtual void 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);

    /**
     * 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 iPage index of the page in the pages chooser
     * @param iNewPage to open a new page or not
     */
    virtual void openPage(int iPage, bool iNewPage);

    /**
     * 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
     */
    virtual void registerGlobalAction(const QString& iIdentifier, KAction* iAction);

    /**
     * Get a registered global action
     * @param iIdentifier identifier of the action
     * @return action pointer
     */
    virtual KAction* getGlobalAction(const QString& iIdentifier);

    /**
     * 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 advices
     * @return the list of advices
     */
    virtual SKGAdviceList getAdvices() const;

Q_SIGNALS:
    /**
     * 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 object object
     * @param event 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* object, QEvent* event);

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

    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 actionPrevious();
    void actionNext();
    void actionFullScreen();

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

    void onShowMenuBar();
    void onShowButtonMenu();

    void actionHideContextItem();
    void actionShowAllContextItems();

    void actionLockDocks();
    void actionUnlockDocks();
private:
    Q_DISABLE_COPY(SKGMainPanel);
    void setupActions();
    bool iconInSystemtray();
    void refreshTabPosition();

    static int progressBarCallBack(int iPos, qint64 iTime, const QString& iName, void* iProgressBar);
    static bool naturalLessThan(const QString& s1, const QString& s2);
    static bool adviceLessThan(const SKGAdvice& s1, const SKGAdvice& s2);


    Ui::skgmainpanel_base ui;
    Ui::skgmainpanel_pref uipref;

    SKGTabWidget* m_tabWidget;
    KSplashScreen* m_splashScreen;

    SKGDocument* m_currentDocument;

    QList<SKGInterfacePlugin*> m_pluginsList;
    QMap<QString, KAction*> m_registeredGlogalAction;
    QList<QWidget*> m_hiddenWidgets;

    KMenu* m_contextMenu;
    QAction* m_actHideContextItem;
    QAction* m_actShowAllContextItems;
    QAction* m_actDelete;
    KAction* m_addTabAction;
    KAction* m_tipOfDayAction;
    KAction* m_closePageAction;
    KAction* m_closeAllPagesAction;
    KAction* m_closeAllOtherPagesAction;
    KAction* m_switchPinState;
    KAction* m_saveDefaultStateAction;
    KAction* m_resetDefaultStateAction;
    KAction* m_overwriteBookmarkStateAction;
    KAction* m_configureAction;
    KAction* m_enableEditorAction;
    KAction* m_fullScreenAction;
    KAction* m_actLock;
    KAction* m_actUnLock;
    KTemporaryFile m_tipsFile;
    KSystemTrayIcon* m_kSystemTrayIcon;
    QLabel* m_kNormalMessage;
    SKGZoomSelector* m_zoomSelector;

    KToolBarPopupAction* m_previousAction;
    KToolBarPopupAction* m_nextAction;
    KToolBarPopupAction* m_buttonMenuAction;
    KToggleAction* m_showMenuBarAction;

    KMenu* m_previousMenu;
    KMenu* m_nextMenu;
    KMenu* m_buttonMenu;
    QWidget* m_mainWidget;
    QHBoxLayout* m_mainLayout;

    struct doublePointer {
        void* p1;
        void* p2;
    };

    doublePointer m_progressObjects;
    bool m_middleClick;
    bool m_saveOnClose;

    static bool m_currentActionCanceled;
    static SKGMainPanel* m_mainPanel;
};

#endif // SKGMAINPANEL_H
