// Copyright 2021 Filippo Rusconi
// GPL3+

#include "baseplotcontext.h"

namespace pappso
{

BasePlotContext::BasePlotContext()
{
}


BasePlotContext::BasePlotContext(const BasePlotContext &other)
{
  m_dataKind = other.m_dataKind;

  m_isMouseDragging  = other.m_isMouseDragging;
  m_wasMouseDragging = other.m_wasMouseDragging;

  m_isKeyBoardDragging            = other.m_isKeyBoardDragging;
  m_isLeftPseudoButtonKeyPressed  = other.m_isLeftPseudoButtonKeyPressed;
  m_isRightPseudoButtonKeyPressed = other.m_isRightPseudoButtonKeyPressed;
  m_wassKeyBoardDragging          = other.m_wassKeyBoardDragging;

  m_startDragPoint         = other.m_startDragPoint;
  m_currentDragPoint       = other.m_currentDragPoint;
  m_lastCursorHoveredPoint = other.m_lastCursorHoveredPoint;

  m_selectionPolygon     = other.m_selectionPolygon;
  m_selectRectangleWidth = other.m_selectRectangleWidth;

  // The effective range of the axes.
  m_xRange = other.m_xRange;
  m_yRange = other.m_yRange;

  // Tell if the mouse move was started onto either axis, because that will
  // condition if some calculations needs to be performed or not (for example,
  // if the mouse cursor motion was started on an axis, there is no point to
  // perform deconvolutions).
  m_wasClickOnXAxis = other.m_wasClickOnXAxis;
  m_wasClickOnYAxis = other.m_wasClickOnYAxis;

  m_isMeasuringDistance = other.m_isMeasuringDistance;

  // The user-selected region over the plot.
  // Note that we cannot use QCPRange structures because these are normalized by
  // QCustomPlot in such a manner that lower is actually < upper. But we need
  // for a number of our calculations (specifically for the deconvolutions) to
  // actually have the lower value be start drag point.x even if the drag
  // direction was from right to left.
  m_xRegionRangeStart = other.m_xRegionRangeStart;
  m_xRegionRangeEnd   = other.m_xRegionRangeEnd;

  m_yRegionRangeStart = other.m_yRegionRangeStart;
  m_yRegionRangeEnd   = other.m_yRegionRangeEnd;

  m_xDelta = other.m_xDelta;
  m_yDelta = other.m_yDelta;

  m_pressedKeyCode  = other.m_pressedKeyCode;
  m_releasedKeyCode = other.m_releasedKeyCode;

  m_keyboardModifiers = other.m_keyboardModifiers;

  m_lastPressedMouseButton  = other.m_lastPressedMouseButton;
  m_lastReleasedMouseButton = other.m_lastReleasedMouseButton;

  m_pressedMouseButtons = other.m_pressedMouseButtons;

  m_mouseButtonsAtMousePress   = other.m_mouseButtonsAtMousePress;
  m_mouseButtonsAtMouseRelease = other.m_mouseButtonsAtMouseRelease;
}


BasePlotContext &
BasePlotContext::operator=(const BasePlotContext &other)
{
  if(this == &other)
    return *this;

  m_dataKind = other.m_dataKind;

  m_isMouseDragging  = other.m_isMouseDragging;
  m_wasMouseDragging = other.m_wasMouseDragging;

  m_isKeyBoardDragging            = other.m_isKeyBoardDragging;
  m_isLeftPseudoButtonKeyPressed  = other.m_isLeftPseudoButtonKeyPressed;
  m_isRightPseudoButtonKeyPressed = other.m_isRightPseudoButtonKeyPressed;
  m_wassKeyBoardDragging          = other.m_wassKeyBoardDragging;

  m_startDragPoint         = other.m_startDragPoint;
  m_currentDragPoint       = other.m_currentDragPoint;
  m_lastCursorHoveredPoint = other.m_lastCursorHoveredPoint;

  m_selectionPolygon     = other.m_selectionPolygon;
  m_selectRectangleWidth = other.m_selectRectangleWidth;

  // The effective range of the axes.
  m_xRange = other.m_xRange;
  m_yRange = other.m_yRange;

  // Tell if the mouse move was started onto either axis, because that will
  // condition if some calculations needs to be performed or not (for example,
  // if the mouse cursor motion was started on an axis, there is no point to
  // perform deconvolutions).
  m_wasClickOnXAxis = other.m_wasClickOnXAxis;
  m_wasClickOnYAxis = other.m_wasClickOnYAxis;

  m_isMeasuringDistance = other.m_isMeasuringDistance;

  // The user-selected region over the plot.
  // Note that we cannot use QCPRange structures because these are normalized by
  // QCustomPlot in such a manner that lower is actually < upper. But we need
  // for a number of our calculations (specifically for the deconvolutions) to
  // actually have the lower value be start drag point.x even if the drag
  // direction was from right to left.
  m_xRegionRangeStart = other.m_xRegionRangeStart;
  m_xRegionRangeEnd   = other.m_xRegionRangeEnd;

  m_yRegionRangeStart = other.m_yRegionRangeStart;
  m_yRegionRangeEnd   = other.m_yRegionRangeEnd;

  m_xDelta = other.m_xDelta;
  m_yDelta = other.m_yDelta;

  m_pressedKeyCode  = other.m_pressedKeyCode;
  m_releasedKeyCode = other.m_releasedKeyCode;

  m_keyboardModifiers = other.m_keyboardModifiers;

  m_lastPressedMouseButton  = other.m_lastPressedMouseButton;
  m_lastReleasedMouseButton = other.m_lastReleasedMouseButton;

  m_pressedMouseButtons = other.m_pressedMouseButtons;

  m_mouseButtonsAtMousePress   = other.m_mouseButtonsAtMousePress;
  m_mouseButtonsAtMouseRelease = other.m_mouseButtonsAtMouseRelease;

  return *this;
}


BasePlotContext::~BasePlotContext()
{
}


DragDirections
BasePlotContext::recordDragDirections()
{
  int drag_directions = static_cast<int>(DragDirections::NOT_SET);

  if(m_currentDragPoint.x() > m_startDragPoint.x())
    drag_directions |= static_cast<int>(DragDirections::LEFT_TO_RIGHT);
  else
    drag_directions |= static_cast<int>(DragDirections::RIGHT_TO_LEFT);

  if(m_currentDragPoint.y() > m_startDragPoint.y())
    drag_directions |= static_cast<int>(DragDirections::BOTTOM_TO_TOP);
  else
    drag_directions |= static_cast<int>(DragDirections::TOP_TO_BOTTOM);

  //qDebug() << "DragDirections:" << drag_directions;

  m_dragDirections = static_cast<DragDirections>(drag_directions);

  return static_cast<DragDirections>(drag_directions);
}


QString
BasePlotContext::toString() const
{
  QString text("Context:");

  text += QString("data kind: %1").arg(static_cast<int>(m_dataKind));

  text += QString(" isMouseDragging: %1 -- wasMouseDragging: %2")
            .arg(m_isMouseDragging ? "true" : "false")
            .arg(m_wasMouseDragging ? "true" : "false");

  text += QString(" -- startDragPoint : (%1, %2)")
            .arg(m_startDragPoint.x())
            .arg(m_startDragPoint.y());

  text += QString(" -- currentDragPoint : (%1, %2)")
            .arg(m_currentDragPoint.x())
            .arg(m_currentDragPoint.y());

  text += QString(" -- lastCursorHoveredPoint : (%1, %2)")
            .arg(m_lastCursorHoveredPoint.x())
            .arg(m_lastCursorHoveredPoint.y());

  // Document how the mouse cursor is being dragged.
  if(m_isMouseDragging)
  {
    if(static_cast<int>(m_dragDirections) &  static_cast<int>(DragDirections::LEFT_TO_RIGHT))
        text += " -- dragging from left to right";
    else if(static_cast<int>(m_dragDirections) &  static_cast<int>(DragDirections::RIGHT_TO_LEFT))
        text += " -- dragging from right to left";
    if(static_cast<int>(m_dragDirections) &  static_cast<int>(DragDirections::TOP_TO_BOTTOM))
        text += " -- dragging from top to bottom";
    if(static_cast<int>(m_dragDirections) &  static_cast<int>(DragDirections::BOTTOM_TO_TOP))
        text += " -- dragging from bottom to top";
  }
 
  // The selection polygon.
  text += m_selectionPolygon.toString();

  text +=
    QString(" -- xRange: (%1, %2)").arg(m_xRange.lower).arg(m_xRange.upper);

  text +=
    QString(" -- yRange: (%1, %2)").arg(m_yRange.lower).arg(m_yRange.upper);

  text += QString(" -- wasClickOnXAxis: %1")
            .arg(m_wasClickOnXAxis ? "true" : "false");
  text += QString(" -- wasClickOnYAxis: %1")
            .arg(m_wasClickOnYAxis ? "true" : "false");
  text += QString(" -- isMeasuringDistance: %1")
            .arg(m_isMeasuringDistance ? "true" : "false");

  text += QString(" -- xRegionRangeStart: %1 -- xRegionRangeEnd: %2")
            .arg(m_xRegionRangeStart)
            .arg(m_xRegionRangeEnd);

  text += QString(" -- yRegionRangeStart: %1 -- yRegionRangeEnd: %2")
            .arg(m_yRegionRangeStart)
            .arg(m_yRegionRangeEnd);

  text += QString(" -- xDelta: %1 -- yDelta: %2").arg(m_xDelta).arg(m_yDelta);

  text += QString(" -- pressedKeyCode: %1").arg(m_pressedKeyCode);

  text += QString(" -- keyboardModifiers: %1").arg(m_keyboardModifiers);

  text +=
    QString(" -- lastPressedMouseButton: %1").arg(m_lastPressedMouseButton);

  text +=
    QString(" -- lastReleasedMouseButton: %1").arg(m_lastReleasedMouseButton);

  text += QString(" -- pressedMouseButtons: %1").arg(m_pressedMouseButtons);

  text +=
    QString(" -- mouseButtonsAtMousePress: %1").arg(m_mouseButtonsAtMousePress);

  text += QString(" -- mouseButtonsAtMouseRelease: %1")
            .arg(m_mouseButtonsAtMouseRelease);

  return text;
}


} // namespace pappso

