//  ************************************************************************************************
//
//  BornAgain: simulate and fit reflection and scattering
//
//! @file      GUI/View/Fit/FitActivityPanel.cpp
//! @brief     Implements class FitActivityPanel.
//!
//! @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/Fit/FitActivityPanel.h"
#include "Base/Util/Assert.h"
#include "GUI/Model/Job/JobItem.h"
#include "GUI/View/Base/mainwindow_constants.h"
#include "GUI/View/Fit/FitSessionController.h"
#include "GUI/View/Fit/FitSessionManager.h"
#include "GUI/View/Fit/FitSessionWidget.h"
#include "GUI/View/FitControl/FitEditor.h"
#include "GUI/View/Tuning/JobRealTimeWidget.h"
#include "GUI/View/Tuning/ParameterTuningWidget.h"
#include <QSettings>
#include <QVBoxLayout>

FitActivityPanel::FitActivityPanel(QWidget* parent)
    : QWidget(parent)
    , m_stack(new QStackedWidget(this))
    , m_blank_widget(new QWidget(m_stack))
    , m_fit_session_widget(new FitSessionWidget(m_stack))
    , m_real_time_widget(nullptr)
    , m_fit_session_manager(new FitSessionManager(this))
{
    setWindowTitle(GUI::Style::JobFitPanelName);
    setObjectName("FitActivityPanel");
    setSizePolicy(QSizePolicy::Expanding, QSizePolicy::MinimumExpanding);

    auto* layout = new QVBoxLayout(this);
    layout->setContentsMargins(0, 0, 0, 0);
    layout->setSpacing(0);

    layout->addWidget(m_stack);

    m_stack->addWidget(m_blank_widget);

    m_nofit_label = new QLabel("Job has no real data linked to it for fitting.", m_stack);
    m_nofit_label->setAlignment(Qt::AlignCenter);
    m_stack->addWidget(m_nofit_label);

    m_stack->addWidget(m_fit_session_widget);

    setFixedSize(GUI::Style::FIT_ACTIVITY_PANEL_WIDTH, GUI::Style::FIT_ACTIVITY_PANEL_HEIGHT);
    applySettings();
}

FitActivityPanel::~FitActivityPanel()
{
    saveSettings();
}

void FitActivityPanel::setRealTimeWidget(JobRealTimeWidget* realTimeWidget)
{
    ASSERT(realTimeWidget);
    m_real_time_widget = realTimeWidget;
    connect(m_real_time_widget, &JobRealTimeWidget::widthChanged, this,
            &FitActivityPanel::adjustWidthToRealTimeWidget, Qt::UniqueConnection);
}

void FitActivityPanel::resizeEvent(QResizeEvent* event)
{
    QWidget::resizeEvent(event);
    setMinimumSize(0, 0);
    setMaximumSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
}

void FitActivityPanel::setJobItem(JobItem* jobItem)
{
    if (!isValidJobItem(jobItem)) {
        if (!jobItem)
            m_stack->setCurrentWidget(m_blank_widget);
        else
            m_stack->setCurrentWidget(m_nofit_label);
        emit showLog(nullptr);
        return;
    }

    m_stack->setCurrentWidget(m_fit_session_widget);
    m_fit_session_widget->setJobItem(jobItem);
    ParameterTuningWidget* paramTuner = m_real_time_widget->parameterTuningWidget();
    m_fit_session_widget->setModelTuningWidget(paramTuner);
    FitSessionController* controller = m_fit_session_manager->sessionController(jobItem);
    m_fit_session_widget->setSessionController(controller);
    emit showLog(controller->fitLog());

    connect(controller, &FitSessionController::fittingFinished, paramTuner,
            &ParameterTuningWidget::updateView, Qt::UniqueConnection);
}

bool FitActivityPanel::isValidJobItem(JobItem* item)
{
    return item ? item->isValidForFitting() : false;
}

void FitActivityPanel::adjustWidthToRealTimeWidget(int w)
{
    if (w != width()) {
        setFixedWidth(w);
        setMinimumSize(0, 0);
        setMaximumSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
    }
}

void FitActivityPanel::applySettings()
{
    QSettings settings;
    if (settings.childGroups().contains(GUI::Style::S_FIT_ACTIVITY_PANEL)) {
        settings.beginGroup(GUI::Style::S_FIT_ACTIVITY_PANEL);
        setFixedSize(settings.value(GUI::Style::S_FIT_ACTIVITY_PANEL_SIZE).toSize());
        settings.endGroup();
    }
}

void FitActivityPanel::saveSettings()
{
    QSettings settings;
    settings.beginGroup(GUI::Style::S_FIT_ACTIVITY_PANEL);
    settings.setValue(GUI::Style::S_FIT_ACTIVITY_PANEL_SIZE, size());
    settings.endGroup();
    settings.sync();
}
