#include "LtrIpEntriesModel.h"
#include "CheckBoxItemDelegate.h"
#include <QBrush>
#include <QTableView>

LtrIpEntriesModel::LtrIpEntriesModel(LtrdConnection *con, QObject *parent ) :
    QAbstractTableModel(parent), m_con(con) {

    connect(con, SIGNAL(ipAddrStatusChanged(TLTR_CRATE_IP_ENTRY,LtrConEvent,int)),
            SLOT(ipAddrStatusChanged(TLTR_CRATE_IP_ENTRY,LtrConEvent,int)));
    connect(this, SIGNAL(ipEntryFlagsChange(qint32,qint32,bool)),
            con, SLOT(ipEntryFlagsChange(qint32,qint32,bool)));


    QList<TLTR_CRATE_IP_ENTRY> ipList = con->ipEntryList();
    for (int i=0; i < ipList.size(); i++) {
        ipAddrStatusChanged(ipList.at(i), LTR_CONEVENT_ADD, i);
    }
}

int LtrIpEntriesModel::ipEntryCount() const {
    return m_ip_list.size();
}



TLTR_CRATE_IP_ENTRY LtrIpEntriesModel::ipEntry(int ind) const {
    return (ind>=0) && (ind < m_ip_list.size()) ? m_ip_list.at(ind) : TLTR_CRATE_IP_ENTRY();
}

int LtrIpEntriesModel::rowCount(const QModelIndex &parent) const {
    return m_ip_list.size();
}

int LtrIpEntriesModel::columnCount(const QModelIndex &parent) const {
    return COLUMN_CNT;
}

QVariant LtrIpEntriesModel::data(const QModelIndex &index, int role) const {
    QVariant ret;
    if (index.isValid()) {
        TLTR_CRATE_IP_ENTRY entry = m_ip_list.at(index.row());
        if (role == Qt::ForegroundRole) {
            switch (entry.status) {
                case LTR_CRATE_IP_STATUS_CONNECTING:
                    ret = QBrush(Qt::darkBlue);
                    break;
                case LTR_CRATE_IP_STATUS_OFFLINE:
                    /* default color */
                    break;
                case LTR_CRATE_IP_STATUS_ONLINE:
                    ret = QBrush(Qt::darkGreen);
                    break;
                case LTR_CRATE_IP_STATUS_ERROR:
                    ret = QBrush(Qt::red);
                    break;
            }
        } else {
            switch (index.column()) {
                case COLUMN_AUTO: {
                        bool on = entry.flags & LTR_CRATE_IP_FLAG_AUTOCONNECT ? Qt::Checked : Qt::Unchecked;
                        if (role == Qt::DisplayRole) {
                            ret = on ? tr("Yes") : tr("No");
                        } else if (role == Qt::EditRole) {
                            ret = on;
                        } else if (role == Qt::CheckStateRole) {
                            ret = on ? Qt::Checked : Qt::Unchecked;
                        }
                    }
                    break;
                case  COLUMN_RECONNECT: {
                        bool on = entry.flags & LTR_CRATE_IP_FLAG_RECONNECT ? Qt::Checked : Qt::Unchecked;
                        if (role == Qt::DisplayRole) {
                            ret = on ? tr("Yes") : tr("No");
                        } else if (role == Qt::EditRole) {
                            ret = on;
                        } else if (role == Qt::CheckStateRole) {
                            ret = on ? Qt::Checked : Qt::Unchecked;
                        }
                    }
                    break;
                case COLUMN_ADDR:
                    if (role == Qt::DisplayRole)
                        ret = QHostAddress(entry.ip_addr).toString();
                    break;
                case COLUMN_SERIAL:
                    if ((role == Qt::DisplayRole) && (entry.serial_number[0]))
                        ret = QString::fromLatin1(entry.serial_number);
                    break;
                case COLUMN_STATUS:
                    switch (entry.status) {
                        case LTR_CRATE_IP_STATUS_CONNECTING:
                            if (role == Qt::DisplayRole)
                                ret = tr("Connecting...");
                            break;
                        case LTR_CRATE_IP_STATUS_OFFLINE:
                            if (role == Qt::DisplayRole)
                                ret = tr("Offline");
                            break;
                        case LTR_CRATE_IP_STATUS_ONLINE:
                            if (role == Qt::DisplayRole)
                                ret = tr("Online");
                            break;
                        case LTR_CRATE_IP_STATUS_ERROR:
                            if (role == Qt::DisplayRole)
                                ret = tr("Error!");
                            break;
                    }
                    break;
                default:
                    break;
            }
        }
    }
    return ret;
}

