#pragma once

#include "cpdecoder.hh"
#include <cstdint>
#include <optional>
#include <vector>

namespace ffmsep::tactile {
inline constexpr std::uint8_t kStartByteFirst = 0xAA;
inline constexpr std::uint8_t kStartByteSecond = 0x55;

enum class FunctionCode : std::uint8_t {
    Unknown             = 0x00,
    ReadMatrix          = 0x01,
    ReadSingle          = 0x02,
    ReadTemperature     = 0x03,
    SetDeviceId         = 0x51,
    SetMatrixSize       = 0x52,
    CalibrationMode     = 0x53,
};

struct MatrixSize {
    std::uint8_t long_edge = 0;
    std::uint8_t short_edge = 0;
};

struct TactileFrame {
    std::uint8_t device_address             = 0;
    std::uint8_t reserved                   = 0;
    std::uint8_t response_function          = 0;
    FunctionCode function                   = FunctionCode::Unknown;
    std::uint32_t start_address             = 0;
    std::uint16_t return_byte_count         = 0;
    std::uint8_t status                     = 0;
    std::vector<std::uint8_t> payload;
};

std::optional<TactileFrame> parse_frame(const CPFrame& frame);
std::vector<std::uint16_t> parse_pressure_values(const TactileFrame& frame);
std::optional<MatrixSize> parse_matrix_size_payload(const TactileFrame& frame);
std::optional<MatrixSize> parse_patrix_coordinate_payload(const TactileFrame& frame);

const CPCodec* tactile_codec();
void register_tactile_codec();
}
