#include "treemodelcomposeelement.h"
#include "treeitem.h"

#include <QtWidgets>


TreeModelComposeElement::TreeModelComposeElement(const QStringList &headers, const QString &data, QObject *parent)
    : QAbstractItemModel(parent)
{
    QVector<QVariant> rootData;
    foreach (QString header, headers)
        rootData << header;

    rootItem = new TreeItem(rootData);
    //setupModelData(data.split(QString("\n")), rootItem);

    // Insertar 20 filas vacias por defecto:
    for (int i = 0; i < 5; i++)
    {
        rootItem->insertChildren(rootItem->childCount(), 1, rootItem->columnCount());
        for (int column = 0; column < rootItem->columnCount(); ++column)
            rootItem->child(rootItem->childCount() - 1)->setData(column, QVariant());
    }
}

TreeModelComposeElement::~TreeModelComposeElement()
{
    delete rootItem;
}
//! [1]

//! [2]
int TreeModelComposeElement::columnCount(const QModelIndex & /* parent */) const
{
    return rootItem->columnCount();
}
//! [2]

QVariant TreeModelComposeElement::data(const QModelIndex &index, int role) const
{
    if (!index.isValid())
        return QVariant();

    TreeItem *item = getItem(index);

    switch (role)
    {
        case Qt::DisplayRole:
        case Qt::EditRole:
        {
            if(item->data(7).toString().isEmpty())
            {
                //return data(index, role).toString();
                return item->data(index.column()).toString();
            }

            switch (index.column())
            {
                case 2:
                case 3:
                case 5:
                case 6:
                {
                    float value = 0;

                    if(item->data(index.column()).isValid())
                    {
                        value = item->data(index.column()).toFloat();
                    }

                    QLocale locale = QLocale("es_ES");
                    QString s = locale.toString(value, 'f', 2);
                    return s;
                }
                default:
                    return item->data(index.column()).toString();
            }
            break;
        }

        case Qt::ForegroundRole:
            if(index.column() == 0)
                return QVariant::fromValue(QColor(Qt::blue));
            else
                return QVariant();

        case Qt::TextAlignmentRole:
            switch (index.column())
            {
                case 2:
                case 3:
                case 5:
                case 6:
                {
                    return int(Qt::AlignRight | Qt::AlignTop);
                }
                default:
                    return int(Qt::AlignLeft | Qt::AlignTop);
            }

        case Qt::FontRole:
            if(item->childCount() > 0)
            {
                QFont font = QFont("Helvetica", 9, QFont::Bold);
                return QVariant::fromValue(font);
            }
            else
                return QVariant();

        case Qt::SizeHintRole:
        {
            int he = 24;
            switch (index.column())
            {
                case 0:
                    return QSize(30, he);
                case 1:
                    return QSize(70, he);
                case 2:
                case 3:
                    return QSize(150, he);
                case 4:
                case 5:
                    return QSize(50, he);
                case 6:
                    return QSize(40, he);
                case 7:
                case 8:
                case 9:
                case 10:
                case 11:
                    return QSize(50, he);
                case 12:
                    return QSize(70, he);
                default:
                    return QVariant();
            }
        }

        case Qt::DecorationRole:
        {
            /*
    0 Sin clasificar
    1 Mano de obra
    2 Maquinaria
    3 Materiales
    4 Componentes adicionales de residuo
    5 Clasificación de residuo
            */

            if(index.column() == 0)
            {
                if(item->data(7).toString() == "CO")               // Compuesto
                {
                    return QIcon(":/resources/icons/box.svg");
                }
                else if(item->data(7).toString() == "MT")          // Materiales
                {
                    return QIcon(":/resources/icons/blocks.svg");
                }
                else if(item->data(7).toString() == "MO")          // Mano de obra
                {
                    return QIcon(":/resources/icons/helmet.svg");
                }
                else if(item->data(7).toString() == "MQ")          // Maquinaria
                {
                    return QIcon(":/resources/icons/gear.svg");
                }
            }
        }

        default:
            break;
    }

    return QVariant();
}

//! [3]
Qt::ItemFlags TreeModelComposeElement::flags(const QModelIndex &index) const
{
    if (!index.isValid())
        return Qt::NoItemFlags;

    Qt::ItemFlags flags = QAbstractItemModel::flags(index);

    switch (index.column())
    {
        case 0:
        case 2:
        //case 5:
        {
            flags |= Qt::ItemIsEditable;
        }
    }

    return flags;
}
//! [3]

//! [4]
TreeItem *TreeModelComposeElement::getItem(const QModelIndex &index) const
{
    if (index.isValid())
    {
        TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
        if (item)
            return item;
    }
    return rootItem;
}
//! [4]

QVariant TreeModelComposeElement::headerData(int section, Qt::Orientation orientation,
                               int role) const
{
    if (orientation == Qt::Horizontal && role == Qt::DisplayRole)
        return rootItem->data(section);

    return QVariant();
}

