"""XPT2046 Touch module."""
from time import sleep
from micropython import const  # type: ignore

class Touch(object):
    """Serial interface for XPT2046 Touch Screen Controller."""

    # Command constants
    GET_X = const(0b11010000)  # X position
    GET_Y = const(0b10010000)  # Y position

    def __init__(self, spi, cs, width=320, height=240,
                 x_min=181, x_max=1890, y_min=123, y_max=1813,
                 swap_xy=False, invert_x=False, invert_y=False):
        """Initialize touch screen controller."""
        self.spi = spi
        self.cs = cs
        from machine import Pin
        self.cs.init(Pin.OUT, value=1)
        self.rx_buf = bytearray(3)
        self.tx_buf = bytearray(3)
        self.width = width
        self.height = height
        self.swap_xy = swap_xy
        self.invert_x = invert_x
        self.invert_y = invert_y
        
        # Calibration
        self.x_min = x_min
        self.x_max = x_max
        self.y_min = y_min
        self.y_max = y_max

    def normalize(self, x, y):
        """Normalize raw X,Y values to match LCD screen."""
        if self.swap_xy:
            x, y = y, x
            # Plages pour swap : X_raw devient LCD_Y, Y_raw devient LCD_X
            nx = int(self.width * (x - self.y_min) / (self.y_max - self.y_min))
            ny = int(self.height * (y - self.x_min) / (self.x_max - self.x_min))
        else:
            nx = int(self.width * (x - self.x_min) / (self.x_max - self.x_min))
            ny = int(self.height * (y - self.y_min) / (self.y_max - self.y_min))

        if self.invert_x:
            nx = self.width - nx
        if self.invert_y:
            ny = self.height - ny
            
        return nx, ny

    def raw_touch(self):
        """Read raw X,Y touch values."""
        x = self.send_command(self.GET_X)
        y = self.send_command(self.GET_Y)
        if x > 10 and y > 10:
            return (x, y)
        return None

    def get_touch(self):
        """Read normalized X,Y touch values."""
        pos = self.raw_touch()
        if pos:
            return self.normalize(*pos)
        return None

    def send_command(self, command):
        """Write command to XT2046."""
        self.tx_buf[0] = command
        self.cs(0)
        self.spi.write_readinto(self.tx_buf, self.rx_buf)
        self.cs(1)
        return (self.rx_buf[1] << 4) | (self.rx_buf[2] >> 4)
