package com.xyzshell.andinfo.libs

import android.content.Context
import android.hardware.input.InputManager
import android.os.Build
import android.view.InputDevice
import android.view.KeyCharacterMap
import androidx.annotation.RequiresApi

class InputInfo(private val context: Context) {
    private val inputManager = context.getSystemService(InputManager::class.java)

            fun getInputDevices(): List<InputDeviceInfo> {
                return inputManager.inputDeviceIds.toList().mapNotNull { id ->
                    inputManager.getInputDevice(id)?.let { device -> InputDeviceInfo(device) }
                }
            }

    fun getInputDevice(deviceId: Int): InputDeviceInfo? {
        return inputManager.getInputDevice(deviceId)?.let { device ->
            InputDeviceInfo(device)
        }
    }

    @RequiresApi(Build.VERSION_CODES.S)
    fun getMaximumObscuringOpacityForTouch(): Float {
        return inputManager.maximumObscuringOpacityForTouch
    }

    @RequiresApi(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
    fun isStylusPointerIconEnabled(): Boolean {
        return inputManager.isStylusPointerIconEnabled
    }

    data class InputDeviceInfo(val inputDevice: InputDevice) {
        val id: Int get() = inputDevice.id
        val controllerNumber: Int get() = inputDevice.controllerNumber
        val vendorId: Int get() = inputDevice.vendorId
        val productId: Int get() = inputDevice.productId
        val descriptor: String? get() = inputDevice.descriptor
        val isVirtual: Boolean get() = inputDevice.isVirtual
        val isExternal: Boolean
            get() = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
                inputDevice.isExternal
            } else {
                false
            }
        val name: String get() = inputDevice.name
        val sources: Int get() = inputDevice.sources
        val keyboardType: Int get() = inputDevice.keyboardType
        val keyCharacterMapKeyboardType: Int get() = inputDevice.keyCharacterMap.keyboardType
        val motionRangesCount: Int get() = inputDevice.motionRanges.size
        val hasVibrator: Boolean
            get() = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
                inputDevice.vibratorManager.vibratorIds.isNotEmpty()
            } else {
                @Suppress("DEPRECATION")
                inputDevice.vibrator.hasVibrator()
            }
        val isEnabled: Boolean
            get() = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
                inputDevice.isEnabled
            } else {
                true
            }
        val hasMicrophone: Boolean get() = inputDevice.hasMicrophone()

        companion object {
            val keyboardTypeToString = mapOf(
                InputDevice.KEYBOARD_TYPE_NONE to "None",
                InputDevice.KEYBOARD_TYPE_NON_ALPHABETIC to "Non-alphabetic",
                InputDevice.KEYBOARD_TYPE_ALPHABETIC to "Alphabetic",
            )

            val keyCharacterMapKeyboardTypeToString = mapOf(
                KeyCharacterMap.NUMERIC to "Numeric",
                KeyCharacterMap.PREDICTIVE to "Predictive",
                KeyCharacterMap.ALPHA to "Alpha",
                KeyCharacterMap.FULL to "Full",
                KeyCharacterMap.SPECIAL_FUNCTION to "Special Function",
            )

            val sourceClassToString = mapOf(
                InputDevice.SOURCE_CLASS_BUTTON to "Button",
                InputDevice.SOURCE_CLASS_POINTER to "Pointer",
                InputDevice.SOURCE_CLASS_TRACKBALL to "Trackball",
                InputDevice.SOURCE_CLASS_POSITION to "Position",
                InputDevice.SOURCE_CLASS_JOYSTICK to "Joystick",
            )

            val sourceToString = mapOf(
                InputDevice.SOURCE_KEYBOARD to "Keyboard",
                InputDevice.SOURCE_DPAD to "D-Pad",
                InputDevice.SOURCE_GAMEPAD to "Gamepad",
                InputDevice.SOURCE_TOUCHSCREEN to "Touchscreen",
                InputDevice.SOURCE_MOUSE to "Mouse",
                InputDevice.SOURCE_STYLUS to "Stylus",
                InputDevice.SOURCE_TRACKBALL to "Trackball",
                InputDevice.SOURCE_TOUCHPAD to "Touchpad",
                InputDevice.SOURCE_TOUCH_NAVIGATION to "Touch Navigation",
                InputDevice.SOURCE_ROTARY_ENCODER to "Rotary Encoder",
                InputDevice.SOURCE_JOYSTICK to "Joystick",
                InputDevice.SOURCE_HDMI to "HDMI",
            )
        }
    }
}
