#!/bin/env python3
# SPDX-License-Identifier: GPL-2.0
# -*- coding: utf-8 -*-
#
# Copyright (c) 2020 Benjamin Tissoires <benjamin.tissoires@gmail.com>
# Copyright (c) 2020 Red Hat, Inc.
#

from .base import application_matches
from .base import KernelModule
from .test_gamepad import BaseTest
from hidtools.device.sony_gamepad import (
    PS3Controller,
    PS4ControllerBluetooth,
    PS4ControllerUSB,
    PS5ControllerBluetooth,
    PS5ControllerUSB,
    PSTouchPoint,
)
from hidtools.util import BusType

import libevdev
import logging
import pytest

logger = logging.getLogger("hidtools.test.sony")

PS3_MODULE = KernelModule("sony", "hid_sony")
PS4_MODULE = KernelModule("playstation", "hid_playstation")
PS5_MODULE = KernelModule("playstation", "hid_playstation")


class SonyBaseTest:
    class SonyTest(BaseTest.TestGamepad):
        pass

    class SonyPS4ControllerTest(SonyTest):
        kernel_modules = [PS4_MODULE]

        def test_accelerometer(self):
            uhdev = self.uhdev
            evdev = uhdev.get_evdev("Accelerometer")

            for x in range(-32000, 32000, 4000):
                r = uhdev.event(accel=(x, None, None))
                events = uhdev.next_sync_events("Accelerometer")
                self.debug_reports(r, uhdev, events)

                assert libevdev.InputEvent(libevdev.EV_ABS.ABS_X) in events
                value = evdev.value[libevdev.EV_ABS.ABS_X]
                # Check against range due to small loss in precision due
                # to inverse calibration, followed by calibration by hid-sony.
                assert x - 1 <= value <= x + 1

            for y in range(-32000, 32000, 4000):
                r = uhdev.event(accel=(None, y, None))
                events = uhdev.next_sync_events("Accelerometer")
                self.debug_reports(r, uhdev, events)

                assert libevdev.InputEvent(libevdev.EV_ABS.ABS_Y) in events
                value = evdev.value[libevdev.EV_ABS.ABS_Y]
                assert y - 1 <= value <= y + 1

            for z in range(-32000, 32000, 4000):
                r = uhdev.event(accel=(None, None, z))
                events = uhdev.next_sync_events("Accelerometer")
                self.debug_reports(r, uhdev, events)

                assert libevdev.InputEvent(libevdev.EV_ABS.ABS_Z) in events
                value = evdev.value[libevdev.EV_ABS.ABS_Z]
                assert z - 1 <= value <= z + 1

        def test_gyroscope(self):
            uhdev = self.uhdev
            evdev = uhdev.get_evdev("Accelerometer")

            for rx in range(-2000000, 2000000, 200000):
                r = uhdev.event(gyro=(rx, None, None))
                events = uhdev.next_sync_events("Accelerometer")
                self.debug_reports(r, uhdev, events)

                assert libevdev.InputEvent(libevdev.EV_ABS.ABS_RX) in events
                value = evdev.value[libevdev.EV_ABS.ABS_RX]
                # Sensor internal value is 16-bit, but calibrated is 22-bit, so
                # 6-bit (64) difference, so allow a range of +/- 64.
                assert rx - 64 <= value <= rx + 64

            for ry in range(-2000000, 2000000, 200000):
                r = uhdev.event(gyro=(None, ry, None))
                events = uhdev.next_sync_events("Accelerometer")
                self.debug_reports(r, uhdev, events)

                assert libevdev.InputEvent(libevdev.EV_ABS.ABS_RY) in events
                value = evdev.value[libevdev.EV_ABS.ABS_RY]
                assert ry - 64 <= value <= ry + 64

            for rz in range(-2000000, 2000000, 200000):
                r = uhdev.event(gyro=(None, None, rz))
                events = uhdev.next_sync_events("Accelerometer")
                self.debug_reports(r, uhdev, events)

                assert libevdev.InputEvent(libevdev.EV_ABS.ABS_RZ) in events
                value = evdev.value[libevdev.EV_ABS.ABS_RZ]
                assert rz - 64 <= value <= rz + 64

        def test_battery(self):
            uhdev = self.uhdev

            assert uhdev.power_supply_class is not None

            # DS4 capacity levels are in increments of 10.
            # Battery is never below 5%.
            for i in range(5, 105, 10):
                uhdev.battery.capacity = i
                uhdev.event()
                assert uhdev.power_supply_class.capacity == i

            # Discharging tests only make sense for BlueTooth.
            if uhdev.bus == BusType.BLUETOOTH:
                uhdev.battery.cable_connected = False
                uhdev.battery.capacity = 45
                uhdev.event()
                assert uhdev.power_supply_class.status == "Discharging"

            uhdev.battery.cable_connected = True
            uhdev.battery.capacity = 5
            uhdev.event()
            assert uhdev.power_supply_class.status == "Charging"

            uhdev.battery.capacity = 100
            uhdev.event()
            assert uhdev.power_supply_class.status == "Charging"

            uhdev.battery.full = True
            uhdev.event()
            assert uhdev.power_supply_class.status == "Full"

        def test_mt_single_touch(self):
            """send a single touch in the first slot of the device,
            and release it."""
            uhdev = self.uhdev
            evdev = uhdev.get_evdev("Touch Pad")

            t0 = PSTouchPoint(1, 50, 100)
            r = uhdev.event(touch=[t0])
            events = uhdev.next_sync_events("Touch Pad")
            self.debug_reports(r, uhdev, events)

            assert libevdev.InputEvent(libevdev.EV_KEY.BTN_TOUCH, 1) in events
            assert evdev.slots[0][libevdev.EV_ABS.ABS_MT_TRACKING_ID] == 0
            assert evdev.slots[0][libevdev.EV_ABS.ABS_MT_POSITION_X] == 50
            assert evdev.slots[0][libevdev.EV_ABS.ABS_MT_POSITION_Y] == 100

            t0.tipswitch = False
            r = uhdev.event(touch=[t0])
            events = uhdev.next_sync_events("Touch Pad")
            self.debug_reports(r, uhdev, events)
            assert libevdev.InputEvent(libevdev.EV_KEY.BTN_TOUCH, 0) in events
            assert evdev.slots[0][libevdev.EV_ABS.ABS_MT_TRACKING_ID] == -1

        def test_mt_dual_touch(self):
            """Send 2 touches in the first 2 slots.
            Make sure the kernel sees this as a dual touch.
            Release and check

            Note: PTP will send here BTN_DOUBLETAP emulation"""
            uhdev = self.uhdev
            evdev = uhdev.get_evdev("Touch Pad")

            t0 = PSTouchPoint(1, 50, 100)
            t1 = PSTouchPoint(2, 150, 200)

            r = uhdev.event(touch=[t0])
            events = uhdev.next_sync_events("Touch Pad")
            self.debug_reports(r, uhdev, events)

            assert libevdev.InputEvent(libevdev.EV_KEY.BTN_TOUCH, 1) in events
            assert evdev.value[libevdev.EV_KEY.BTN_TOUCH] == 1
            assert evdev.slots[0][libevdev.EV_ABS.ABS_MT_TRACKING_ID] == 0
            assert evdev.slots[0][libevdev.EV_ABS.ABS_MT_POSITION_X] == 50
            assert evdev.slots[0][libevdev.EV_ABS.ABS_MT_POSITION_Y] == 100
            assert evdev.slots[1][libevdev.EV_ABS.ABS_MT_TRACKING_ID] == -1

            r = uhdev.event(touch=[t0, t1])
            events = uhdev.next_sync_events("Touch Pad")
            self.debug_reports(r, uhdev, events)
            assert libevdev.InputEvent(libevdev.EV_KEY.BTN_TOUCH) not in events
            assert evdev.value[libevdev.EV_KEY.BTN_TOUCH] == 1
            assert (
                libevdev.InputEvent(libevdev.EV_ABS.ABS_MT_POSITION_X, 5) not in events
            )
            assert (
                libevdev.InputEvent(libevdev.EV_ABS.ABS_MT_POSITION_Y, 10) not in events
            )
            assert evdev.slots[0][libevdev.EV_ABS.ABS_MT_TRACKING_ID] == 0
            assert evdev.slots[0][libevdev.EV_ABS.ABS_MT_POSITION_X] == 50
            assert evdev.slots[0][libevdev.EV_ABS.ABS_MT_POSITION_Y] == 100
            assert evdev.slots[1][libevdev.EV_ABS.ABS_MT_TRACKING_ID] == 1
            assert evdev.slots[1][libevdev.EV_ABS.ABS_MT_POSITION_X] == 150
            assert evdev.slots[1][libevdev.EV_ABS.ABS_MT_POSITION_Y] == 200

            t0.tipswitch = False
            r = uhdev.event(touch=[t0, t1])
            events = uhdev.next_sync_events("Touch Pad")
            self.debug_reports(r, uhdev, events)
            assert evdev.slots[0][libevdev.EV_ABS.ABS_MT_TRACKING_ID] == -1
            assert evdev.slots[1][libevdev.EV_ABS.ABS_MT_TRACKING_ID] == 1
            assert libevdev.InputEvent(libevdev.EV_ABS.ABS_MT_POSITION_X) not in events
            assert libevdev.InputEvent(libevdev.EV_ABS.ABS_MT_POSITION_Y) not in events

            t1.tipswitch = False
            r = uhdev.event(touch=[t1])

            events = uhdev.next_sync_events("Touch Pad")
            self.debug_reports(r, uhdev, events)
            assert evdev.slots[0][libevdev.EV_ABS.ABS_MT_TRACKING_ID] == -1
            assert evdev.slots[1][libevdev.EV_ABS.ABS_MT_TRACKING_ID] == -1


