// Copyright 2021 Filippo Rusconi
// GPLv3+


/////////////////////// StdLib includes
#include <limits>
#include <cmath>


/////////////////////// Qt includes
#include <QDebug>


/////////////////////// Local includes
#include "integrationscope.h"


namespace pappso
{

IntegrationScope::IntegrationScope(QObject *parent_p)
    : IntegrationScopeBase(parent_p)
{
  // qDebug() << "Constructing" << this;
}

IntegrationScope::IntegrationScope(const QPointF &point, double width, QObject *parent_p)
    : IntegrationScopeBase(parent_p)
    , m_point(point)
    , m_width(width)
{
  // qDebug() << "Constructing" << this << "point:" << point << "width:" << width;
}

IntegrationScope::IntegrationScope(const QPointF &point,
                                   double width,
                                   Enums::DataKind data_kind,
                                   QObject *parent_p)
    : IntegrationScopeBase(parent_p)
    , m_point(point)
    , m_width(width)
    , m_dataKindX(data_kind)
{
  // qDebug() << "Constructing" << this << "point:" << point << "width:" << width;
}

IntegrationScope::IntegrationScope(const IntegrationScope &other, QObject *parent_p)
    : IntegrationScopeBase(parent_p)
    , m_point(other.m_point)
    , m_width(other.m_width)
    , m_dataKindX(other.m_dataKindX)
{
  // qDebug() << "Constructing" << this << "point:" << point << "width:" << width;
}

IntegrationScope::~IntegrationScope()
{
  // qDebug() << "Destructing" << this;
}

IntegrationScope &
IntegrationScope::operator=(const IntegrationScope &other)
{

  if(this == &other)
    return *this;

  m_point = other.m_point;
  m_width = other.m_width;

  return *this;
}

void
IntegrationScope::setPoint(const QPointF &point)
{
  m_point = point;
}

bool
IntegrationScope::getPoint(QPointF &point) const
{
  point = m_point;
  return true;
}

IntegrationScopeFeatures
IntegrationScope::getLeftMostPoint(QPointF &point) const
{
  point = m_point;
  return IntegrationScopeFeatures::SUCCESS;
}

IntegrationScopeFeatures
IntegrationScope::getRightMostPoint(QPointF &point) const
{
  point = QPointF(m_point.x() + m_width, m_point.y());
  return IntegrationScopeFeatures::SUCCESS;
}

IntegrationScopeFeatures
IntegrationScope::getTopMostPoint(QPointF &point) const
{
  point = m_point;
  return IntegrationScopeFeatures::SUCCESS;
}

IntegrationScopeFeatures
IntegrationScope::getBottomMostPoint(QPointF &point) const
{
  point = m_point;
  return IntegrationScopeFeatures::SUCCESS;
}

void
IntegrationScope::setWidth(double width)
{
  m_width = width;
}

IntegrationScopeFeatures
IntegrationScope::getWidth(double &width) const
{
  width = m_width;
  return IntegrationScopeFeatures::SUCCESS;
}

bool
IntegrationScope::range(Enums::Axis axis, double &start, double &end) const
{
  if(axis == Enums::Axis::x)
    {
      start = m_point.x();
      end   = start + m_width;

      return true;
    }

  return false;
}

void
IntegrationScope::setDataKindX([[maybe_unused]] Enums::DataKind data_kind)
{
  m_dataKindX = data_kind;
}

bool
IntegrationScope::getDataKindX([[maybe_unused]] Enums::DataKind &data_kind)
{
  data_kind = m_dataKindX;
  return true;
}

bool
IntegrationScope::is1D() const
{
  return true;
}

bool
IntegrationScope::is2D() const
{
  return !is1D();
}

bool
IntegrationScope::isRectangle() const
{
  return false;
}

bool
IntegrationScope::isRhomboid() const
{
  return false;
}

bool
IntegrationScope::transpose()
{
  return false;
}

void
IntegrationScope::update(const QPointF &point, double width)
{
  m_point = point;
  m_width = width;
}

bool
IntegrationScope::contains(const QPointF &point) const
{
  return (point.x() >= m_point.x() && point.x() <= m_point.x() + m_width);
}

QString
IntegrationScope::toString() const
{
  return QString("(%1, %2)").arg(m_point.x(), 0, 'f', 3).arg(m_point.x() + m_width, 0, 'f', 3);
}

void
IntegrationScope::reset()
{
  m_point.rx() = 0;
  m_point.ry() = 0;

  m_width = 0;
}

} // namespace pappso
