//  ************************************************************************************************
//
//  BornAgain: simulate and fit reflection and scattering
//
//! @file      GUI/Model/Project/DataSource.cpp
//! @brief     Defines class DataSource.
//!
//! @homepage  http://www.bornagainproject.org
//! @license   GNU General Public License v3 or higher (see COPYING)
//! @copyright Forschungszentrum Jülich GmbH 2022
//! @authors   Scientific Computing Group at MLZ (see CITATION, AUTHORS)
//
//  ************************************************************************************************

#include "GUI/Model/Project/DataSource.h"
#include "GUI/Model/Data/Data1DItem.h"
#include "GUI/Model/Data/Data2DItem.h"
#include "GUI/Model/File/DatafilesSet.h"
#include "GUI/Model/Job/JobsSet.h"
#include "GUI/Model/Project/ProjectDocument.h"

DataSource::~DataSource() = default;

QVector<Data1DItem*> DataSource::mainData1DItems() const
{
    QVector<Data1DItem*> result;
    if (auto* ii = simuData1DItem())
        result.append(ii);
    if (auto* ii = realData1DItem())
        result.append(ii);
    return result;
}

QVector<Data2DItem*> DataSource::mainData2DItems() const
{
    QVector<Data2DItem*> result;
    if (auto* ii = simuData2DItem())
        result.append(ii);
    if (auto* ii = realData2DItem())
        result.append(ii);
    return result;
}

QVector<Data1DItem*> DataSource::allData1DItems() const
{
    QVector<Data1DItem*> result = mainData1DItems();
    if (auto* ii = diffData1DItem())
        result.append(ii);
    return result;
}

QVector<Data2DItem*> DataSource::allData2DItems() const
{
    QVector<Data2DItem*> result = mainData2DItems();
    if (auto* ii = diffData2DItem())
        result.append(ii);
    return result;
}

Data1DItem* DataSource::currentData1DItem() const
{
    if (allData1DItems().empty())
        return nullptr;
    return allData1DItems().first();
}

Data2DItem* DataSource::currentData2DItem() const
{
    if (allData2DItems().empty())
        return nullptr;
    return allData2DItems().first();
}

//  ************************************************************************************************

DataFromData::~DataFromData() = default;

DataItem* DataFromData::realDataItem() const
{
    if (DatafileItem* dfi = gDoc->datafilesRW()->currentItem())
        return dfi->dataItem();
    return nullptr;
}

Data1DItem* DataFromData::realData1DItem() const
{
    return dynamic_cast<Data1DItem*>(realDataItem());
}

Data2DItem* DataFromData::realData2DItem() const
{
    return dynamic_cast<Data2DItem*>(realDataItem());
}

//  ************************************************************************************************

DataFromJob::~DataFromJob() = default;

JobItem* DataFromJob::jobxItem() const
{
    return gDoc->jobsRW()->currentItem();
}

Data1DItem* DataFromJob::realData1DItem() const
{
    if (JobItem* ji = jobxItem()) {
        if (ji->isValidForFitting())
            return ji->dfileItem()->data1DItem();
        else
            return ji->data1DItem();
    }
    return nullptr;
}

Data2DItem* DataFromJob::realData2DItem() const
{
    if (JobItem* ji = jobxItem()) {
        if (ji->isValidForFitting())
            return ji->dfileItem()->data2DItem();
        else
            return ji->data2DItem();
    }
    return nullptr;
}

Data1DItem* DataFromJob::simuData1DItem() const
{
    if (JobItem* ji = jobxItem())
        return ji->data1DItem();
    return nullptr;
}

Data2DItem* DataFromJob::simuData2DItem() const
{
    if (JobItem* ji = jobxItem())
        return ji->data2DItem();
    return nullptr;
}

Data1DItem* DataFromJob::diffData1DItem() const
{
    if (JobItem* ji = jobxItem())
        if (ji->isValidForFitting())
            return dynamic_cast<Data1DItem*>(ji->diffDataItem());
    return nullptr;
}

Data2DItem* DataFromJob::diffData2DItem() const
{
    if (JobItem* ji = jobxItem())
        if (ji->isValidForFitting())
            return dynamic_cast<Data2DItem*>(ji->diffDataItem());
    return nullptr;
}
