//  ************************************************************************************************
//
//  BornAgain: simulate and fit reflection and scattering
//
//! @file      GUI/View/PlotUtil/RangeUtil.cpp
//! @brief     Implements RangeUtil namespace
//!
//! @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/PlotUtil/RangeUtil.h"
#include "GUI/Model/Axis/AmplitudeAxisItem.h"
#include "GUI/Model/Data/IntensityDataItem.h"
#include "GUI/Model/Data/SpecularDataItem.h"
#include "GUI/Support/Util/Style.h"
#include <qcustomplot.h>

QCPRange GUI::View::RangeUtil::itemZoomX(const IntensityDataItem* item)
{
    return QCPRange(item->lowerX(), item->upperX());
}

QCPRange GUI::View::RangeUtil::itemZoomY(const IntensityDataItem* item)
{
    return QCPRange(item->lowerY(), item->upperY());
}

QCPRange GUI::View::RangeUtil::itemDataRange(const IntensityDataItem* item)
{
    QPair<double, double> range = item->dataRange();
    return QCPRange(range.first, range.second);
}

QCPRange GUI::View::RangeUtil::itemDataZoom(const IntensityDataItem* item)
{
    return QCPRange(item->lowerZ(), item->upperZ());
}

QList<AmplitudeAxisItem*>
GUI::View::RangeUtil::valueAxesFromSpecularItems(const QList<SpecularDataItem*>& items)
{
    QList<AmplitudeAxisItem*> axes;
    for (auto item : items)
        axes.append(item->yAxisItem());
    return axes;
}

QList<AmplitudeAxisItem*>
GUI::View::RangeUtil::valueAxesFromIntensityItems(const QList<IntensityDataItem*>& items)
{
    QList<AmplitudeAxisItem*> axes;
    for (auto item : items)
        axes.append(item->zAxisItem());
    return axes;
}

double GUI::View::RangeUtil::commonMin(const QList<AmplitudeAxisItem*>& axes)
{
    double min = +std::numeric_limits<double>::max();
    for (auto axis : axes)
        if (min > axis->min())
            min = axis->min();
    return min;
}

double GUI::View::RangeUtil::commonMax(const QList<AmplitudeAxisItem*>& axes)
{
    double max = -std::numeric_limits<double>::max();
    for (auto axis : axes)
        if (max < axis->max())
            max = axis->max();
    return max;
}

QCPRange GUI::View::RangeUtil::commonRange(const QList<AmplitudeAxisItem*>& axes)
{
    return QCPRange(commonMin(axes), commonMax(axes));
}

void GUI::View::RangeUtil::setCommonRangeY(QList<SpecularDataItem*> items)
{
    QCPRange range = commonRange(valueAxesFromSpecularItems(items));
    for (auto item : items) {
        item->setLowerY(range.lower);
        item->setUpperY(range.upper);
    }
}

void GUI::View::RangeUtil::setCommonRangeZ(QList<IntensityDataItem*> items)
{
    QCPRange range = commonRange(valueAxesFromIntensityItems(items));
    for (auto item : items) {
        item->setLowerZ(range.lower);
        item->setUpperZ(range.upper);
    }
}
