#include "leddisplaytextmodel.h"

LedDisplayTextModel::LedDisplayTextModel(QObject* parent) : QAbstractListModel(parent)
{
    this->maximumTextSets = 0;
    this->maximumTextLength = 0;

    connect(this, &LedDisplayTextModel::rowsInserted, this, &LedDisplayTextModel::rowCountChanged);
    connect(this, &LedDisplayTextModel::rowsRemoved, this, &LedDisplayTextModel::rowCountChanged);
}

int LedDisplayTextModel::rowCount(const QModelIndex &) const
{
    return this->texts.length();
}

QVariant LedDisplayTextModel::data(const QModelIndex &index, int role) const
{
    return this->data(index.row(), role);
}

QVariant LedDisplayTextModel::data(int row, int role) const {
    if (row >= 0 && row < rowCount()) {
        if(this->texts[row].contains(role)) {
            QVariant value = this->texts[row][role];
            value.convert(this->roleDataTypes[LedDisplayTextModelRole(role)]);
            return value;
        }
        else if(role == IndexRole) {
            return row;
        }
    }
    else {
        qDebug() << "[WARING] Row " << row << "is larger than row count " << rowCount();
    }
    return QVariant();
}

QHash<int, QByteArray> LedDisplayTextModel::roleNames() const
{
    static const QHash<int, QByteArray> roles {
        { TextRole, "text" },
        { ActiveRole, "active" },
        { RuntimeRole, "runtime" },
        { ColorRole, "color" },
        { AlignmentRole, "alignment" },
        { ScrollRole, "scroll" },
        { ScrollDirectionRole, "scrollDirection" },
        { ScrollSpeedRole, "scrollSpeed" },
        { ScrollCountRole, "scrollCount" },
        { IndexRole, "index" }
    };
    return roles;
}

void LedDisplayTextModel::append(
        QString text,
        bool active,
        unsigned int runtime,
        QString color,
        unsigned int alignment,
        bool scroll,
        unsigned int scrollDirection,
        unsigned int scrollSpeed,
        unsigned int scrollCount
        ) {

    // check length maximums
    if(this->texts.length() >= this->maximumTextSets)
        return;

    if(text.length() > this->maximumTextLength)
        text = text.left(this->maximumTextLength);

    QMap<int, QVariant> roles = {
        { TextRole, text },
        { ActiveRole, active },
        { RuntimeRole, runtime },
        { ColorRole, color },
        { AlignmentRole, alignment },
        { ScrollRole, scroll },
        { ScrollDirectionRole, scrollDirection},
        { ScrollSpeedRole, scrollSpeed },
        { ScrollCountRole, scrollCount }
    };

    this->append(roles);
}

void LedDisplayTextModel::append(const QMap<int, QVariant> &roles) {
    int row = this->texts.length();
    this->beginInsertRows(QModelIndex(), row, row);
    this->texts.insert(row, roles);
    this->endInsertRows();
}

bool LedDisplayTextModel::setData(const QModelIndex &index, const QVariant &value, int role) {
    if (index.row() >= rowCount() || !this->texts[index.row()].contains(role))
        return false;

    if(this->texts[index.row()][role] == value)
        return true;

    if(role == TextRole && value.toString().length() > this->maximumTextLength)
        this->texts[index.row()][role] = value.toString().left(this->maximumTextLength);
    else
        this->texts[index.row()][role] = value;

    qDebug() << "setting index: " << index << " role: " << role << " value " << value;

    emit dataChanged(index, index, QVector<int>({role}));

    return true;
}

void LedDisplayTextModel::remove(int row)
{
    if (row < 0 || row >= this->rowCount())
        return;

    qDebug() << "Removing row: " << row;
    beginRemoveRows(QModelIndex(), row, row);
    this->texts.removeAt(row);
    endRemoveRows();
}

void LedDisplayTextModel::clear() {
    for(int i = 0; i < this->texts.length(); i++)
        this->remove(i);
}

bool LedDisplayTextModel::setTexts(QList<QMap<int, QVariant>> texts) {
    this->beginResetModel();
    this->resetInternalData();
    this->texts.clear();
    this->endResetModel();

    for(QMap<int, QVariant> text : texts) {
        if(text[0].toString().isEmpty()) continue;
        this->append(text);
    }

    return true;
}

QList<QMap<int, QVariant>> LedDisplayTextModel::getTexts() {
    return this->texts;
}

QMap<int, QVariant> LedDisplayTextModel::getText(const QModelIndex &index) {
    if (index.row() < this->rowCount())
            return this->texts[index.row()];

    return QMap<int, QVariant>();
}


int LedDisplayTextModel::getMaximumTextSets() {
    return this->maximumTextSets;
}
