//  ************************************************************************************************
//
//  BornAgain: simulate and fit reflection and scattering
//
//! @file      GUI/View/Projection/IntensityDataProjectionsWidget.cpp
//! @brief     Defines class IntensityDataProjectionsWidget
//!
//! @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/Projection/IntensityDataProjectionsWidget.h"
#include "GUI/Model/Data/IntensityDataItem.h"
#include "GUI/Model/Data/ProjectionItems.h"
#include "GUI/View/Common/IntensityDataPropertyWidget.h"
#include "GUI/View/Projection/ProjectionsEditorActions.h"
#include "GUI/View/Projection/ProjectionsEditorCanvas.h"
#include "GUI/View/Projection/ProjectionsToolbar.h"
#include "GUI/View/Projection/ProjectionsWidget.h"
#include <QBoxLayout>
#include <QSplitter>

IntensityDataProjectionsWidget::IntensityDataProjectionsWidget(QWidget* parent)
    : DataAccessWidget(parent)
    , m_editorActions(new ProjectionsEditorActions(this))
    , m_toolbar(new ProjectionsToolbar(m_editorActions))
    , m_projectionsCanvas(new ProjectionsEditorCanvas)
    , m_projectionsWidget(new ProjectionsWidget)
    , m_propertyPanel(new IntensityDataPropertyWidget(this))
{
    auto* splitter = new QSplitter;
    splitter->setOrientation(Qt::Vertical);
    splitter->addWidget(m_projectionsCanvas);
    splitter->addWidget(m_projectionsWidget);

    auto* mainLayout = new QHBoxLayout(this);
    mainLayout->setContentsMargins(0, 0, 0, 0);
    mainLayout->setSpacing(0);
    mainLayout->setContentsMargins(0, 0, 0, 0);
    mainLayout->addWidget(splitter);
    mainLayout->addWidget(m_propertyPanel);

    m_toolbar->setOrientation(Qt::Vertical);
    m_toolbar->setStyleSheet("QToolBar{border-left:1px solid rgb(180,180,180);}");
    mainLayout->addWidget(m_toolbar);

    m_propertyPanel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Minimum);
    m_propertyPanel->setHidden(true);
    setup_connections();
}

void IntensityDataProjectionsWidget::setJobOrRealItem(QObject* job_or_real_item)
{
    DataAccessWidget::setJobOrRealItem(job_or_real_item);
    m_propertyPanel->setJobOrRealItem(job_or_real_item);
    setContext();
}

void IntensityDataProjectionsWidget::setContext()
{
    ASSERT(currentIntensityDataItem());

    // The following line must come before 'm_projectionsCanvas->setContext()'!
    // It prevents problem with switching between datasets in projection mode.
    m_projectionsWidget->disconnectItem();

    m_projectionsCanvas->setContext(currentIntensityDataItem());
    m_projectionsWidget->setIntensityItem(currentIntensityDataItem());

    m_editorActions->setContext(currentIntensityDataItem());
}

void IntensityDataProjectionsWidget::resetContext()
{
    m_projectionsCanvas->resetContext();
    m_projectionsWidget->disconnectItem();
    m_projectionsWidget->setIntensityItem(nullptr);
}

void IntensityDataProjectionsWidget::showEvent(QShowEvent*)
{
    if (currentIntensityDataItem())
        setContext();
}

void IntensityDataProjectionsWidget::hideEvent(QHideEvent*)
{
    resetContext();
}

QList<QAction*> IntensityDataProjectionsWidget::actionList()
{
    return m_editorActions->topToolbarActions();
}

void IntensityDataProjectionsWidget::setup_connections()
{
    // tool panel request is propagated from editorActions to this MaskEditor
    connect(m_editorActions, &ProjectionsEditorActions::resetViewRequest, m_projectionsCanvas,
            &ProjectionsEditorCanvas::onResetViewRequest, Qt::UniqueConnection);

    // tool panel request is propagated from editorActions to this MaskEditor
    connect(m_editorActions, &ProjectionsEditorActions::propertyPanelRequest,
            [this]() { m_propertyPanel->setHidden(!m_propertyPanel->isHidden()); });

    // selection/drawing activity is propagated from Toolbar to graphics scene
    connect(m_toolbar, &ProjectionsToolbar::activityModeChanged, m_projectionsCanvas,
            &ProjectionsEditorCanvas::onActivityModeChanged, Qt::UniqueConnection);

    // selection/drawing activity is propagated from Toolbar to Projections Widget
    connect(m_toolbar, &ProjectionsToolbar::activityModeChanged, m_projectionsWidget,
            &ProjectionsWidget::onActivityModeChanged, Qt::UniqueConnection);

    // click on projections tab is propagated to tool bar
    connect(m_projectionsWidget, &ProjectionsWidget::changeActivityRequest, m_toolbar,
            &ProjectionsToolbar::onProjectionTabChange, Qt::UniqueConnection);

    // Delete request is propagated from canvas to actions
    connect(m_projectionsCanvas, &ProjectionsEditorCanvas::deleteSelectedRequest, m_editorActions,
            &ProjectionsEditorActions::onDeleteAction, Qt::UniqueConnection);

    // moving projection automatically switches projections tab
    connect(m_projectionsCanvas, &ProjectionsEditorCanvas::changeProjectionsTabRequest,
            m_projectionsWidget, &ProjectionsWidget::onActivityModeChanged, Qt::UniqueConnection);

    // space bar push (request for zoom mode) is propagated from graphics view to Toolbar
    connect(m_projectionsCanvas, &ProjectionsEditorCanvas::changeActivityRequest, m_toolbar,
            &ProjectionsToolbar::onChangeActivityRequest, Qt::UniqueConnection);

    // ColorMap margins changed, canvas -> projection widget
    connect(m_projectionsCanvas, &ProjectionsEditorCanvas::marginsChanged, m_projectionsWidget,
            &ProjectionsWidget::onMarginsChanged, Qt::UniqueConnection);

    m_toolbar->onChangeActivityRequest(MaskEditorFlags::HORIZONTAL_LINE_MODE);
}
