#include "Communicate.h"

constexpr unsigned char gHeader[] = {0xFF, 0xFE};
constexpr unsigned char gTail[] = {0xFF, 0xFF};

Communicate::Communicate()
{
}

/*
【 transm TCP 数据协议 】
    header      2 char: 0xFF 0xFE
    dataType    2 char;
    from        32 char:
    to          32 char:
    len         4 char:
    data        xxxxx:
    tail        2 char: 0xFF 0xFF
 */
FrameBuffer* Communicate::ParseBuffer(MutBuffer& buffer)
{
    FrameBuffer* frame = nullptr;

    int find = buffer.IndexOf((const char*)gHeader, sizeof(gHeader));
    if (find < 0) {
        return frame;
    }

    int32_t dataLen = 0;
    std::memcpy(&dataLen, buffer.GetData() + find + sizeof(gHeader) + sizeof(uint16_t) + 64, sizeof(dataLen));
    if (buffer.Length() < (find + sizeof(gHeader) + sizeof(uint16_t) + 64 + dataLen + sizeof(dataLen) + sizeof(gTail)) ||
        dataLen < 0) {
        return frame;
    }

    if (std::memcmp(buffer.GetData() + find + sizeof(gHeader) + sizeof(uint16_t) + 64 + sizeof(dataLen) + dataLen, gTail,
                    sizeof(gTail)) != 0) {
        return frame;
    }

    frame = new FrameBuffer();
    frame->len = dataLen;
    frame->fid = std::string(buffer.GetData() + find + sizeof(gHeader) + sizeof(uint16_t), 32);
    frame->tid = std::string(buffer.GetData() + find + sizeof(gHeader) + sizeof(uint16_t) + 32, 32);
    std::memcpy(&frame->dataType, buffer.GetData() + find + sizeof(gHeader), sizeof(frame->dataType));

    if (frame->len > 0) {
        frame->dataMut = new char[frame->len];
        std::memcpy(frame->dataMut, buffer.GetData() + find + sizeof(gHeader) + sizeof(uint16_t) + 64 + sizeof(frame->len),
                    frame->len);
    }
    buffer.RemoveOf(0, find + sizeof(gHeader) + sizeof(uint16_t) + 64 + frame->len + sizeof(frame->len) + sizeof(gTail));
    return frame;
}

bool Communicate::PackBuffer(FrameBuffer* frame, char** buf, int32_t& len)
{
    if (frame == nullptr) {
        return false;
    }
    const char* dataPtr = nullptr;
    if (frame->dataMut == nullptr && frame->dataConst == nullptr) {
        frame->len = 0;
    }
    if (frame->dataConst) {
        dataPtr = frame->dataConst;
    } else {
        dataPtr = frame->dataMut;
    }
    len = sizeof(gHeader) + sizeof(uint16_t) + 64 + sizeof(len) + frame->len + sizeof(gTail);
    *buf = new char[len];
    std::memcpy(*buf, gHeader, sizeof(gHeader));
    std::memcpy(*buf + sizeof(gHeader), &frame->dataType, sizeof(frame->dataType));
    std::memcpy(*buf + sizeof(gHeader) + sizeof(uint16_t), frame->fid.c_str(), 32);
    std::memcpy(*buf + sizeof(gHeader) + sizeof(uint16_t) + 32, frame->tid.c_str(), 32);
    std::memcpy(*buf + sizeof(gHeader) + sizeof(uint16_t) + 64, &frame->len, sizeof(frame->len));
    if (frame->len > 0) {
        std::memcpy(*buf + sizeof(gHeader) + sizeof(uint16_t) + 64 + sizeof(len), dataPtr, frame->len);
    }
    std::memcpy(*buf + sizeof(gHeader) + sizeof(uint16_t) + 64 + sizeof(len) + frame->len, gTail, sizeof(gTail));
    frame->dataConst = nullptr;
    return true;
}

FrameBuffer::FrameBuffer()
{
    dataConst = nullptr;
    dataMut = nullptr;
    len = 0;
}

FrameBuffer::~FrameBuffer()
{
    delete[] dataMut;
    len = 0;
}