/*****************************************************************************
 * $CAMITK_LICENCE_BEGIN$
 *
 * CamiTK - Computer Assisted Medical Intervention ToolKit
 * (c) 2001-2016 Univ. Grenoble Alpes, CNRS, TIMC-IMAG UMR 5525 (GMCAO)
 *
 * Visit http://camitk.imag.fr for more information
 *
 * This file is part of CamiTK.
 *
 * CamiTK is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * CamiTK 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 Lesser General Public License version 3 for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with CamiTK.  If not, see <http://www.gnu.org/licenses/>.
 *
 * $CAMITK_LICENCE_END$
 ****************************************************************************/


#ifndef MAINWINDOW_H
#define MAINWINDOW_H

// -- Core stuff
#include "CamiTKAPI.h"
#include "ConsoleStream.h"

// -- QT stuff
#include <QMainWindow>
#include <QApplication>
#include <QDir>
#include <QTextEdit>
#include <QProgressBar>
#include <QStatusBar>


namespace camitk {

// -- Core stuff classes
class Component;
class Viewer;

/**
  * @ingroup group_sdk_libraries_core_application
  *
  * @brief
  * This Class is the base class for your application. It sets up the main
  * window and providing a menubar, toolbar and statusbar (all hidden).
  * It is the default main window for a application.
  *
  * Create a class that inherits from MainWindow to
  * get all the goodies of Core and add your own customization/UI.
  * See applications for examples.
  *
  */
class CAMITK_API MainWindow : public QMainWindow {
    Q_OBJECT

public:

    /// @name general
    ///@{
    /** Constructor, the window title can be changed here, it is inconsistent to use setWindowTitle().
     * If you like to dynamically add some information to the window title, please use setWindowSubtitle() instead.
     *
     * @see setWindowSubtitle
     * @param title main window title
     */
    MainWindow(QString title);

    /// destructor
    virtual ~MainWindow();

    /** this method is automatically called by Application before the first time show() is called.
     * This method calls initSettings().
     */
    virtual void aboutToShow();

    ///@}

    /// @name subtitle, status bar message, progress bar state and console
    ///@{
    /** The subtitle is situated at the end of the title, on the title bar, is helps for example showing which file is currently
     *  selected.
     *  It appears between brackets "[ ... ]"
     *
     *  \note the main title is set to Core::version, you can change the title part (i.e. the part
     *  of the title bar before the subtitle), by calling setWindowTitle(...)
     */
    void setWindowSubtitle(QString);

    /// similar as statusBar() from QMainWindow but for the progress bar
    QProgressBar * getProgressBar();

    /// show the status bar (by default it is hidden)
    void showStatusBar(bool);

    /// use or not the application console (redirect or not standard out/err streams)
    virtual void redirectToConsole(bool);

    /// get the console window
    void showConsole(bool);
    ///@}

    /// @name Viewers
    ///@{



    /// set the visibility for the given viewer (if it is in a dock)
    virtual void showViewer(Viewer *, bool);

    /** add a Viewer to the application as a docking widget and specify where it has to be docked
    * Note that MainWindow takes ownership of the Viewer pointer and deletes it at the appropriate time.
    * This method calls addViewer(...).
    */
    virtual void addDockViewer(Qt::DockWidgetArea, Viewer*);

    /** Method uses to refresh all the viewer of the Main Window */
    void refreshViewers();

    /** set the central Viewer of the application.
    * Note that MainWindow takes ownership of the Viewer pointer and deletes it at the appropriate time.
    * This method calls addViewer(...).
    */
    virtual void setCentralViewer(Viewer*);

    /**
     * @Return the actual central viewer.
     * @return
     */
    virtual const Viewer & getCentralViewer() const;
    ///@}

    ///@cond
    /**
     * TODO CAMITK_DEPRECATED. This section list all the methods marked as deprecated. They are to be removed in CamiTK 4.0
     * @deprecated
     * Add a viewer (called by addDockViewer and setCentralViewer), returns true if not already added.
     * Note that MainWindow takes ownership of the Viewer pointer and deletes it at the appropriate time.
     * This method connects the selectionChanged signal of the viewer to the refresh method.
     * DEPRECATED (CamiTK 4.0) -> should still exist but private
     */
    virtual bool addViewer(Viewer*);
    ///@endcond


public slots:

    /** @name Refresh and show */
    ///@{
    /// this slot is connected to all the viewers selectionChanged() signal, this will call the refresh method of all viewers
    virtual void refresh();

    /// inherited from QWidget, just to refresh all viewers
    void show();
    ///@}


protected:

    /// overriden from QMainWindow, just connect to slotFileQuit
    virtual void closeEvent ( QCloseEvent *);

    /** @name Viewer and other things */
    ///@{
    /// the set of viewers
    QList<Viewer *> viewers;

    /// the map that gives the corresponding QDockWidget for a given Viewer
    QMap<Viewer*, QDockWidget*> dockWidgetMap;

    /// init MainWindow specific settings (e.g. size, position)
    virtual void initSettings();
    ///@}

    /// called when a drag event started on the main window, accept drag only if file is MIME type text/uri-list
    void dragEnterEvent(QDragEnterEvent *event);

    /// called when the mouse moves inside the widgets area during a drag/drop operation
    void dragMoveEvent(QDragMoveEvent* event);

    /// called when the mouse leaves the widgets area during a drag/drop operation
    void dragLeaveEvent(QDragLeaveEvent* event);

    /// just call open with the dragged uri
    void dropEvent(QDropEvent *event);

    /**
     * @brief Remove the given viewer from the list of viewer.
     * @note This tell all Component not to be visible anymore in this viewer instance, remove it from the list of viewers and delete it.
     * @param viewer The viewer to remove.
     * @return True if removing succeeded, false otherwise.
     */
    bool removeViewer(Viewer* viewer);

    /**
     * @brief The actual central Viewer.
     * @note MainWindow, like QMainWindow with its central widget contains an unique central viewer.
     */
    Viewer* centralViewer;


private:

    /// the output stream for the application console
    ConsoleStream cout;

    /// the error stream for the application console
    ConsoleStream cerr;

    /// the progress bar (access through setProgress() method)
    QProgressBar *myProgressBar;

    /// console to display all messages
    QDialog *consoleWindow;

    /// the QTextEdit part of the console dialog
    QTextEdit *consoleWindowTextEdit;

    /// the main part of the title
    QString mainTitle;
};
}


#endif // MAINWINDOW_H
