//  ************************************************************************************************
//
//  BornAgain: simulate and fit reflection and scattering
//
//! @file      GUI/View/Overlay/LineOverlays.cpp
//! @brief     Implements classes VerticalLineOverlay and HorizontalLineOverlay.
//!
//! @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/Overlay/LineOverlays.h"
#include "GUI/Model/Mask/MaskItems.h"
#include "GUI/View/Overlay/OverlayStyle.h"
#include "GUI/View/Overlay/Viewport.h"
#include "GUI/View/Plotter/ColorMap.h"
#include <QCursor>
#include <QPainter>
#include <QStyleOptionGraphicsItem>

namespace {

const double mask_width = 8.0;
const double mask_visible_width = 3.0;

} // namespace

LineOverlay::LineOverlay(LineItem* item, ColorMap* plot, bool is_projection)
    : IMaskOverlay(plot)
    , m_item(item)
    , m_is_projection(is_projection)
{
}

void LineOverlay::paint(QPainter* painter, const QStyleOptionGraphicsItem*, QWidget*)
{
    bool mask_value = m_item->maskValue();
    if (m_is_projection) {
        painter->setBrush(GUI::Overlay::getProjectionBrush());
        painter->setPen(GUI::Overlay::getProjectionPen());
    } else {
        painter->setBrush(GUI::Overlay::getMaskBrush(mask_value));
        painter->setPen(GUI::Overlay::getMaskPen(mask_value));
    }
    painter->drawRect(rectangle());

    if (isSelected()) {
        QPen pen;
        pen.setStyle(Qt::DashLine);
        painter->setPen(pen);
        painter->setBrush(Qt::NoBrush);
        painter->drawRect(rectangle());
    }
}

QPainterPath LineOverlay::shape() const
{
    QPainterPath path;
    path.addRect(rectangle());
    return path;
}

OverlayItem* LineOverlay::parameterizedItem() const
{
    return m_item;
}

// --------------------------------------------------------------------------------------------- //

HorizontalLineOverlay::HorizontalLineOverlay(LineItem* item, ColorMap* plot, bool is_projection)
    : LineOverlay(item, plot, is_projection)
{
}

QRectF HorizontalLineOverlay::rectangle() const
{
    return {0., -mask_visible_width / 2., m_bounding_rect.width(), mask_visible_width};
}

void HorizontalLineOverlay::onChangedY()
{
    setBlockOnProperty(true);
    m_item->setPos(y2coo(this->y()));
    setBlockOnProperty(false);
}

void HorizontalLineOverlay::onPropertyChange()
{
    setY(y2pix(m_item->pos().dVal()));
}

void HorizontalLineOverlay::update_view()
{
    QRectF plot_scene_rectangle = GUI::Util::viewportRectangle(m_plot);

    setX(plot_scene_rectangle.left());
    setY(y2pix(m_item->pos().dVal()));

    m_bounding_rect = QRectF(0.0, -mask_width / 2., plot_scene_rectangle.width(), mask_width);
    update();
}

//! Allows item movement along y, prevent movement along x
QVariant HorizontalLineOverlay::itemChange(QGraphicsItem::GraphicsItemChange change,
                                           const QVariant& value)
{
    if (isSelected() && change == ItemPositionChange && scene()) {
        QPointF newPos = value.toPointF();
        newPos.setX(x());
        return newPos;
    }
    return QGraphicsItem::itemChange(change, value);
}

// --------------------------------------------------------------------------------------------- //

VerticalLineOverlay::VerticalLineOverlay(LineItem* item, ColorMap* plot, bool is_projection)
    : LineOverlay(item, plot, is_projection)
{
}

QRectF VerticalLineOverlay::rectangle() const
{
    return {-mask_visible_width / 2., 0.0, mask_visible_width, m_bounding_rect.height()};
}

void VerticalLineOverlay::onChangedX()
{
    setBlockOnProperty(true);
    m_item->setPos(x2coo(this->x()));
    setBlockOnProperty(false);
}

void VerticalLineOverlay::onPropertyChange()
{
    setX(x2pix(m_item->pos().dVal()));
}

void VerticalLineOverlay::update_view()
{
    QRectF plot_scene_rectangle = GUI::Util::viewportRectangle(m_plot);

    setX(x2pix(m_item->pos().dVal()));
    setY(plot_scene_rectangle.top());

    m_bounding_rect = QRectF(-mask_width / 2., 0.0, mask_width, plot_scene_rectangle.height());
    update();
}

//! Allows item movement along x, prevent movement along y
QVariant VerticalLineOverlay::itemChange(QGraphicsItem::GraphicsItemChange change,
                                         const QVariant& value)
{
    if (isSelected() && change == ItemPositionChange && scene()) {
        QPointF newPos = value.toPointF();
        newPos.setY(y());
        return newPos;
    }
    return QGraphicsItem::itemChange(change, value);
}
