//  ************************************************************************************************
//
//  BornAgain: simulate and fit reflection and scattering
//
//! @file      GUI/View/Overlay/EllipseOverlay.cpp
//! @brief     Implements class EllipseOverlay.
//!
//! @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/EllipseOverlay.h"
#include "GUI/Model/Mask/MaskItems.h"
#include "GUI/View/Plotter/ColorMap.h"
#include <QGraphicsSceneMouseEvent>

EllipseOverlay::EllipseOverlay(EllipseItem* item, ColorMap* plot)
    : IRectangularOverlay(plot)
    , m_item(item)
{
    m_item->maskVisibilityChanged();
}

void EllipseOverlay::onChangedX()
{
    setBlockOnProperty(true);
    m_item->setXCenter(m_plot->fromSceneX(this->x()));
    setBlockOnProperty(false);
}

void EllipseOverlay::onChangedY()
{
    setBlockOnProperty(true);
    m_item->setYCenter(m_plot->fromSceneY(this->y()));
    setBlockOnProperty(false);
}

void EllipseOverlay::onPropertyChange()
{
    update_view();
    setX(m_plot->toSceneX(m_item->xCenter()));
    setY(m_plot->toSceneY(m_item->yCenter()));
    setTransform(QTransform().rotate(-1.0 * m_item->angle()));
}

void EllipseOverlay::mouseMoveEvent(QGraphicsSceneMouseEvent* event)
{
    if (m_active_handle_element) {
        QPointF opposPos = mapFromScene(m_resize_opposite_origin);
        qreal xmin = std::min(event->pos().x(), opposPos.x());
        qreal xmax = std::max(event->pos().x(), opposPos.x());
        qreal ymin = std::min(event->pos().y(), opposPos.y());
        qreal ymax = std::max(event->pos().y(), opposPos.y());
        qreal width = xmax - xmin;
        qreal height = ymax - ymin;

        qreal xcenter = xmin + (xmax - xmin) / 2.;
        qreal ycenter = ymin + (ymax - ymin) / 2.;

        QPointF center(xcenter, ycenter);
        QPointF centerInScene = mapToScene(center);

        if (m_active_handle_element->getHandleType() == SizeHandleElement::RESIZE) {
            m_item->setXCenter(m_plot->fromSceneX(centerInScene.x()));
            m_item->setYCenter(m_plot->fromSceneY(centerInScene.y()));

            m_item->setXRadius((m_plot->fromSceneX(centerInScene.x() + width / 2.)
                                - m_plot->fromSceneX(centerInScene.x() - width / 2.))
                               / 2.);
            m_item->setYRadius((m_plot->fromSceneY(centerInScene.y() - height / 2.)
                                - m_plot->fromSceneY(centerInScene.y() + height / 2.))
                               / 2.);
        } else if (m_active_handle_element->getHandleType() == SizeHandleElement::RESIZE_HEIGHT) {
            m_item->setYCenter(m_plot->fromSceneY(centerInScene.y()));
            m_item->setYRadius((m_plot->fromSceneY(centerInScene.y() - height / 2.)
                                - m_plot->fromSceneY(centerInScene.y() + height / 2.))
                               / 2.);
        } else if (m_active_handle_element->getHandleType() == SizeHandleElement::RESIZE_WIDTH) {
            m_item->setXCenter(m_plot->fromSceneX(centerInScene.x()));
            m_item->setXRadius((m_plot->fromSceneX(centerInScene.x() + width / 2.)
                                - m_plot->fromSceneX(centerInScene.x() - width / 2.))
                               / 2.);
        }
    } else {
        QGraphicsObject::mouseMoveEvent(event);
    }
}

QPainterPath EllipseOverlay::shape() const
{
    QPainterPath path;
    path.addEllipse(m_mask_rect);
    return path;
}

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

//! updates position of view using item properties

void EllipseOverlay::update_position()
{
    disconnect(this, &EllipseOverlay::xChanged, this, &EllipseOverlay::onChangedX);
    disconnect(this, &EllipseOverlay::yChanged, this, &EllipseOverlay::onChangedY);

    setX(m_plot->toSceneX(m_item->xCenter()));
    setY(m_plot->toSceneY(m_item->yCenter()));

    connect(this, &EllipseOverlay::xChanged, this, &EllipseOverlay::onChangedX);
    connect(this, &EllipseOverlay::yChanged, this, &EllipseOverlay::onChangedY);

    if (m_item->angle() != 0)
        setTransform(QTransform().rotate(-1 * m_item->angle()));
}

QRectF EllipseOverlay::mask_rectangle()
{
    return QRectF(-width() / 2, -height() / 2, width(), height());
}

qreal EllipseOverlay::width() const
{
    return m_plot->toSceneX(m_item->xCenter() + m_item->xRadius())
           - m_plot->toSceneX(m_item->xCenter() - m_item->xRadius());
}

qreal EllipseOverlay::height() const
{
    return m_plot->toSceneY(m_item->yCenter() - m_item->yRadius())
           - m_plot->toSceneY(m_item->yCenter() + m_item->yRadius());
}
