#include "writeregistermodel.h"

#include "writeregistermodel.h"

enum { NumColumn = 0, NameColumn = 1, CoilsColumn = 2, HoldingColumn = 3, ColumnCount = 5, CurrentUColumn = 4};

WriteRegisterModel::WriteRegisterModel(QObject *parent, int _tmpRC, bool _isHR)
    : QAbstractTableModel(parent),
      m_coils(RowCount=_tmpRC, false), m_holdingRegisters(RowCount=_tmpRC, 0u), m_currentU(RowCount=_tmpRC)
{
    isHR=_isHR;
}

int WriteRegisterModel::rowCount(const QModelIndex &/*parent*/) const
{
    return RowCount;
}

int WriteRegisterModel::columnCount(const QModelIndex &/*parent*/) const
{
    return ColumnCount;
}

QVariant WriteRegisterModel::data(const QModelIndex &index, int role) const
{
    if (!index.isValid() || index.row() >= RowCount || index.column() >= ColumnCount)
        return QVariant();
    Q_ASSERT(m_coils.count() == RowCount);
    Q_ASSERT(m_holdingRegisters.count() == RowCount);
    if (index.column() == NumColumn && role == Qt::DisplayRole)
        return QString::number(index.row());
    if (index.column() == NameColumn && role == Qt::DisplayRole)
        return QString("ТЭ%1").arg(index.row()%(RowCount/(1+isHR))+1);
    if (index.column() == CoilsColumn && role == Qt::CheckStateRole) // coils
        return m_coils.at(index.row()) ? Qt::Checked : Qt::Unchecked;
    if (index.column() == HoldingColumn && role == Qt::DisplayRole) // holding registers
        return QString("%1 В").arg(QString::number((double)((double)m_holdingRegisters.at(index.row())/(double)1000), 'f', 3));
    if(index.column() == CurrentUColumn && role == Qt::DisplayRole)
        return QString("%1 В").arg(QString::number((double)((double)m_currentU.at(index.row())/(double)1000), 'f', 3));
    return QVariant();
}

QVariant WriteRegisterModel::headerData(int section, Qt::Orientation orientation, int role) const
{
    if (role != Qt::DisplayRole)
        return QVariant();
    if (orientation == Qt::Horizontal) {
        switch (section) {
        case NumColumn:
            return QStringLiteral("#Reg");
        case NameColumn:
            return QStringLiteral("Fuel Cell");
        case CoilsColumn:
            return QStringLiteral("Coils");
        case HoldingColumn:
            return QStringLiteral("Holding Registers");
        case CurrentUColumn:
            return QStringLiteral("Current U");
        default:
            break;
        }
    }
    return QVariant();
}

bool WriteRegisterModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
    if (!index.isValid() ||  index.row() >= RowCount || index.column() >= ColumnCount)
        return false;
    Q_ASSERT(m_coils.count() == RowCount);
    Q_ASSERT(m_holdingRegisters.count() == RowCount);
    if (index.column() == CoilsColumn && role == Qt::CheckStateRole) { // coils
        auto s = static_cast<Qt::CheckState>(value.toUInt());
        s == Qt::Checked ? m_coils.setBit(index.row()) : m_coils.clearBit(index.row());
        emit dataChanged(index, index);
        return true;
    }
    if (index.column() == HoldingColumn && role == Qt::EditRole) { // holding registers
        bool result = false;
        quint16 newValue = value.toString().toUShort(&result, 10);
        if (result)
            m_holdingRegisters[index.row()] = newValue;
        emit dataChanged(index, index);
        return result;
    }
    return false;
}

Qt::ItemFlags WriteRegisterModel::flags(const QModelIndex &index) const
{
    if (!index.isValid() || index.row() >= RowCount || index.column() >= ColumnCount)
        return QAbstractTableModel::flags(index);
    Qt::ItemFlags flags = QAbstractTableModel::flags(index);
    if ((index.row() < m_address) || (index.row() >= (m_address + m_number)))
        flags &= ~Qt::ItemIsEnabled;
    if (index.column() == CoilsColumn) // coils
        return flags | Qt::ItemIsUserCheckable;
    if (index.column() == HoldingColumn) // holding registers
        return flags | Qt::ItemIsEditable;
    return flags;
}

void WriteRegisterModel::setStartAddress(int address)
{
    m_address = address;
    //emit updateViewport();
}

void WriteRegisterModel::setNumberOfValues(const QString &number)
{
    m_number = number.toInt();
    //emit updateViewport();
}

bool WriteRegisterModel::get_coil(const QModelIndex &index)
{
    return m_coils.at(index.row());
}

uint WriteRegisterModel::get_holreg(const QModelIndex &index)
{
    return m_holdingRegisters.at(index.row());
}

bool WriteRegisterModel::set_currentU(unsigned _tmpU, unsigned index)
{
    m_currentU[index] = _tmpU;
    if(isHR)
        m_currentU[index + m_number] = _tmpU;
    return true;
}
