#include "NtpServerProtocolBM.h"
#include "common/utils/QByteUtil.h"
#include <QDateTime>

NtpServerProtocolBM::NtpServerProtocolBM(QObject *parent) : DeviceProtocolBase(parent)
{

}

NtpServerProtocolBM::~NtpServerProtocolBM()
{

}

bool NtpServerProtocolBM::parseDeviceFrameData(QByteArray rawData, DeviceFrameBaseDto *frameData, int frameType)
{
    if (frameType == NTP_SERVER_FRAME_TYPE::STATUS_FRAME)
    {
        qint8 length = rawData.mid(1, 2).toInt(0, 16);
        QByteArray content = rawData.mid(19, length - 24);

//        1 2 111000 02 220115072016 ff 04120
        ((NtpServerStatusDto *) frameData)->devStatus = content.at(0);

        ((NtpServerStatusDto *) frameData)->freqInType = content.at(2);
        ((NtpServerStatusDto *) frameData)->oppsValid = content.at(3);
        ((NtpServerStatusDto *) frameData)->bdcValid = content.at(4);
        ((NtpServerStatusDto *) frameData)->dclsValid = content.at(5);
        ((NtpServerStatusDto *) frameData)->dclsInType = content.at(6);
        ((NtpServerStatusDto *) frameData)->dclsOutType = content.at(7);

        ((NtpServerStatusDto *) frameData)->refType = content.at(8);
        ((NtpServerStatusDto *) frameData)->refStatus = content.at(9);

        QString dtStr = content.mid(10, 12);
        QDateTime dtObj = QDateTime::fromString(dtStr, "yyMMddHHmmss");
        dtObj = dtObj.addSecs(3600 * 8); // add 8 hours
        ((NtpServerStatusDto *) frameData)->sysTime = "20" + dtObj.toString("yyMMddHHmmss");

        QByteArray outArray = QByteUtil::hexStringToBytes(content.mid(22, 2));
        quint8 outByte = outArray.at(0);
        for (int i = 0; i < 8; i++)
        {
            ((NtpServerStatusDto *) frameData)->outValid.append(QString::number(outByte % 2));
            outByte = outByte / 2;
        }

        for ( int i = 0; i < 5; i++ )
        {
            ((NtpServerStatusDto *) frameData)->tmSrcPrio.append(QString(content.at(24 + i)));
        }

        ((NtpServerStatusDto *)frameData)->frameType = NTP_SERVER_STATUS_FRAME_TYPE;

        return true;
    } else if (frameType == NTP_SERVER_FRAME_TYPE::CMDREP_FRAME)
    {
        qint8 length = rawData.mid(1, 2).toInt(0, 16);
        QByteArray content = rawData.mid(length - 6, 1);

        ((CommandReplyDto *)frameData)->cmdStatus = content == "1" ? 1 : 0;
        ((CommandReplyDto *)frameData)->frameType = NTP_SERVER_CMDREP_TYPE;

        return true;
    }
}

QByteArray NtpServerProtocolBM::generateSettingCommand(QString devCode, QString commandType, QString valueSet)
{
    QByteArray commandBytes;

    commandBytes.append("3");
    commandBytes.append("1308-07").append(0x20);
    commandBytes.append(devCode);
    commandBytes.append(commandType);
    commandBytes.append(valueSet);

    commandBytes.append(this->buildCRC16(commandBytes));
    commandBytes.append("*");

    commandBytes.prepend(QString::number(commandBytes.size() + 3, 16).toUpper().toLocal8Bit());
    commandBytes.prepend("$");

    return commandBytes;
}

int NtpServerProtocolBM::checkFrame(QByteArray rawData)
{
    if (rawData.at(0) == '$' && rawData.at(rawData.size() - 1) == '*' &&
            rawData.size() == rawData.mid(1, 2).toInt(0, 16))
    {
        if (rawData.at(3) == '2' && rawData.at(20) == '2')
        {
            return NTP_SERVER_FRAME_TYPE::STATUS_FRAME;
        } else if (rawData.at(3) == '4')
        {
            return NTP_SERVER_FRAME_TYPE::CMDREP_FRAME;
        }
    } else {
        return NTP_SERVER_FRAME_TYPE::UNKNOW_FRAME;
    }
}

DeviceFrameBaseDto * NtpServerProtocolBM::frameFactory(int frameType)
{
    DeviceFrameBaseDto * frameData = 0;
    switch (frameType) {
        case NtpServerProtocolBM::NTP_SERVER_FRAME_TYPE::STATUS_FRAME :
            frameData = new NtpServerStatusDto();
            break;

        case NtpServerProtocolBM::NTP_SERVER_FRAME_TYPE::CMDREP_FRAME :
            frameData = new CommandReplyDto();
            break;

        default:
            frameData = nullptr;
            break;
    }

    return frameData;
}

QList<QByteArray> NtpServerProtocolBM::extractFrameList(QByteArray rawData)
{
    QList<QByteArray> resultList;
    while ((rawData.endsWith(QByteArray("*")) == true || rawData.endsWith(QByteArray("*\r\n")) == true) &&
           rawData.startsWith("$") == true)
    {
        QByteArray ba;
        qint8 length = rawData.mid(1, 2).toInt(0, 16);
        if (rawData.at(0) == '$' && rawData.at(length - 1) == '*')
        {
            ba.append(rawData.mid(0, length));
            resultList.append(ba);
            ba.clear();
            rawData = rawData.mid(length, rawData.size() - length);
        } else
        {
            break;
        }
    }

    return resultList;
}
