#include "TimeReplicatorProtocolBM.h"

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

}

TimeReplicatorProtocolBM::~TimeReplicatorProtocolBM()
{

}

bool TimeReplicatorProtocolBM::parseDeviceFrameData(QByteArray rawData, DeviceFrameBaseDto *frameData, int frameType)
{
    if (frameType == TIME_REPLICATOR_FRAME_TYPE::STATUS_FRAME)
    {
        qint8 length = rawData.mid(1, 2).toInt(0, 16);
        QByteArray content = rawData.mid(19, length - 24);
        qint8 count;
        int inputByte = 0;
        QString outStr = "";

        ((TimeReplicatorStatusDto *) frameData)->devStatus = content.at(0);
        if (length < 0x30)
        {
            count = 2;
            inputByte = content.mid(2, 1).toInt();
            outStr = content.mid(3, 8 * count);
        } else
        {
            count = 4;
            inputByte = content.mid(2, 2).toInt();
            outStr = content.mid(4, 8 * count);
        }

        ((TimeReplicatorStatusDto *) frameData)->inCount = count;
        for (int i = 0; i < count; i++)
        {
            qint8 in = inputByte % 2;
            ((TimeReplicatorStatusDto *) frameData)->inValid.append(in == 1 ? "1" : "0");
            inputByte = inputByte / 2;

            QString output = "";
            for (int j = 0; j < 8; j++)
            {
                output += outStr.at(i * 8 + j);
                output += ",";
            }
            ((TimeReplicatorStatusDto *) frameData)->outValid.append(output.mid(0, output.size() - 1));
        }

        ((TimeReplicatorStatusDto *)frameData)->frameType = TIME_REPLICATOR_STATUS_FRAME_TYPE;

        return true;
    } else if (frameType == TIME_REPLICATOR_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;

        return true;
    }
}

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

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

    if (commandType == "1")
    {
        // 4*8 or 2*8
        QStringList valueList = valueSet.split(",");
        for (int i = 0; i < valueList.size(); i++)
        {
            QString value = valueList.at(i);
            while (value.size() < 6)
            {
                value.prepend("0");
            }
            commandBytes.append(value);
        }
    } else if (commandType == "2")
    {
        QStringList delayParams = valueSet.split(",");
        if (delayParams.size() == 2)
        {
            commandBytes.append(delayParams.at(0));
            QString delay = delayParams.at(1);
            while(delay.size() < 11)
            {
                delay.insert(1, "0");
            }
            commandBytes.append(delay);
        }
    }

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

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

    return commandBytes;
}

int TimeReplicatorProtocolBM::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 TIME_REPLICATOR_FRAME_TYPE::STATUS_FRAME;
        } else if (rawData.at(3) == '4')
        {
            return TIME_REPLICATOR_FRAME_TYPE::CMDREP_FRAME;
        }
    } else {
        return TIME_REPLICATOR_FRAME_TYPE::UNKNOW_FRAME;
    }
}

DeviceFrameBaseDto * TimeReplicatorProtocolBM::frameFactory(int frameType)
{
    DeviceFrameBaseDto * frameData = 0;
    switch (frameType) {
        case TimeReplicatorProtocolBM::TIME_REPLICATOR_FRAME_TYPE::STATUS_FRAME :
            frameData = new TimeReplicatorStatusDto();
            break;

        case TimeReplicatorProtocolBM::TIME_REPLICATOR_FRAME_TYPE::CMDREP_FRAME :
            frameData = new CommandReplyDto();
            break;

        default:
            frameData = nullptr;
            break;
    }

    return frameData;
}

QList<QByteArray> TimeReplicatorProtocolBM::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;
}