class TestPS3Controller(SonyBaseTest.SonyTest):
    kernel_modules = [PS3_MODULE]

    def create_device(self):
        controller = PS3Controller()
        controller.application_matches = application_matches
        return controller

    @pytest.fixture(autouse=True)
    def start_controller(self):
        # emulate a 'PS' button press to tell the kernel we are ready to accept events
        self.assert_button(17)

        # drain any remaining udev events
        while self.uhdev.dispatch(10):
            pass

        def test_led(self):
            for k, v in self.uhdev.led_classes.items():
                # the kernel might have set a LED for us
                logger.info(f"{k}: {v.brightness}")

                idx = int(k[-1]) - 1
                assert self.uhdev.hw_leds.get_led(idx)[0] == bool(v.brightness)

                v.brightness = 0
                self.uhdev.dispatch(10)
                assert self.uhdev.hw_leds.get_led(idx)[0] is False

                v.brightness = v.max_brightness
                self.uhdev.dispatch(10)
                assert self.uhdev.hw_leds.get_led(idx)[0]


class CalibratedPS4Controller(object):
    # DS4 reports uncalibrated sensor data. Calibration coefficients
    # can be retrieved using a feature report (0x2 USB / 0x5 BT).
    # The values below are the processed calibration values for the
    # DS4s matching the feature reports of PS4ControllerBluetooth/USB
    # as dumped from hid-sony 'ds4_get_calibration_data'.
    #
    # Note we duplicate those values here in case the kernel changes them
    # so we can have tests passing even if hid-tools doesn't have the
    # correct values.
    accelerometer_calibration_data = {
        "x": {"bias": -73, "numer": 16384, "denom": 16472},
        "y": {"bias": -352, "numer": 16384, "denom": 16344},
        "z": {"bias": 81, "numer": 16384, "denom": 16319},
    }
    gyroscope_calibration_data = {
        "x": {"bias": 0, "numer": 1105920, "denom": 17827},
        "y": {"bias": 0, "numer": 1105920, "denom": 17777},
        "z": {"bias": 0, "numer": 1105920, "denom": 17748},
    }


