#include "touch.h"
#include "config.h"
#include "game.h"
#include "storage.h"
#include <SPI.h>

int16_t tchXMin = 130, tchXMax = 1943;
int16_t tchYMin = 161, tchYMax = 1948;

static bool lastTouchDown = false;
static uint32_t touchCooldown = 0;

bool readRawTouch(int16_t &rawX, int16_t &rawY)
{
    SPI1.beginTransaction(SPISettings(2500000, MSBFIRST, SPI_MODE0));
    digitalWrite(TCH_CS, LOW);

    SPI1.transfer(0xB1);
    int z1 = SPI1.transfer16(0) >> 3;
    SPI1.transfer(0xC1);
    int z2 = SPI1.transfer16(0) >> 3;
    int pressure = z1 + 4095 - z2;
    bool touched = pressure > 1500;

    if (touched)
    {
        int32_t sx = 0, sy = 0;
        for (int i = 0; i < 4; i++)
        {
            SPI1.transfer(0xD0);
            sx += SPI1.transfer16(0) >> 3;
            SPI1.transfer(0x90);
            sy += SPI1.transfer16(0) >> 3;
        }
        rawX = sx / 4;
        rawY = sy / 4;
    }

    SPI1.transfer(0x00);
    digitalWrite(TCH_CS, HIGH);
    SPI1.endTransaction();
    return touched;
}

bool getTouchDown(uint16_t &x, uint16_t &y)
{
    int16_t rawX, rawY;
    bool touched = readRawTouch(rawX, rawY);
    bool down = touched && !lastTouchDown && (millis() > touchCooldown);
    lastTouchDown = touched;
    if (!down)
        return false;

    touchCooldown = millis() + 300;
    x = constrain(map(rawX, tchXMin, tchXMax, 0, 239), 0, 239);
    y = constrain(map(rawY, tchYMin, tchYMax, 0, 319), 0, 319);
    return true;
}

int colFromTouch(uint16_t x, uint16_t y)
{
    if (y < BRD_Y - 20 || y > (uint16_t)(BRD_Y + ROWS * CELL + 10))
        return -1;
    int col = ((int)x - BRD_X) / CELL;
    return (col >= 0 && col < COLS) ? col : -1;
}

int menuItemFromTouch(uint16_t x, uint16_t y)
{
    int itemW = 220, itemH = 36, mx = 10, startY = 80, gap = 6;
    for (int i = 0; i < 4; i++)
    {
        int iy = startY + i * (itemH + gap);
        if ((int)x >= mx && (int)x <= mx + itemW &&
            (int)y >= iy && (int)y <= iy + itemH)
            return i;
    }
    return -1;
}

void calibrateTouch()
{
    tft.fillScreen(ST77XX_BLACK);
    tft.setTextSize(2);
    tft.setTextColor(ST77XX_WHITE);
    tft.setCursor(10, 140);
    tft.print("Touch top-left +");
    tft.drawFastHLine(10, 20, 20, ST77XX_MAGENTA);
    tft.drawFastVLine(20, 10, 20, ST77XX_MAGENTA);

    int16_t rx, ry;
    while (!readRawTouch(rx, ry))
        delay(10);
    tchXMin = rx;
    tchYMin = ry;
    while (readRawTouch(rx, ry))
        delay(10);
    delay(300);

    tft.fillScreen(ST77XX_BLACK);
    tft.setCursor(10, 140);
    tft.print("Touch bottom-right +");
    tft.drawFastHLine(210, 300, 20, ST77XX_MAGENTA);
    tft.drawFastVLine(220, 290, 20, ST77XX_MAGENTA);

    while (!readRawTouch(rx, ry))
        delay(10);
    tchXMax = rx;
    tchYMax = ry;
    while (readRawTouch(rx, ry))
        delay(10);

    saveCalibration();
}
