#include "DeviceProtocolBase.h"
#include "FrequencyTuningProtocolTX.h"
#include "SignalGeneratorProtocolBM.h"
#include "TimeSwitcherProtocolBM.h"
#include "FreqSwitcherProtocolBM.h"
#include "TimeReplicatorProtocolBM.h"
#include "FreqReplicatorProtocolTX.h"
#include "BCodeTerminalProtocolBM.h"
#include "NtpServerProtocolBM.h"

#include <iostream>

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

}

DeviceProtocolBase * DeviceProtocolBase::deviceProtocolFactory(QString deviceType)
{
    if (deviceType == "03" || deviceType.contains("FrequencyTuning") == true)
    {
        return new FrequencyTuningProtocolTX();
    } else if (deviceType == "04" || deviceType.contains("SignalGenerator") == true)
    {
        return new SignalGeneratorProtocolBM();
    } else if (deviceType == "05" || deviceType.contains("TimeSwitcher") == true)
    {
        return new TimeSwitcherProtocolBM();
    } else if (deviceType == "06" || deviceType.contains("FreqSwitcher") == true)
    {
        return new FreqSwitcherProtocolBM();
    } else if (deviceType == "07" || deviceType.contains("BCodeTerminal") == true)
    {
        return new BCodeTerminalProtocolBM();
    } else if (deviceType == "09" || deviceType.contains("TimeReplicator") == true)
    {
        return new TimeReplicatorProtocolBM();
    } else if (deviceType == "10" || deviceType.contains("FreqReplicator") == true)
    {
        return new FreqReplicatorProtocolTX();
    } else if (deviceType == "11" || deviceType.contains("NtpServer") == true)
    {
        return new NtpServerProtocolBM();
    }

    return nullptr;
}

QByteArray DeviceProtocolBase::generateSettingCommand(QString devCode, QString commandType, QString valueSet)
{
    QByteArray commandBytes;
    commandBytes.append(commandType).append(",");
    commandBytes.append(valueSet);

    QString xorValue = this->calculateXOR(commandBytes);

    commandBytes.prepend("$");
    commandBytes.append("*");
    commandBytes.append(xorValue);

    return commandBytes;
}

QString DeviceProtocolBase::calculateXOR(QByteArray byteArray)
{
    quint8 xorValue = 0;

    for (int i =0; i < byteArray.size(); i++)
    {
        xorValue = xorValue ^ byteArray.at(i);
    }

    QString str;
    str.sprintf("%02X", xorValue);
    return str;
}

QString DeviceProtocolBase::buildCRC16(QByteArray byteArray)
{
    qint16 crc = 0;
    for (int i = 0; i < byteArray.size(); i++) {
        crc = crc ^ byteArray[i] << 8;
        for (int j = 0; j < 8; j++) {
            if ((crc & 0x8000) > 0) {
                crc = crc << 1 ^ 0x1021;
            } else {
                crc = crc << 1;
            }
        }
    }

    QByteArray crcBytes = QByteUtil::ULongToBytes(crc, 2);
    return QByteUtil::binToHexString(crcBytes);
}
