//  ************************************************************************************************
//
//  BornAgain: simulate and fit reflection and scattering
//
//! @file      GUI/View/Widget/ItemComboWidget.cpp
//! @brief     Implements class ItemComboWidget
//!
//! @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/Widget/ItemComboWidget.h"
#include "Base/Util/Assert.h"
#include "GUI/View/Widget/ItemComboToolbar.h"
#include <QVBoxLayout>

ItemComboWidget::ItemComboWidget(QWidget* parent)
    : DataAccessWidget(parent)
    , m_toolbar(new ItemComboToolbar)
    , m_stackedWidget(new QStackedWidget)
{
    setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    m_stackedWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    m_blankWidget = new QWidget;
    m_stackedWidget->addWidget(m_blankWidget);

    auto* layout = new QVBoxLayout;
    layout->setContentsMargins(0, 0, 0, 0);
    layout->setSpacing(0);
    layout->setContentsMargins(0, 0, 0, 0);
    layout->addWidget(m_toolbar);
    layout->addWidget(m_stackedWidget);
    setLayout(layout);

    connect(m_toolbar, &ItemComboToolbar::comboChanged, this, &ItemComboWidget::onComboChanged);

    setToolbarVisible(false);
}

void ItemComboWidget::registerWidget(const QString& presentationType, factory_function_t f)
{
    m_widgetFactory.registerItem(presentationType, f);
}

//! Sets stack to show widget corresponding to given presentation
void ItemComboWidget::setPresentation(const QString& presentationType)
{
    if (presentationType.isEmpty()) {
        m_stackedWidget->setCurrentWidget(m_blankWidget);
        setToolbarVisible(false);
        return;
    }

    if (!activePresentationList().contains(presentationType))
        return;

    setToolbarVisible(true);
    m_toolbar->setPresentation(presentationType);

    ASSERT(jobRealBase());

    DataAccessWidget* widget = m_presentationTypeToWidget[presentationType];

    if (!widget) {
        widget = m_widgetFactory.createItemPtr(presentationType).release();
        m_stackedWidget->addWidget(widget);
        m_presentationTypeToWidget[presentationType] = widget;
    }
    ASSERT(widget);
    widget->setJobOrRealItem(jobRealBase());
    m_toolbar->setActionList(widget->actionList());
    m_stackedWidget->setCurrentWidget(widget);
    if (widget->isHidden())
        widget->show();

    setSizeToCurrentWidget();
}

void ItemComboWidget::setToolbarVisible(bool value)
{
    m_toolbar->setVisible(value);
}

void ItemComboWidget::setJobOrRealItem(QObject* job_or_real_item)
{
    if (!job_or_real_item) {
        m_stackedWidget->setCurrentWidget(m_blankWidget);
        return;
    }

    DataAccessWidget::setJobOrRealItem(job_or_real_item);
    setToolbarVisible(!itemPresentation().isEmpty());
    m_toolbar->setPresentationList(presentationList(), activePresentationList());
    setPresentation(itemPresentation());
}

//! Returns list of active presentations. Active presentation is the one
//! which is present in QComboBox selector and can be selected. For example, if JobItem
//! is fittable, the list will contain "FitComparisonWidgetName".

QStringList ItemComboWidget::activePresentationList() const
{
    return QStringList();
}

//! Returns full list of presentations available for given item.

QStringList ItemComboWidget::presentationList() const
{
    return activePresentationList();
}

//! Presentation which should be shown for current item.

QString ItemComboWidget::itemPresentation() const
{
    if (activePresentationList().size())
        return activePresentationList().first();

    return selectedPresentation();
}

//! Presentation selected in combo selector.

QString ItemComboWidget::selectedPresentation() const
{
    return m_toolbar->currentPresentation();
}

void ItemComboWidget::onComboChanged(const QString&)
{
    setPresentation(selectedPresentation());
}

//! Resizes QStackedWidget to currently active page.

void ItemComboWidget::setSizeToCurrentWidget()
{
    for (int i = 0; i < m_stackedWidget->count(); ++i) {
        // determine the vertical size policy
        QSizePolicy::Policy policy = QSizePolicy::Ignored;
        if (i == m_stackedWidget->currentIndex())
            policy = QSizePolicy::Expanding;

        // update the size policy
        auto* page = m_stackedWidget->widget(i);
        page->setSizePolicy(policy, policy);
    }
}
