#include "pch.h"
#include "XYEegParser64.h"

#include <vector>

namespace {

constexpr std::uint8_t kFrameHeader = 0xAA;
constexpr std::uint8_t kFrameTail = 0x55;
constexpr std::size_t kReservedByteCount = 6;

} // namespace

std::vector<std::uint8_t> XYEegParser64::SerializeImpedanceCommand(ImpedanceSwitch impedance_switch)
{
    std::vector<std::uint8_t> payload(kReservedByteCount, 0);
    payload.push_back(static_cast<std::uint8_t>(impedance_switch));
    return SerializeCommand(FunctionCode::kImpedance, payload);
}

std::vector<std::uint8_t> XYEegParser64::SerializeGainAndSampleRateCommand(GainSwitch gain,
                                                                           SampleRateSwitch sample_rate)
{
    std::vector<std::uint8_t> payload(kReservedByteCount, 0);
    payload.push_back(static_cast<std::uint8_t>(gain));
    payload.push_back(static_cast<std::uint8_t>(sample_rate));
    return SerializeCommand(FunctionCode::kGainSampleRate, payload);
}

std::vector<std::uint8_t> XYEegParser64::SerializeCommand(FunctionCode function_code,
                                                          const std::vector<std::uint8_t>& payload)
{
    std::vector<std::uint8_t> command;
    command.reserve(1 + 1 + 2 + payload.size() + 1 + 2);

    command.push_back(kFrameHeader);
    command.push_back(static_cast<std::uint8_t>(function_code));
    command.push_back(static_cast<std::uint8_t>((payload.size() >> 8) & 0xFF));
    command.push_back(static_cast<std::uint8_t>(payload.size() & 0xFF));
    command.insert(command.end(), payload.begin(), payload.end());
    command.push_back(Checksum(command, 1, command.size()));
    command.push_back(kFrameTail);
    command.push_back(kFrameTail);

    return command;
}

std::uint8_t XYEegParser64::Checksum(const std::vector<std::uint8_t>& bytes,
                                     std::size_t begin_offset,
                                     std::size_t end_offset_exclusive) noexcept
{
    std::uint8_t checksum = 0;
    for (std::size_t i = begin_offset; i < end_offset_exclusive && i < bytes.size(); ++i) {
        checksum = static_cast<std::uint8_t>(checksum + bytes[i]);
    }
    return checksum;
}
