#include "universemodel.h"

#include <QFont>
#include <QChar>
#include <QMetaEnum>

/**
 * @brief UniverseModel::UniverseModel
 * @param parent
 */
UniverseModel::UniverseModel(QObject *parent)
    : QAbstractTableModel(parent)
{
}


/**
 * @brief UniverseModel::headerData
 * @param section
 * @param orientation
 * @param role
 * @return
 */
QVariant UniverseModel::headerData(int section, Qt::Orientation orientation, int role) const
{
    if (role != Qt::DisplayRole)
        return QVariant();

    if (orientation == Qt::Horizontal)
        return section + 1;

    if (orientation == Qt::Vertical)
        return section * 10;

    return QVariant();
}


/**
 * @brief UniverseModel::rowCount
 * @param parent
 * @return
 */
int UniverseModel::rowCount(const QModelIndex &parent) const
{
    if (parent.isValid())
        return 0;

    return 52;
}


/**
 * @brief UniverseModel::columnCount
 * @param parent
 * @return
 */
int UniverseModel::columnCount(const QModelIndex &parent) const
{
    if (parent.isValid())
        return 0;

    return 10;
}


/**
 * @brief UniverseModel::data
 * @param index
 * @param role
 * @return
 */
QVariant UniverseModel::data(const QModelIndex &index, int role) const
{
    if (!index.isValid())
        return QVariant();

    if (!universe_)
        return QVariant();

    switch (role) {
    case Qt::DisplayRole:
    {
        int slot = (index.row() * 10) + (index.column() + 1);
        if (slot == 0)
            return QVariant();
        if (slot > 512)
            return QVariant();
        switch (data_mode_) {
        case Decimal:
            return universe_->slot(slot);
            break;
        case Hex:
            return QString("%1")
                    .arg(universe_->slot(slot), 2, 16, QChar('0'))
                    .toUpper();
            break;
        case Percent:
            return QString("%1%").arg((universe_->slot(slot) / 255.0F) * 100,
                                      0, 'f', 0, '0');
            break;
        }
        break;
    }
    case Qt::FontRole:
        return QFont("monospace");
        break;
    case Qt::TextAlignmentRole:
        return int(Qt::AlignCenter | Qt::AlignVCenter);
        break;
    default:
        return QVariant();
    }
}


/**
 * @brief UniverseModel::setData
 * @param index
 * @param value
 * @param role
 * @return
 */
bool UniverseModel::setData(const QModelIndex &index, const QVariant &value,
                            int role)
{
    if (data(index, role) != value) {
        // FIXME: Implement me!
        emit dataChanged(index, index, QVector<int>() << role);
        return true;
    }
    return false;
}


/**
 * @brief UniverseModel::flags
 * @param index
 * @return
 */
Qt::ItemFlags UniverseModel::flags(const QModelIndex &index) const
{
    if (!index.isValid())
        return Qt::NoItemFlags;

    if (!universe_)
        return Qt::NoItemFlags;

    int slot = (index.row() * 10) + (index.column() + 1);

    if (slot == 0)
        return Qt::NoItemFlags;
    if (slot > 512)
        return Qt::NoItemFlags;

    return QAbstractItemModel::flags(index);// | Qt::ItemIsEditable;
}


/**
 * @brief UniverseModel::universeRefreshed
 */
void UniverseModel::universeRefreshed() {
    emit dataChanged(index(0,0), index(rowCount(), columnCount()));
    emit recievedUpdate(universe_);
}


/**
 * @brief UniverseModel::setDataMode
 * @param mode
 */
void UniverseModel::setDataMode(const QString mode)
{
   auto&& metaEnum = QMetaEnum::fromType<data_modes>();
   data_mode_ = static_cast<data_modes>(metaEnum.keyToValue(mode.toLocal8Bit()));
   emit dataChanged(index(0,0), index(rowCount(), columnCount()));
}


/**
 * @brief UniverseModel::setUniverse
 * @param universe
 */
void UniverseModel::setUniverse(QSacnUniverse *universe)
{
    if (universe_)
        disconnect(universe_, 0, this, 0);
    universe_ = universe;
    connect(universe_, &QSacnUniverse::changed,
            this, &UniverseModel::universeRefreshed);
}
