/***************************************************************************
 *   Copyright (C) 2003-2005 by David Saxton                               *
 *   david@bluehaze.org                                                    *
 *                                                                         *
 *   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.                                   *
 ***************************************************************************/

#ifndef KTECHLAB_H
#define KTECHLAB_H

#include <katemdi.h>

#include <QList>
#include <QMap>
#include <QPointer>
#include <QUrl>

class CircuitDocument;
class TextDocument;
class ComponentSelector;
class Document;
class FlowCodeDocument;
class ItemEditor;
class LanguageManager;
class LogView;
class MechanicsDocument;
class ProjectManager;
class View;
class ViewArea;
class ViewContainer;

typedef QMap<int, QString> IntStringMap;
typedef QList<QPointer<ViewContainer>> ViewContainerList;

class KRecentFilesAction;
class QTabWidget;
class KToggleAction;
class QLabel;

/**
 * This class serves as the main window for KTechlab.  It handles the
 * menus, toolbars, status bars, loading/saving files, config, etc.
 *
 * @short Main window class
 * @author David Saxton
 */
class KTechlab : public KateMDI::MainWindow
{
    Q_OBJECT

    friend class KtlTestsAppFixture;

public:
    KTechlab();
    ~KTechlab() override;

    /**
     * @return pointer to the main KTechlab object. This is set to null when
     * KTechlab is about to be deleted.
     */
    static KTechlab *self()
    {
        return m_pSelf;
    }
    /**
     * The standard item font in use (set to a maximum of 12 pixels).
     */
    QFont itemFont() const
    {
        return m_itemFont;
    }
    /**
     * Returns a pointer to an action with the given name.
     */
    QAction *actionByName(const QString &name) const;
    /**
     * Returns a URL from a Open File dialog (with all ktechlab related file
     * types allowed).
     * @param allowMultiple Whether to allow the user to select more than
     * one URL.
     */
    static QList<QUrl> getFileURLs(bool allowMultiple = true);
    /**
     * Returns a list of the recently opened/saved files
     */
    QList<QUrl> recentFiles();
    /**
     * The tab and window captions will get updated when we have re-entered
     * the Qt event loop.
     */
    void requestUpdateCaptions();
    /**
     * Returns the tabwidget that shows the list of view containers.
     */
    QTabWidget *tabWidget() const
    {
        return m_pViewContainerTabWidget;
    }
    /**
     * Registers the viewcontainer with the internal list.
     */
    void addWindow(ViewContainer *vc);
    /**
     * Removes all gui clients added to the factory other than ourself.
     */
    void removeGUIClients();
    /**
     * Work around a crash. Adds the given KXMLGUIClient to a list of those
     * that ktechlab will not attempt to remove on calling removeGUIClients.
     */
    void addNoRemoveGUIClient(KXMLGUIClient *client);
    /**
     * For preventing flickering when we are updating the toolbars - grab
     * a pixmap of the current toolbars, and overlay it in position.
     */
    void overlayToolBarScreenshot();
    /**
     * Opens a file in the given ViewArea.
     */
    void openFile(ViewArea *viewArea);

    virtual void show();

signals:
    /**
     * Emitted when the user changes the configuration settings in the config dialog
     */
    void configurationChanged();
    /**
     * Emitted when a recent file is added
     */
    void recentFileAdded(const QUrl &url);
    /**
     * Emitted when ViewContainers should update their captions.
     */
    void needUpdateCaptions();

public slots:
    /**
     * The user right clicked on a tab item.
     */
    void slotTabContext(const QPoint &pos);
    /**
     * The user clicked on an item in the tab-menu (from right clicking).
     */
    void slotTabContextActivated(QAction *action);
    void slotChangeStatusbar(const QString &text);
    /**
     * Open the document at the given url. If viewArea is non-null, then the
     * new view will be put into viewArea.
     */
    void load(const QUrl &url, ViewArea *viewArea = nullptr);
    void slotUpdateConfiguration();
    /**
     * Adds a url to the list of recently opened files
     */
    void addRecentFile(const QUrl &url);
    /**
     * A document had its modified state changed; will update actions,
     * tab titles, etc as appropriate.
     */
    void slotDocModifiedChanged();
    /**
     * A document had its undo/redo state changed; will update actions,
     * tab titles, etc as appropriate.
     */
    void slotDocUndoRedoChanged();

