//  ************************************************************************************************
//
//  BornAgain: simulate and fit reflection and scattering
//
//! @file      GUI/View/Overlay/SizeHandleElement.cpp
//! @brief     Implements class SizeHandleElement.
//!
//! @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/SizeHandleElement.h"
#include "GUI/View/Overlay/OverlayStyle.h"
#include <QCursor>
#include <QGraphicsSceneHoverEvent>
#include <QPainter>

namespace {

const QMap<SizeHandleElement::EHandleLocation, SizeHandleElement::EHandleType> location_to_type{
    {SizeHandleElement::NONE, SizeHandleElement::RESIZE},
    {SizeHandleElement::TOPLEFT, SizeHandleElement::RESIZE},
    {SizeHandleElement::TOPMIDDLE, SizeHandleElement::RESIZE_HEIGHT},
    {SizeHandleElement::TOPRIGHT, SizeHandleElement::RESIZE},
    {SizeHandleElement::MIDDLERIGHT, SizeHandleElement::RESIZE_WIDTH},
    {SizeHandleElement::BOTTOMRIGHT, SizeHandleElement::RESIZE},
    {SizeHandleElement::BOTTOMMIDLE, SizeHandleElement::RESIZE_HEIGHT},
    {SizeHandleElement::BOTTOMLEFT, SizeHandleElement::RESIZE},
    {SizeHandleElement::MIDDLELEFT, SizeHandleElement::RESIZE_WIDTH},
};

const QMap<SizeHandleElement::EHandleLocation, Qt::CursorShape> location_to_cursor{
    {SizeHandleElement::NONE, Qt::ArrowCursor},
    {SizeHandleElement::TOPLEFT, Qt::SizeFDiagCursor},
    {SizeHandleElement::TOPMIDDLE, Qt::SizeVerCursor},
    {SizeHandleElement::TOPRIGHT, Qt::SizeBDiagCursor},
    {SizeHandleElement::MIDDLERIGHT, Qt::SizeHorCursor},
    {SizeHandleElement::BOTTOMRIGHT, Qt::SizeFDiagCursor},
    {SizeHandleElement::BOTTOMMIDLE, Qt::SizeVerCursor},
    {SizeHandleElement::BOTTOMLEFT, Qt::SizeBDiagCursor},
    {SizeHandleElement::MIDDLELEFT, Qt::SizeHorCursor},
};

const QMap<SizeHandleElement::EHandleLocation, SizeHandleElement::EHandleLocation>
    opposite_location{
        {SizeHandleElement::TOPLEFT, SizeHandleElement::BOTTOMRIGHT},
        {SizeHandleElement::TOPMIDDLE, SizeHandleElement::BOTTOMMIDLE},
        {SizeHandleElement::TOPRIGHT, SizeHandleElement::BOTTOMLEFT},
        {SizeHandleElement::MIDDLERIGHT, SizeHandleElement::MIDDLELEFT},
        {SizeHandleElement::BOTTOMRIGHT, SizeHandleElement::TOPLEFT},
        {SizeHandleElement::BOTTOMMIDLE, SizeHandleElement::TOPMIDDLE},
        {SizeHandleElement::BOTTOMLEFT, SizeHandleElement::TOPRIGHT},
        {SizeHandleElement::MIDDLELEFT, SizeHandleElement::MIDDLERIGHT},
    };

} // namespace


SizeHandleElement::SizeHandleElement(EHandleLocation pointType, QGraphicsObject* parent)
    : QGraphicsObject(parent)
    , m_handle_location(pointType)
    , m_handle_type(location_to_type[pointType])
{
    setCursor(location_to_cursor[m_handle_location]);
    setParentItem(parent);
}

QRectF SizeHandleElement::boundingRect() const
{
    return {-4, -4, 8, 8};
}

void SizeHandleElement::paint(QPainter* painter, const QStyleOptionGraphicsItem*, QWidget*)
{
    painter->setRenderHints(QPainter::Antialiasing);
    painter->setBrush(GUI::Overlay::getSelectionMarkerBrush());
    painter->setPen(GUI::Overlay::getSelectionMarkerPen());
    if (getHandleType() == RESIZE)
        painter->drawRect(boundingRect());
    else
        painter->drawEllipse(boundingRect());
}

void SizeHandleElement::mousePressEvent(QGraphicsSceneMouseEvent* event)
{
    emit resize_request(true);
    QGraphicsObject::mousePressEvent(event);
}

void SizeHandleElement::mouseReleaseEvent(QGraphicsSceneMouseEvent* event)
{
    emit resize_request(false);
    QGraphicsObject::mouseReleaseEvent(event);
}

//! set position from location type using coordinates of external rectangle
void SizeHandleElement::updateHandleElementPosition(const QRectF& rect)
{
    if (m_handle_location == TOPLEFT)
        setPos(rect.topLeft());

    else if (m_handle_location == TOPMIDDLE)
        setPos(QPointF(rect.x() + rect.width() / 2., rect.y()));

    else if (m_handle_location == TOPRIGHT)
        setPos(rect.topRight());

    else if (m_handle_location == MIDDLERIGHT)
        setPos(QPointF(rect.x() + rect.width(), rect.y() + rect.height() / 2.));

    else if (m_handle_location == BOTTOMRIGHT)
        setPos(rect.bottomRight());

    else if (m_handle_location == BOTTOMMIDLE)
        setPos(QPointF(rect.x() + rect.width() / 2., rect.y() + rect.height()));

    else if (m_handle_location == BOTTOMLEFT)
        setPos(rect.bottomLeft());

    else if (m_handle_location == MIDDLELEFT)
        setPos(QPointF(rect.x(), rect.y() + rect.height() / 2.));
}

SizeHandleElement::EHandleLocation SizeHandleElement::getOppositeHandleLocation() const
{
    return opposite_location[m_handle_location];
}

void SizeHandleElement::update_view()
{
    update();
}
