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

namespace {

const double bbox_margins = 5; // additional margins around rectangle to form bounding box

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

} // namespace


IRectangularOverlay::IRectangularOverlay(ColorMap* plot)
    : IMaskOverlay(plot)
    , m_active_handle_element(nullptr)
{
    setAcceptHoverEvents(true);

    for (SizeHandleElement::EHandleLocation point_type : points) {
        auto* el = new SizeHandleElement(point_type, this);
        connect(el, &SizeHandleElement::resize_request, this,
                &IRectangularOverlay::onSizeHandleElementRequest);
        el->setVisible(false);
        m_resize_handles[point_type] = el;
    }
}

//! triggered by SizeHandleElement
void IRectangularOverlay::onSizeHandleElementRequest(bool going_to_resize)
{
    if (going_to_resize) {
        setFlag(QGraphicsItem::ItemIsMovable, false);
        m_active_handle_element = qobject_cast<SizeHandleElement*>(sender());
        ASSERT(m_active_handle_element);
        SizeHandleElement::EHandleLocation oposite_corner =
            m_active_handle_element->getOppositeHandleLocation();
        m_resize_opposite_origin = m_resize_handles[oposite_corner]->scenePos();
    } else {
        setFlag(QGraphicsItem::ItemIsMovable, true);
        m_active_handle_element = nullptr;
    }
}

//! Track if item selected/deselected and show/hide size handles
QVariant IRectangularOverlay::itemChange(QGraphicsItem::GraphicsItemChange change,
                                         const QVariant& value)
{
    if (change == QGraphicsItem::ItemSelectedChange)
        for (auto it = m_resize_handles.begin(); it != m_resize_handles.end(); ++it)
            it.value()->setVisible(!this->isSelected());
    return value;
}

void IRectangularOverlay::mouseReleaseEvent(QGraphicsSceneMouseEvent* event)
{
    onSizeHandleElementRequest(false);
    QGraphicsObject::mouseReleaseEvent(event);
}

void IRectangularOverlay::update_view()
{
    prepareGeometryChange();
    update_bounding_rect();
    update_position();
}

//! updates view's bounding rectangle using item properties

void IRectangularOverlay::update_bounding_rect()
{
    if (parameterizedItem()) {
        m_mask_rect = mask_rectangle();
        if (is_true_mask())
            m_bounding_rect = m_mask_rect.marginsAdded(
                QMarginsF(bbox_margins, bbox_margins, bbox_margins, bbox_margins));
    }
    for (auto it = m_resize_handles.begin(); it != m_resize_handles.end(); ++it)
        it.value()->updateHandleElementPosition(m_mask_rect);
}