class CalibratedPS4ControllerBluetooth(CalibratedPS4Controller, PS4ControllerBluetooth):
    pass


class TestPS4ControllerBluetooth(SonyBaseTest.SonyPS4ControllerTest):
    def create_device(self):
        controller = CalibratedPS4ControllerBluetooth()
        controller.application_matches = application_matches
        return controller


class CalibratedPS4ControllerUSB(CalibratedPS4Controller, PS4ControllerUSB):
    pass


class TestPS4ControllerUSB(SonyBaseTest.SonyPS4ControllerTest):
    def create_device(self):
        controller = CalibratedPS4ControllerUSB()
        controller.application_matches = application_matches
        return controller


class CalibratedPS5Controller(object):
    # DualSense reports uncalibrated sensor data. Calibration coefficients
    # can be retrieved using feature report 0x09.
    # The values below are the processed calibration values for the
    # DualSene matching the feature reports of PS5ControllerBluetooth/USB
    # as dumped from hid-playstation 'dualsense_get_calibration_data'.
    #
    # Note we duplicate those values here in case the kernel changes them
    # so we can have tests passing even if hid-tools doesn't have the
    # correct values.
    accelerometer_calibration_data = {
        "x": {"bias": 0, "numer": 16384, "denom": 16374},
        "y": {"bias": -114, "numer": 16384, "denom": 16362},
        "z": {"bias": 2, "numer": 16384, "denom": 16395},
    }
    gyroscope_calibration_data = {
        "x": {"bias": 0, "numer": 1105920, "denom": 17727},
        "y": {"bias": 0, "numer": 1105920, "denom": 17728},
        "z": {"bias": 0, "numer": 1105920, "denom": 17769},
    }


class CalibratedPS5ControllerBluetooth(CalibratedPS5Controller, PS5ControllerBluetooth):
    pass


class TestPS5ControllerBluetooth(SonyBaseTest.SonyPS4ControllerTest):
    kernel_modules = [PS5_MODULE]

    def create_device(self):
        controller = CalibratedPS5ControllerBluetooth()
        controller.application_matches = application_matches
        return controller


class CalibratedPS5ControllerUSB(CalibratedPS5Controller, PS5ControllerUSB):
    pass


class TestPS5ControllerUSB(SonyBaseTest.SonyPS4ControllerTest):
    kernel_modules = [PS5_MODULE]

    def create_device(self):
        controller = CalibratedPS5ControllerUSB()
        controller.application_matches = application_matches
        return controller
