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

#include "GUI/View/Import/RealDataPropertiesWidget.h"
#include "GUI/Model/Device/InstrumentItems.h"
#include "GUI/Model/Device/RealItem.h"
#include "GUI/Model/Project/ProjectDocument.h"
#include "GUI/View/Tool/Globals.h"
#include <QComboBox>
#include <QLabel>
#include <QVBoxLayout>

RealDataPropertiesWidget::RealDataPropertiesWidget(QWidget* parent, ProjectDocument* document)
    : QWidget(parent)
    , m_instrumentCombo(new QComboBox)
    , m_currentRealItem(nullptr)
    , m_document(document)
{
    setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
    setWindowTitle("RealDataPropertiesWidget");

    auto* mainLayout = new QVBoxLayout;
    mainLayout->setContentsMargins(5, 5, 5, 5);
    mainLayout->setSpacing(2);

    m_instrumentCombo->setToolTip("Select instrument to link with real data");

    mainLayout->addWidget(new QLabel("Linked instrument"));
    mainLayout->addWidget(m_instrumentCombo);

    mainLayout->addStretch();
    setLayout(mainLayout);

    updateInstrumentComboEntries();
    setEnabled(false);

    connect(m_instrumentCombo,
            static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this,
            &RealDataPropertiesWidget::onInstrumentComboIndexChanged);

    connect(m_document->multiNotifier(), &MultiInstrumentNotifier::instrumentAddedOrRemoved, this,
            &RealDataPropertiesWidget::updateInstrumentComboEntries);

    connect(m_document->multiNotifier(), &MultiInstrumentNotifier::instrumentNameChanged, this,
            &RealDataPropertiesWidget::updateInstrumentComboEntries);

    connect(m_document->linkInstrumentManager(), &LinkInstrumentManager::linkToInstrumentChanged,
            this, &RealDataPropertiesWidget::updateInstrumentComboIndex);
}

void RealDataPropertiesWidget::setRealItem(RealItem* realItem)
{
    m_currentRealItem = realItem;
    updateInstrumentComboIndex();
    setEnabled(m_currentRealItem != nullptr);
}

void RealDataPropertiesWidget::onInstrumentComboIndexChanged(int /*index*/)
{
    if (!m_currentRealItem)
        return;

    const QString newSelectedInstrumentId = m_instrumentCombo->currentData().toString();

    if (newSelectedInstrumentId == m_currentRealItem->instrumentId())
        return;

    if (m_document->linkInstrumentManager()->canLinkDataToInstrument(
            m_currentRealItem, newSelectedInstrumentId, GUI::Global::mainWindow)) {
        const auto* newSelectedInstrument =
            m_document->instrumentModel()->findInstrumentItemById(newSelectedInstrumentId);
        m_currentRealItem->linkToInstrument(newSelectedInstrument);
        m_document->setModified();
    }

    // If linking was impossible or denied --> set combo to previous state.
    // Otherwise keep combobox updated to the current data after unlinking other data
    updateInstrumentComboIndex();

    emit instrumentUpdated(m_currentRealItem);
}

//! Updates instrument selector for new instruments and their names.
//! Current selection will be preserved.

void RealDataPropertiesWidget::updateInstrumentComboEntries()
{
    QSignalBlocker b(m_instrumentCombo);

    m_instrumentCombo->clear();

    // fill the combo. Userdata contains instrument's uid
    m_instrumentCombo->addItem("Undefined", ""); // undefined instrument
    for (auto* instrumentItem : m_document->instrumentModel()->instrumentItems())
        m_instrumentCombo->addItem(instrumentItem->instrumentName(), instrumentItem->id());

    updateInstrumentComboIndex();

    emit instrumentUpdated(m_currentRealItem);
}

//! Sets instrument combo selector to the state corresponding to given instrument identifier.

void RealDataPropertiesWidget::updateInstrumentComboIndex()
{
    const QString instrumentId =
        m_currentRealItem != nullptr ? m_currentRealItem->instrumentId() : "";

    QSignalBlocker b(m_instrumentCombo);
    m_instrumentCombo->setCurrentIndex(m_instrumentCombo->findData(instrumentId));
}
