//  ************************************************************************************************
//
//  BornAgain: simulate and fit reflection and scattering
//
//! @file      GUI/View/Instrument/InstrumentView.cpp
//! @brief     Implements class InstrumentView
//!
//! @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/Instrument/InstrumentView.h"
#include "GUI/Model/Item/InstrumentItems.h"
#include "GUI/Model/Model/InstrumentModel.h"
#include "GUI/Model/Project/ProjectDocument.h"
#include "GUI/View/Common/StyledToolBar.h"
#include "GUI/View/Instrument/DepthProbeInstrumentEditor.h"
#include "GUI/View/Instrument/GISASInstrumentEditor.h"
#include "GUI/View/Instrument/InstrumentListView.h"
#include "GUI/View/Instrument/OffSpecularInstrumentEditor.h"
#include "GUI/View/Instrument/SpecularInstrumentEditor.h"
#include <QBoxLayout>
#include <QFormLayout>
#include <QLabel>
#include <QLineEdit>
#include <QScrollArea>

InstrumentView::InstrumentView(QWidget* parent, ProjectDocument* document)
    : QWidget(parent)
    , m_document(document)
{
    auto* horizontalLayout = new QHBoxLayout;
    m_instrumentListView = new InstrumentListView(document, this);
    horizontalLayout->addWidget(m_instrumentListView);

    auto* rightVLayout = new QVBoxLayout;
    rightVLayout->setContentsMargins(0, 20, 0, 20);

    auto* formLayout = new QFormLayout;
    formLayout->setMargin(17);
    formLayout->setSpacing(8);
    rightVLayout->addLayout(formLayout);

    m_nameLineEdit = new QLineEdit(this);
    formLayout->addRow("Instrument name:", m_nameLineEdit);

    m_typeLabel = new QLabel(this);
    formLayout->addRow("Instrument type:", m_typeLabel);

    m_scrollArea = new QScrollArea(this);
    m_scrollArea->setWidgetResizable(true);
    m_scrollArea->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    rightVLayout->addWidget(m_scrollArea);
    horizontalLayout->addLayout(rightVLayout, 1);

    auto* toolbar = new StyledToolBar(this);
    toolbar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
    toolbar->addActions(m_instrumentListView->toolbarActions());

    auto* mainLayout = new QVBoxLayout;
    mainLayout->setMargin(0);
    mainLayout->setSpacing(0);
    mainLayout->addWidget(toolbar);
    mainLayout->addLayout(horizontalLayout);
    setLayout(mainLayout);

    createWidgetsForCurrentInstrument();

    connect(m_nameLineEdit, &QLineEdit::editingFinished, this,
            &InstrumentView::onInstrumentNameEditingFinished);

    connect(m_instrumentListView, &InstrumentListView::instrumentSelected, this,
            &InstrumentView::createWidgetsForCurrentInstrument);
}

void InstrumentView::createWidgetsForCurrentInstrument()
{
    auto* currentInstrument = m_instrumentListView->currentInstrument();

    if (currentInstrument) {
        m_nameLineEdit->setEnabled(true);
        m_nameLineEdit->setText(currentInstrument->instrumentName());
        m_typeLabel->setText(currentInstrument->instrumentType());
        if (auto* sp = dynamic_cast<SpecularInstrumentItem*>(currentInstrument)) {
            auto* editor = new SpecularInstrumentEditor(m_scrollArea, sp);
            connect(editor, &SpecularInstrumentEditor::dataChanged,
                    [=] { emit instrumentChanged(currentInstrument); });
            m_scrollArea->setWidget(editor);
        } else if (auto* os = dynamic_cast<OffSpecularInstrumentItem*>(currentInstrument)) {
            auto* editor = new OffSpecularInstrumentEditor(m_scrollArea, os);
            connect(editor, &OffSpecularInstrumentEditor::dataChanged,
                    [=] { emit instrumentChanged(currentInstrument); });
            m_scrollArea->setWidget(editor);
        } else if (auto* gisas = dynamic_cast<GISASInstrumentItem*>(currentInstrument)) {
            auto* editor = new GISASInstrumentEditor(m_scrollArea, gisas);
            connect(editor, &GISASInstrumentEditor::dataChanged,
                    [=] { emit instrumentChanged(currentInstrument); });
            m_scrollArea->setWidget(editor);
        } else if (auto* dp = dynamic_cast<DepthProbeInstrumentItem*>(currentInstrument)) {
            auto* editor = new DepthProbeInstrumentEditor(m_scrollArea, dp);
            connect(editor, &DepthProbeInstrumentEditor::dataChanged,
                    [=] { emit instrumentChanged(currentInstrument); });
            m_scrollArea->setWidget(editor);
        } else
            ASSERT(false);
    } else {
        m_scrollArea->setWidget(new QWidget(m_scrollArea)); // blank widget
        m_nameLineEdit->clear();
        m_nameLineEdit->setEnabled(false);
        m_typeLabel->clear();
    }
}

void InstrumentView::onInstrumentNameEditingFinished()
{
    auto* currentInstrument = m_instrumentListView->currentInstrument();
    auto newName = m_nameLineEdit->text();
    if (currentInstrument && currentInstrument->instrumentName() != newName) {
        currentInstrument->setInstrumentName(newName);
        emit instrumentChanged(currentInstrument);
    }
}