Qt::ItemFlags LtrIpEntriesModel::flags(const QModelIndex &index) const {
    if (!index.isValid())
        return 0;

    Qt::ItemFlags flags = Qt::ItemIsEnabled | Qt::ItemIsSelectable;

    switch (index.column()) {
        case COLUMN_AUTO:
        case COLUMN_RECONNECT:
            flags |= Qt::ItemIsEditable;
            break;
        default:
            break;
    }

    return flags;
}

QVariant LtrIpEntriesModel::headerData(int section, Qt::Orientation orientation,
                                       int role) const {
    QVariant ret;
    if ((role == Qt::DisplayRole) && (orientation==Qt::Horizontal)) {
        switch (section) {
            case COLUMN_AUTO:
                ret = tr("A");
                break;
            case COLUMN_RECONNECT:
                ret = tr("R");
                break;
            case COLUMN_ADDR:
                ret = tr("Address");
                break;
            case COLUMN_STATUS:
                ret = tr("Status");
                break;
            case COLUMN_SERIAL:
                ret = tr("Serial");
                break;
            default:
                break;
        }
    } else if (role == Qt::ToolTipRole) {
        switch (section) {
            case COLUMN_AUTO:
                ret = tr("Autoconnection on ltrd startup");
                break;
            case COLUMN_RECONNECT:
                ret = tr("Reconnection on error");
                break;
            case COLUMN_ADDR:
                ret = tr("Crate IP-address");
                break;
            case COLUMN_STATUS:
                ret = tr("Connection status");
                break;
            case COLUMN_SERIAL:
                ret = tr("Crate serial number");
                break;
            default:
                break;
        }
    }
    return ret;
}

bool LtrIpEntriesModel::setData(const QModelIndex &index, const QVariant &value, int role) {
    bool ret = false;
    if (index.isValid()) {
        switch (index.column()) {
            case COLUMN_AUTO:
                if (role == Qt::CheckStateRole) {
                    qint32 new_flags = m_ip_list.at(index.row()).flags;
                    if (value == Qt::Checked) {
                        new_flags |= LTR_CRATE_IP_FLAG_AUTOCONNECT;
                    } else {
                        new_flags &= ~LTR_CRATE_IP_FLAG_AUTOCONNECT;
                    }
                    m_ip_list[index.row()].flags = new_flags;
                    Q_EMIT dataChanged(index, index);
                    Q_EMIT ipEntryFlagsChange(m_ip_list.at(index.row()).ip_addr, new_flags, true);

                }
                break;
            case COLUMN_RECONNECT:
                if (role == Qt::CheckStateRole) {
                    qint32 new_flags = m_ip_list.at(index.row()).flags;
                    if (value == Qt::Checked) {
                        new_flags |= LTR_CRATE_IP_FLAG_RECONNECT;
                    } else {
                        new_flags &= ~LTR_CRATE_IP_FLAG_RECONNECT;
                    }
                    m_ip_list[index.row()].flags = new_flags;
                    Q_EMIT dataChanged(index, index);
                    Q_EMIT ipEntryFlagsChange(m_ip_list.at(index.row()).ip_addr, new_flags, true);

                }
                break;
        }
    }
    return ret;
}

void LtrIpEntriesModel::initView(QTableView *view) {
    view->setModel(this);
    view->setItemDelegateForColumn(COLUMN_AUTO, new CheckBoxItemDelegate(view));
    view->setItemDelegateForColumn(COLUMN_RECONNECT, new CheckBoxItemDelegate(view));

    view->setColumnWidth(COLUMN_AUTO, 30);
    view->setColumnWidth(COLUMN_RECONNECT, 30);
}

void LtrIpEntriesModel::ipAddrStatusChanged(TLTR_CRATE_IP_ENTRY ip, LtrConEvent event, int pos) {
    int fnd=-1;
    for (int i=0; (fnd==-1) && (i < m_ip_list.size()); i++) {
        if (m_ip_list.at(i).ip_addr == ip.ip_addr)
            fnd = i;
    }

    switch (event) {
        case LTR_CONEVENT_ADD:
            if (fnd==-1) {
                beginInsertRows(QModelIndex(), m_ip_list.size(), m_ip_list.size());
                m_ip_list.append(ip);
                endInsertRows();
            }
            break;
        case LTR_CONEVENT_REMOVE:
            if (fnd!=-1) {
                beginRemoveRows(QModelIndex(), fnd, fnd);
                m_ip_list.removeAt(fnd);
                endRemoveRows();
            }
            break;
        case LTR_CONEVENT_DATA_CHANGED:
            if (fnd!=-1) {
                m_ip_list.replace(fnd, ip);
                Q_EMIT dataChanged(createIndex(fnd, 0, (void*)0), createIndex(fnd, COLUMN_CNT-1, (void*)0));
            }
            break;
    }
}
