#pragma once
#include <cstdint>

// Single place that maps a raw CST820B sample into the shell's display space.
// Coordinate mirroring/rotation is never scattered into UI code: if the first
// physical test shows a flipped or rotated axis, only these booleans change.
//
// Verified from M5GFX StopWatch autodetect (M5GFX.cpp): the CST820B reports
// 0..233 on both axes while the CO5300 panel is 468x466 with offset_x=6.
namespace wearable {

struct TouchTransform {
    uint16_t raw_max_x = 233;
    uint16_t raw_max_y = 233;
    uint16_t display_width = 468;
    uint16_t display_height = 466;
    // Raw axis assignment. CST820B raw X drives display X on this board.
    bool swap_xy = false;
    // Per-axis mirroring. Kept explicit so a physical test can flip one axis.
    bool mirror_x = false;
    bool mirror_y = false;

    void apply(uint16_t raw_x, uint16_t raw_y, uint16_t& x, uint16_t& y) const {
        uint16_t rx = raw_x > raw_max_x ? raw_max_x : raw_x;
        uint16_t ry = raw_y > raw_max_y ? raw_max_y : raw_y;
        uint32_t dx = uint32_t(rx) * display_width / (raw_max_x + 1);
        uint32_t dy = uint32_t(ry) * display_height / (raw_max_y + 1);
        if (swap_xy) { const uint32_t t = dx; dx = dy; dy = t; }
        if (mirror_x) dx = display_width > dx + 1 ? display_width - 1 - dx : 0;
        if (mirror_y) dy = display_height > dy + 1 ? display_height - 1 - dy : 0;
        x = static_cast<uint16_t>(dx);
        y = static_cast<uint16_t>(dy);
    }
};

} // namespace wearable