#include "util.h"
#include <cstddef>
#include <cstdint>

std::shared_ptr<spdlog::logger> get_logger(const std::string& mark, const std::string& log_file)
{
    auto file_sink = std::make_shared<spdlog::sinks::rotating_file_sink_mt>(log_file, 1024 * 50, 3);
    auto console_sink = std::make_shared<spdlog::sinks::stdout_color_sink_mt>();
    file_sink->set_pattern("[%Y-%m-%d %H:%M:%S.%e][%l]: %v");
    console_sink->set_color(spdlog::level::level_enum::info, 0xFFFF);
    console_sink->set_pattern("%^[%Y-%m-%d %H:%M:%S.%e][%l]: %v%$");
    std::vector<spdlog::sink_ptr> sinks{file_sink, console_sink};
    auto logger = std::make_shared<spdlog::logger>(mark, sinks.begin(), sinks.end());
    logger->set_level(spdlog::level::debug);
    spdlog::register_logger(logger);
    return logger;
}

CTransProtocal::CTransProtocal()
{
}

CTransProtocal::~CTransProtocal()
{
}

/*
【 transm TCP 数据协议 】
    header 2 char: 0xFF 0xFE
    type   2 char:
    mark   1 char:
    len    4 char:
    data    xxxxx:
    tail   2 char: 0xFF 0xFF
 */
CFrameBuffer* CTransProtocal::parse(CMutBuffer& buffer)
{
    CFrameBuffer* result = nullptr;
    unsigned char header[] = {0xFF, 0xFE};
    unsigned char tail[] = {0xFF, 0xFF};

    int find = buffer.index_of((const char*)header, sizeof(header));
    if (find < 0) {
        return result;
    }
    int16_t type = *(reinterpret_cast<const int16_t*>(buffer.get_data() + find + 2));
    char mark = *(buffer.get_data() + find + 2 + 2);
    int32_t len = *(reinterpret_cast<const int32_t*>(buffer.get_data() + find + 2 + 2 + 1));
    int32_t tail_index = find + 2 + 2 + 1 + 4 + len;
    if (buffer.get_len() - 2 < tail_index || len < 0) {
        return result;
    }
    unsigned char taila = *((unsigned char*)(buffer.get_data() + tail_index));
    unsigned char tailb = *((unsigned char*)(buffer.get_data() + tail_index + 1));
    if (taila != tail[0] || tailb != tail[1]) {
        return result;
    }
    result = new CFrameBuffer();
    result->data_ = new char[len];
    result->len_ = len;
    result->mark_ = mark;
    result->type_ = type;
    std::memset(result->data_, 0x0, len);
    std::memcpy(result->data_, buffer.get_data() + find + 2 + 2 + 1 + 4, len);
    buffer.remove_of(0, tail_index + 2);
    return result;
}

bool CTransProtocal::pack(CFrameBuffer* buf, char** out_buf, int& len)
{
    if (buf == nullptr || buf->data_ == nullptr || buf->len_ < 1) {
        return false;
    }
    unsigned char header[] = {0xFF, 0xFE};
    unsigned char tail[] = {0xFF, 0xFF};
    len = buf->len_ + 11;
    *out_buf = new char[len];
    std::memcpy(*out_buf, header, 2);
    std::memcpy(*out_buf + 2, &buf->type_, 2);
    std::memcpy(*out_buf + 2 + 2, &buf->mark_, 1);
    std::memcpy(*out_buf + 2 + 2 + 1, &buf->len_, 4);
    std::memcpy(*out_buf + 2 + 2 + 1 + 4, buf->data_, buf->len_);
    std::memcpy(*out_buf + len - 2, tail, 2);
    return true;
}

CFrameBuffer::CFrameBuffer()
{
}

CFrameBuffer::~CFrameBuffer()
{
    delete[] data_;
    len_ = 0;
}

SimpleBuffer::~SimpleBuffer()
{
    delete[] data_;
    len_ = 0;
}
