#include "LtrdLogModel.h"
#include <QBrush>

LtrdLogModel::LtrdLogModel(QObject *parent) :
    QAbstractTableModel(parent), m_con(0) {
    retranslate();
}

int LtrdLogModel::rowCount(const QModelIndex &parent) const {
    return m_showlogrec.size();
}

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

QVariant LtrdLogModel::data(const QModelIndex &index, int role) const {
    QVariant ret;
    if (index.isValid()) {
        QSharedPointer<LtrSrvLogRec> rec = m_showlogrec.at(index.row());
        logLvlCfg cfg = getLvlCfg(rec->level());
        if (role == Qt::ForegroundRole) {
            ret = QBrush(cfg.color());
        } else if (role == Qt::DisplayRole) {
            switch (index.column()) {
                case COLUMN_TIME:
                    ret = rec->time().toString("h:mm:ss, d.MM.yyyy");
                    break;
                case COLUMN_LEVEL: {
                        QString levelStr = cfg.name();
                        if ((rec->level()==LTR_LOGLVL_ERR_FATAL)  ||
                                (rec->level() == LTR_LOGLVL_ERR)) {
                            levelStr.append(QString(" (%1)").arg(QString::number(rec->errCode())));
                        }
                        ret = levelStr;
                    }
                    break;
                case COLUMN_MSG:
                    ret = rec->text();
                    break;
            }
        } else if (role == Qt::ToolTipRole) {
            ret = rec->text();
        }
    }

    return ret;
}

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

    return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
}

QVariant LtrdLogModel::headerData(int section, Qt::Orientation orientation, int role) const {
    QVariant ret;
    if ((role == Qt::DisplayRole) && (orientation==Qt::Horizontal)) {
        switch (section) {
            case COLUMN_TIME:
                ret = tr("Record time");
                break;
            case COLUMN_LEVEL:
                ret = tr("Level");
                break;
            case COLUMN_MSG:
                ret = tr("Text");
                break;
            default:
                break;
        }
    }
    return ret;
}

int LtrdLogModel::logLevelCnt() const {
    return m_logLvlCfg.size();
}

LtrdLogModel::logLvlCfg LtrdLogModel::logLevelConfig(int idx) const {
    return m_logLvlCfg[idx];
}

void LtrdLogModel::setLogLevel(en_LTR_LogLevel lvl) {
    m_lvl = lvl;
    redrawLogRecords();
}



void LtrdLogModel::retranslate() {
    m_logLvlCfg.clear();
    m_logLvlCfg.append(logLvlCfg(LTR_LOGLVL_ERR_FATAL, Qt::darkRed, tr("Critical Errors")));
    m_logLvlCfg.append(logLvlCfg(LTR_LOGLVL_ERR, Qt::red, tr("Errors")));
    m_logLvlCfg.append(logLvlCfg(LTR_LOGLVL_WARN, Qt::darkYellow, tr("Warnings")));
    m_logLvlCfg.append(logLvlCfg(LTR_LOGLVL_INFO,  Qt::darkGreen, tr("Info")));
    m_logLvlCfg.append(logLvlCfg(LTR_LOGLVL_DETAIL, Qt::black, tr("Detail")));
    m_logLvlCfg.append(logLvlCfg(LTR_LOGLVL_DBG_HIGH, Qt::gray, tr("Debug 1")));
    m_logLvlCfg.append(logLvlCfg(LTR_LOGLVL_DBG_MED, Qt::gray, tr("Debug 2")));
    m_logLvlCfg.append(logLvlCfg(LTR_LOGLVL_DBG_LOW, Qt::gray, tr("Debug 3")));
}


void LtrdLogModel::addLogRecords(QList<QSharedPointer<LtrSrvLogRec> > recs) {
    QList<QSharedPointer<LtrSrvLogRec> > newrecs;
    Q_FOREACH(QSharedPointer<LtrSrvLogRec> rec, recs) {
        if (rec->level() <= m_lvl) {
            newrecs.append(rec);
        }
    }

    if (newrecs.size()) {
        beginInsertRows(QModelIndex(), m_showlogrec.size(), m_showlogrec.size()+newrecs.size()-1);
        m_showlogrec += newrecs;
        endInsertRows();
    }
}

void LtrdLogModel::removeOldLogRecords(QList<QSharedPointer<LtrSrvLogRec> > recs) {
    int cnt = 0;
    int cur_check_idx = 0;
    Q_FOREACH(QSharedPointer<LtrSrvLogRec> rec, m_showlogrec) {
        cur_check_idx = recs.indexOf(rec, cur_check_idx);
        if (cur_check_idx >= 0) {
            cnt++;
        } else {
            break;
        }
    }

    if (cnt > 0) {
        beginRemoveRows(QModelIndex(), 0, cnt-1);
        for (int i = 0; i < cnt; i++)
            m_showlogrec.removeFirst();
        endRemoveRows();
    }
}

void LtrdLogModel::redrawLogRecords() {

    if (m_con) {
        disconnect(m_con, &LtrdConnection::newLogRecords, this, &LtrdLogModel::addLogRecords);
        disconnect(m_con, &LtrdConnection::oldLogRecordsRemove, this, &LtrdLogModel::removeOldLogRecords);
    }

    if (m_showlogrec.size()!=0) {
        beginRemoveRows(QModelIndex(), 0, m_showlogrec.size()-1);
        m_showlogrec.clear();
        endRemoveRows();
    }

    if (m_con) {
        m_con->logLock();
        QList<QSharedPointer<LtrSrvLogRec> > recs = m_con->logRecords();
        connect(m_con, &LtrdConnection::newLogRecords, this, &LtrdLogModel::addLogRecords);
        connect(m_con, &LtrdConnection::oldLogRecordsRemove, this, &LtrdLogModel::removeOldLogRecords);
        m_con->logUnlock();
        addLogRecords(recs);
    }
}

LtrdLogModel::logLvlCfg LtrdLogModel::getLvlCfg(en_LTR_LogLevel level) const {
    for (int i=0; i<m_logLvlCfg.size(); i++)  {
         if (m_logLvlCfg[i].level() == level)
            return m_logLvlCfg[i];
    }
    return m_logLvlCfg.last();
}


void LtrdLogModel::setConnection(LtrdConnection *con) {
    if (con != m_con) {
        if (m_con) {
            disconnect(m_con, SIGNAL(newLogRecord(QSharedPointer<LtrSrvLogRec>)),
                       this, SLOT(addLogRec(QSharedPointer<LtrSrvLogRec>)));
        }
        m_con = con;
        redrawLogRecords();
    }
}

void LtrdLogModel::clear() {
    if (m_con)
        m_con->clearLog();
    redrawLogRecords();
}