//! [5]
QModelIndex TreeModelComposeElement::index(int row, int column, const QModelIndex &parent) const
{
    if (parent.isValid() && parent.column() != 0)
        return QModelIndex();
//! [5]

//! [6]
    TreeItem *parentItem = getItem(parent);
    TreeItem *childItem = parentItem->child(row);

    if (childItem)
        return createIndex(row, column, childItem);
    else
        return QModelIndex();
}
//! [6]

bool TreeModelComposeElement::insertColumns(int position, int columns, const QModelIndex &parent)
{
    bool success;

    beginInsertColumns(parent, position, position + columns - 1);
    success = rootItem->insertColumns(position, columns);
    endInsertColumns();

    return success;
}

bool TreeModelComposeElement::insertRows(int position, int rows, const QModelIndex &parent)
{
    TreeItem *parentItem = getItem(parent);
    bool success;

    beginInsertRows(parent, position, position + rows - 1);
    success = parentItem->insertChildren(position, rows, rootItem->columnCount());
    endInsertRows();

    return success;
}

//! [7]
QModelIndex TreeModelComposeElement::parent(const QModelIndex &index) const
{
    if (!index.isValid())
        return QModelIndex();

    TreeItem *childItem = getItem(index);
    TreeItem *parentItem = childItem->parent();

    if (parentItem == rootItem)
        return QModelIndex();

    return createIndex(parentItem->childNumber(), 0, parentItem);
}
//! [7]

bool TreeModelComposeElement::removeColumns(int position, int columns, const QModelIndex &parent)
{
    bool success;

    beginRemoveColumns(parent, position, position + columns - 1);
    success = rootItem->removeColumns(position, columns);
    endRemoveColumns();

    if (rootItem->columnCount() == 0)
        removeRows(0, rowCount());

    return success;
}

bool TreeModelComposeElement::removeRows(int position, int rows, const QModelIndex &parent)
{
    TreeItem *parentItem = getItem(parent);
    bool success = true;

    beginRemoveRows(parent, position, position + rows - 1);
    success = parentItem->removeChildren(position, rows);
    endRemoveRows();

    return success;
}

//! [8]
int TreeModelComposeElement::rowCount(const QModelIndex &parent) const
{
    TreeItem *parentItem = getItem(parent);

    return parentItem->childCount();
}
//! [8]

bool TreeModelComposeElement::setData(const QModelIndex &index, const QVariant &value, int role)
{
    if (role != Qt::EditRole)
        return false;

    TreeItem *item = getItem(index);
    bool result = item->setData(index.column(), value);

    switch (index.column())
    {
        case 2:
            item->setData(3, value);
            calculateRow(item);
    }

    if (result)
    {
        emit dataChanged(index, index, {role});
    }

    return result;
}

void TreeModelComposeElement::calculateRow(TreeItem *item)
{
    float cu = item->data(2).toFloat();
    float ct = item->data(3).toFloat();
    float pcu = item->data(5).toFloat();
    float pct = ct * pcu;

    item->setData(6, pct);
}

bool TreeModelComposeElement::setHeaderData(int section, Qt::Orientation orientation,
                              const QVariant &value, int role)
{
    if (role != Qt::EditRole || orientation != Qt::Horizontal)
        return false;

    bool result = rootItem->setData(section, value);

    if (result)
        emit headerDataChanged(orientation, section, section);

    return result;
}

void TreeModelComposeElement::setupModelData(const QStringList &lines, TreeItem *parent)
{
    QList<TreeItem*> parents;
    QList<int> indentations;
    parents << parent;
    indentations << 0;

    int number = 0;

    while (number < lines.count())
    {
        int position = 0;
        while (position < lines[number].length())
        {
            if (lines[number].at(position) != ' ')
                break;
            ++position;
        }

        QString lineData = lines[number].mid(position).trimmed();

        if (!lineData.isEmpty())
        {
            // Read the column data from the rest of the line.
            QStringList columnStrings = lineData.split("\t", Qt::SkipEmptyParts);
            QVector<QVariant> columnData;
            for (int column = 0; column < columnStrings.count(); ++column)
                columnData << columnStrings[column];

            if (position > indentations.last())
            {
                // The last child of the current parent is now the new parent
                // unless the current parent has no children.

                if (parents.last()->childCount() > 0)
                {
                    parents << parents.last()->child(parents.last()->childCount()-1);
                    indentations << position;
                }
            }
            else
            {
                while (position < indentations.last() && parents.count() > 0)
                {
                    parents.pop_back();
                    indentations.pop_back();
                }
            }

            // Append a new item to the current parent's list of children.
            TreeItem *parent = parents.last();
            parent->insertChildren(parent->childCount(), 1, rootItem->columnCount());
            for (int column = 0; column < columnData.size(); ++column)
                parent->child(parent->childCount() - 1)->setData(column, columnData[column]);
        }

        ++number;
    }
}
