package com.lazy.emulate.input

import com.lazy.emulate.data.PreferencesManager
import com.lazy.emulate.emulation.ConsoleType

class ButtonMappingManager(private val preferencesManager: PreferencesManager) {

    private val defaultMappings = mapOf(
        ConsoleType.PS1 to mapOf(
            GamepadButton.FACE_BOTTOM to 0,   // Cross -> B
            GamepadButton.FACE_RIGHT to 8,    // Circle -> A
            GamepadButton.FACE_LEFT to 1,     // Square -> Y
            GamepadButton.FACE_TOP to 9,      // Triangle -> X
            GamepadButton.DPAD_UP to 4,
            GamepadButton.DPAD_DOWN to 5,
            GamepadButton.DPAD_LEFT to 6,
            GamepadButton.DPAD_RIGHT to 7,
            GamepadButton.L1 to 10,
            GamepadButton.R1 to 11,
            GamepadButton.L2 to 12,
            GamepadButton.R2 to 13,
            GamepadButton.L3 to 14,
            GamepadButton.R3 to 15,
            GamepadButton.SELECT to 2,
            GamepadButton.START to 3
        ),
        ConsoleType.NES to mapOf(
            GamepadButton.FACE_BOTTOM to 0,   // B
            GamepadButton.FACE_RIGHT to 8,    // A
            GamepadButton.DPAD_UP to 4,
            GamepadButton.DPAD_DOWN to 5,
            GamepadButton.DPAD_LEFT to 6,
            GamepadButton.DPAD_RIGHT to 7,
            GamepadButton.SELECT to 2,
            GamepadButton.START to 3
        ),
        ConsoleType.SNES to mapOf(
            GamepadButton.FACE_BOTTOM to 0,   // B
            GamepadButton.FACE_RIGHT to 8,    // A
            GamepadButton.FACE_LEFT to 1,     // Y
            GamepadButton.FACE_TOP to 9,      // X
            GamepadButton.L1 to 10,           // L
            GamepadButton.R1 to 11,           // R
            GamepadButton.DPAD_UP to 4,
            GamepadButton.DPAD_DOWN to 5,
            GamepadButton.DPAD_LEFT to 6,
            GamepadButton.DPAD_RIGHT to 7,
            GamepadButton.SELECT to 2,
            GamepadButton.START to 3
        ),
        ConsoleType.GENESIS to mapOf(
            // Genesis Plus GX default retropad -> Genesis mapping
            GamepadButton.FACE_BOTTOM to 1,   // Genesis A (RETRO_Y)
            GamepadButton.FACE_RIGHT to 0,    // Genesis B (RETRO_B)
            GamepadButton.FACE_LEFT to 8,     // Genesis C (RETRO_A)
            GamepadButton.FACE_TOP to 9,      // Genesis Y (6-button)
            GamepadButton.L1 to 10,           // Genesis X (6-button)
            GamepadButton.R1 to 11,           // Genesis Z (6-button)
            GamepadButton.C_BUTTON to 8,      // alt C
            GamepadButton.Z_BUTTON to 11,     // alt Z
            GamepadButton.DPAD_UP to 4,
            GamepadButton.DPAD_DOWN to 5,
            GamepadButton.DPAD_LEFT to 6,
            GamepadButton.DPAD_RIGHT to 7,
            GamepadButton.MODE to 2,          // Genesis Mode
            GamepadButton.START to 3
        )
    )

    private var cachedConsole: ConsoleType? = null
    private var cachedMapping: Map<GamepadButton, Int> = emptyMap()
    private var controllerRemap: Map<GamepadButton, GamepadButton> = emptyMap()

    fun getRetroId(consoleType: ConsoleType, button: GamepadButton): Int {
        if (cachedConsole != consoleType) {
            rebuildCache(consoleType)
        }
        return cachedMapping[button] ?: -1
    }

    fun remapControllerButton(button: GamepadButton): GamepadButton {
        if (controllerRemap.isEmpty()) {
            controllerRemap = preferencesManager.getControllerButtonRemap()
        }
        return controllerRemap[button] ?: button
    }

    fun setButtonMapping(consoleType: ConsoleType, button: GamepadButton, retroId: Int) {
        preferencesManager.setButtonMapping(consoleType, button, retroId)
        if (cachedConsole == consoleType) {
            cachedMapping = cachedMapping.toMutableMap().apply { put(button, retroId) }
        }
    }

    fun setControllerRemap(from: GamepadButton, to: GamepadButton) {
        preferencesManager.setControllerButtonRemap(from, to)
        controllerRemap = controllerRemap.toMutableMap().apply { put(from, to) }
    }

    fun resetToDefaults(consoleType: ConsoleType) {
        preferencesManager.clearButtonMappings(consoleType)
        cachedConsole = null
    }

    fun resetControllerRemaps() {
        preferencesManager.clearControllerRemaps()
        controllerRemap = emptyMap()
    }

    fun getMapping(consoleType: ConsoleType): Map<GamepadButton, Int> {
        if (cachedConsole != consoleType) {
            rebuildCache(consoleType)
        }
        return cachedMapping
    }

    fun getControllerRemaps(): Map<GamepadButton, GamepadButton> {
        if (controllerRemap.isEmpty()) {
            controllerRemap = preferencesManager.getControllerButtonRemap()
        }
        return controllerRemap
    }

    fun getDefaultMapping(consoleType: ConsoleType): Map<GamepadButton, Int> {
        return defaultMappings[consoleType] ?: emptyMap()
    }

    private fun rebuildCache(consoleType: ConsoleType) {
        val defaults = defaultMappings[consoleType] ?: emptyMap()
        val overrides = preferencesManager.getButtonMapping(consoleType)
        cachedMapping = defaults + overrides
        cachedConsole = consoleType
    }
}