    void slotFileNewAssembly();
    void slotFileNewMicrobe();
    void slotFileNewC();
    void slotFileNewCircuit();
    void slotFileNewFlowCode();
    void slotFileNewMechanics();
    void slotFileNew();
    void slotFileOpen();
    void slotFileSave();
    void slotFileSaveAs();
    void slotFilePrint();
    void slotFileQuit();

protected:
    /**
     * Overridden virtuals for Qt drag 'n drop (XDND)
     */
    void dragEnterEvent(QDragEnterEvent *event) override;
    void dropEvent(QDropEvent *event) override;
    /**
     * This function is called when it is time for the app to save its
     * properties for session management purposes.
     */
    void savePropertiesInConfig(KConfig *);
    /**
     * This function is called when this app is restored.  The KConfig
     * object points to the session management config file that was saved
     * with @ref saveProperties
     */
    void readPropertiesInConfig(KConfig *);
    /**
     * Called before the window is closed, either by the user or indirectly by the session manager.
     * This function doesn't actually close the main window; it only queries the user and closes the active view.
     * To quit the appliaction completly, you should use KTechlab::slotFileQuit()
     */
    bool queryClose() override;

protected slots:
    void slotViewContainerActivated(int index);
    void slotUpdateTabWidget();
    /**
     * Updates the tab and window captions from what is currently open and
     * focused.
     */
    void slotUpdateCaptions();

private slots:
    /**
     * Called from a QTimer timeout (which should be after the toolbars have
     * finished constructing themselves).
     */
    void hideToolBarOverlay();
    /**
     * Called when the user clicks on an example (circuit, etc) from the
     * help menu/
     */
    void openExample(QAction *);
    void slotViewContainerDestroyed(QObject *obj);

    // Editing operations
    void slotEditUndo();
    void slotEditRedo();
    void slotEditCut();
    void slotEditCopy();
    void slotEditPaste();

    /**
     * Split the current view into two
     */
    void slotViewSplitLeftRight();
    /**
     * Split the current view into two
     */
    void slotViewSplitTopBottom();
    void slotViewContainerClose();
    void slotViewClose();

    void slotOptionsShowStatusbar();
    void slotOptionsConfigureKeys();
    void slotOptionsConfigureToolbars();
    void slotOptionsPreferences();
    void slotLoadRecent(const QUrl &url);

private:
    void setupActions();
    void setupExampleActions();
    void setupToolDocks();
    void setupView();
    void setupTabWidget();
    void loadInternal(const QUrl &url, bool isRecent, ViewArea *viewArea = nullptr);

    KRecentFilesAction *m_recentFiles;
    KRecentFilesAction *m_recentProjects;
    KToggleAction *m_statusbarAction;
    QTabWidget *m_pViewContainerTabWidget;
    QString m_lastStatusBarMessage;
    QList<KXMLGUIClient *> m_noRemoveGUIClients;
    QLabel *m_pToolBarOverlayLabel;
    bool m_bIsShown; // Set true when show() is called
    ViewContainerList m_viewContainerList;
    QTimer *m_pUpdateCaptionsTimer;
    IntStringMap m_exampleFiles;
    QFont m_itemFont;

    static KTechlab *m_pSelf;

    QPointer<ViewContainer> m_pContextMenuContainer;
    QPointer<ViewContainer> m_pFocusedContainer;
    QPointer<ViewContainer> m_pContainerDropSource;
    QPointer<ViewContainer> m_pContainerDropReceived;
};

#endif // KTECHLAB_H
