//  ************************************************************************************************
//
//  BornAgain: simulate and fit reflection and scattering
//
//! @file      GUI/View/Main/MainWindow.cpp
//! @brief     Implements class MainWindow.
//!
//! @homepage  http://www.bornagainproject.org
//! @license   GNU General Public License v3 or higher (see COPYING)
//! @copyright Forschungszentrum Jülich GmbH 2018
//! @authors   Scientific Computing Group at MLZ (see CITATION, AUTHORS)
//
//  ************************************************************************************************

#include "GUI/View/Main/MainWindow.h"
#include "GUI/Model/Job/JobsSet.h"
#include "GUI/Model/Project/ProjectDocument.h"
#include "GUI/Model/Util/Path.h"
#include "GUI/View/Base/mainwindow_constants.h"
#include "GUI/View/Main/ActionManager.h"
#include "GUI/View/Main/CentralWidget.h"
#include "GUI/View/Main/ProjectManager.h"
#include "GUI/View/Setup/FrameActions.h"
#include "GUI/View/Widget/AppConfig.h"
#include <QApplication>
#include <QDir>
#include <QMessageBox>
#include <QSettings>

MainWindow::MainWindow()
{
    gActions = new FrameActions;

    // The following must not be moved to the initializer list because they may need gActions.
    m_project_manager = new ProjectManager(this);
    m_action_manager = new ActionManager(this, m_project_manager);
    m_central_widget = new CentralWidget;

    setCentralWidget(m_central_widget);

    initApplication();
    loadSettings();

    connect(m_project_manager, &ProjectManager::documentOpenedOrClosed, this,
            &MainWindow::onDocumentOpenedOrClosed);

    connect(gDoc.get(), &ProjectDocument::modifiedStateChanged, this,
            &MainWindow::onDocumentModified);

    connect(m_central_widget, &CentralWidget::currentViewChanged, m_action_manager,
            &ActionManager::onCurrentViewChanged);

    connect(m_project_manager, &ProjectManager::documentOpenedOrClosed, m_action_manager,
            &ActionManager::updateActionEnabling);

    onDocumentOpenedOrClosed(true);
}

MainWindow::~MainWindow() = default;

void MainWindow::updateTitle()
{
    QString location = "not saved yet";
    if (gDoc->hasValidNameAndPath())
        location = GUI::Path::withTildeHomePath(QDir::toNativeSeparators(gDoc->projectFullPath()));
    const QString cModified = gDoc->isModified() ? "*" : "";
    setWindowTitle("BornAgain - " + cModified + gDoc->projectName() + " [" + location + "]");
}

void MainWindow::closeEvent(QCloseEvent* event)
{
    if (gDoc->jobs()->hasUnfinishedJobs()) {
        QMessageBox::warning(this, "Cannot quit the application.",
                             "Cannot quit the application while jobs are running.\n"
                             "Cancel running jobs or wait until they are completed.");
        event->ignore();
        return;
    }
    if (m_project_manager->saveOnQuit()) {
        saveSettings();
        event->accept();
    } else {
        event->ignore();
    }
}

void MainWindow::onRunSimulationShortcut()
{
    /* TODO 5mar
    // This clearFocus is needed for the propagation of the current editor value,
    // since the simulate method will only change focus after finishing the simulation
    if (auto* widget = QApplication::focusWidget())
        widget->clearFocus();
    m_simulation_view->simulate();
    */
}

void MainWindow::initApplication()
{
    setDockNestingEnabled(true);
    setAcceptDrops(true);

    setCorner(Qt::BottomLeftCorner, Qt::LeftDockWidgetArea);
    setCorner(Qt::BottomRightCorner, Qt::BottomDockWidgetArea);
}

void MainWindow::loadSettings()
{
    QSettings s;
    s.beginGroup(GUI::Style::S_MAIN_WINDOW);
    resize(s.value(GUI::Style::S_WINDOW_SIZE, QSize(1000, 600)).toSize());
    move(s.value(GUI::Style::S_WINDOW_POSITION, QPoint(500, 300)).toPoint());
    s.endGroup();
    m_project_manager->loadSettings();
}

void MainWindow::saveSettings()
{
    QSettings s;
    s.beginGroup(GUI::Style::S_MAIN_WINDOW);
    s.setValue(GUI::Style::S_WINDOW_SIZE, size());
    s.setValue(GUI::Style::S_WINDOW_POSITION, pos());
    s.endGroup();
    m_project_manager->saveSettings();
    gApp->saveSettings();
    s.sync();
}

void MainWindow::onDocumentOpenedOrClosed(bool open)
{
    updateTitle();
    m_central_widget->updateViews(open);
}

void MainWindow::onDocumentModified()
{
    updateTitle();
}

void MainWindow::loadProject(QString projectPath)
{
    m_project_manager->openProject(projectPath);
}
