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

#include "GUI/View/SampleDesigner/SampleListModel.h"
#include "Base/Util/Assert.h"
#include "GUI/Model/FromCore/GUIExamplesFactory.h"
#include "GUI/Model/FromCore/ItemizeSample.h"
#include "GUI/Model/Sample/SampleItem.h"
#include "GUI/Model/Sample/SampleModel.h"
#include "GUI/Support/Util/String.h"
#include "GUI/View/Info/DetailedMessageBox.h"
#include "GUI/View/Project/PyImportAssistant.h"
#include "Sample/Multilayer/MultiLayer.h"
#include <QIcon>

SampleListModel::SampleListModel(QObject* parent, SampleModel* model)
    : QAbstractListModel(parent)
    , m_sampleItems(model)
{
}

int SampleListModel::rowCount(const QModelIndex& parent) const
{
    if (parent.isValid())
        return 0;

    return m_sampleItems->sampleItems().size();
}

QVariant SampleListModel::data(const QModelIndex& index, int role) const
{
    auto* const item = itemForIndex(index);

    if (role == Qt::ToolTipRole)
        return item->description();

    if (role == Qt::DisplayRole) {
        auto descr = item->description();
        if (!descr.isEmpty()) {
            descr.prepend("<br><br>");
            const int maxDescriptionLines = 8;
            while (descr.count("\n") >= maxDescriptionLines) {
                descr.truncate(descr.lastIndexOf("\n"));
                descr += " [...]";
            }
            descr.replace("\n", "<br>");
        }
        return "<b>" + item->sampleName() + "</b>" + descr;
    }

    if (role == Qt::EditRole)
        return item->sampleName();

    return QVariant();
}

Qt::ItemFlags SampleListModel::flags(const QModelIndex& index) const
{
    auto f = QAbstractItemModel::flags(index);
    f |= Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled;

    return f;
}

bool SampleListModel::setData(const QModelIndex& index, const QVariant& value, int role)
{
    if (!index.isValid())
        return false;

    if (role == Qt::EditRole && index.column() == 0) {
        itemForIndex(index)->setSampleName(value.toString());
        emit dataChanged(index, index);
        return true;
    }

    if (role == Qt::ToolTipRole && index.column() == 0) {
        itemForIndex(index)->setDescription(value.toString());
        emit dataChanged(index, index);
        return true;
    }

    return false;
}

SampleItem* SampleListModel::itemForIndex(const QModelIndex& index) const
{
    if (!index.isValid())
        return nullptr;

    return m_sampleItems->sampleItems()[index.row()];
}

QModelIndex SampleListModel::indexForItem(SampleItem* item) const
{
    if (auto row = m_sampleItems->sampleItems().indexOf(item); row >= 0)
        return index(row, 0);

    return QModelIndex();
}

void SampleListModel::removeSample(SampleItem* item)
{
    QModelIndex index = indexForItem(item);
    if (!index.isValid())
        return;

    beginRemoveRows(index.parent(), index.row(), index.row());
    m_sampleItems->removeSample(item);
    endRemoveRows();
}

QModelIndex SampleListModel::createSample()
{
    const QStringList existingNames = m_sampleItems->sampleNames();

    const int row = m_sampleItems->sampleItems().size();
    beginInsertRows(QModelIndex(), row, row);
    auto* sample_item = m_sampleItems->addSampleItem();
    sample_item->setSampleName(GUI::Util::String::suggestName(existingNames, "Sample"));
    sample_item->addStandardMaterials();
    endInsertRows();
    return indexForItem(sample_item);
}

QModelIndex SampleListModel::createSampleFromExamples(const QString& className,
                                                      const QString& title,
                                                      const QString& description)
{
    auto* sample = dynamic_cast<SampleItem*>(GUI::ExamplesFactory::itemizeSample(className));
    if (!sample)
        return {};
    sample->setSampleName(title);
    sample->setDescription(description);

    const int row = m_sampleItems->sampleItems().size();
    beginInsertRows(QModelIndex(), row, row);
    m_sampleItems->addSampleItem(sample);
    endInsertRows();
    return indexForItem(sample);
}

#ifdef BORNAGAIN_PYTHON
QModelIndex SampleListModel::createSampleFromPython()
{
    std::unique_ptr<MultiLayer> sample = PyImportAssistant::importMultiLayer();
    if (!sample)
        return {}; // any messages already shown to user

    SampleItem* sampleItem = PyImportAssistant::itemizeSample(*sample);
    if (!sampleItem)
        return {}; // any messages already shown to user

    sampleItem->setDescription("Imported from python code");

    const int row = m_sampleItems->sampleItems().size();
    beginInsertRows(QModelIndex(), row, row);
    m_sampleItems->addSampleItem(sampleItem);
    endInsertRows();
    return indexForItem(sampleItem);
}
#endif
