package de.ladkau.schwertundmagieonpebblecompanionapp

import android.content.Context
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.graphics.RectF
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.View

data class C64Key(val label: String, val code: Int, val widthWeight: Float = 1f)

/** Callback fired when a key is pressed or released. */
typealias KeyEventListener = (key: C64Key, pressed: Boolean) -> Unit

/**
 * Virtual C64 keyboard.  Draws four rows of keys and fires [onKeyEvent]
 * on touch down / up.
 */
class C64KeyboardView @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null
) : View(context, attrs) {

    var onKeyEvent: KeyEventListener? = null

    private val rows: List<List<C64Key>> = listOf(
        listOf(
            C64Key("F1", C64Engine.KEY_F1), C64Key("F3", C64Engine.KEY_F3),
            C64Key("F5", C64Engine.KEY_F5), C64Key("F7", C64Engine.KEY_F7),
            C64Key("RUN\nSTOP", C64Engine.KEY_RUNSTOP, 1.5f)
        ),
        listOf(
            C64Key("1", C64Engine.KEY_1), C64Key("2", C64Engine.KEY_2),
            C64Key("3", C64Engine.KEY_3), C64Key("4", C64Engine.KEY_4),
            C64Key("5", C64Engine.KEY_5), C64Key("6", C64Engine.KEY_6),
            C64Key("7", C64Engine.KEY_7), C64Key("8", C64Engine.KEY_8),
            C64Key("9", C64Engine.KEY_9), C64Key("0", C64Engine.KEY_0)
        ),
        listOf(
            C64Key("Q", C64Engine.KEY_Q), C64Key("W", C64Engine.KEY_W),
            C64Key("E", C64Engine.KEY_E), C64Key("R", C64Engine.KEY_R),
            C64Key("Y", C64Engine.KEY_Y), C64Key("N", C64Engine.KEY_N),
            C64Key("RETURN", C64Engine.KEY_RETURN, 2f)
        ),
        listOf(
            C64Key("SPACE", C64Engine.KEY_SPACE, 6f)
        )
    )

    // Map pointer-id → key currently held down by that finger
    private val heldKeys = mutableMapOf<Int, C64Key>()

    private val keyPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
        color = Color.parseColor("#2C2C6C")
    }
    private val pressedPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
        color = Color.parseColor("#6464C0")
    }
    private val textPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
        color = Color.WHITE
        textAlign = Paint.Align.CENTER
    }

    // Pre-computed key rectangles for hit-testing: rowIndex → list of (rect, key)
    private var keyRects: List<List<Pair<RectF, C64Key>>> = emptyList()

    override fun onSizeChanged(w: Int, h: Int, oldW: Int, oldH: Int) {
        super.onSizeChanged(w, h, oldW, oldH)
        buildKeyRects(w.toFloat(), h.toFloat())
    }

    private fun buildKeyRects(totalW: Float, totalH: Float) {
        val rowH = totalH / rows.size
        val pad = 4f
        keyRects = rows.mapIndexed { rowIdx, row ->
            val totalUnits = row.sumOf { it.widthWeight.toDouble() }.toFloat()
            val unitW = totalW / totalUnits
            var x = 0f
            row.map { key ->
                val kw = key.widthWeight * unitW
                val rect = RectF(x + pad, rowIdx * rowH + pad, x + kw - pad, (rowIdx + 1) * rowH - pad)
                x += kw
                rect to key
            }
        }
    }

    override fun onDraw(canvas: Canvas) {
        val held = heldKeys.values.toSet()
        textPaint.textSize = height / (rows.size * 2.5f)

        for (row in keyRects) {
            for ((rect, key) in row) {
                val paint = if (key in held) pressedPaint else keyPaint
                canvas.drawRoundRect(rect, 6f, 6f, paint)
                val ty = rect.centerY() - (textPaint.ascent() + textPaint.descent()) / 2
                canvas.drawText(key.label, rect.centerX(), ty, textPaint)
            }
        }
    }

    override fun onTouchEvent(event: MotionEvent): Boolean {
        val idx = event.actionIndex
        val pid = event.getPointerId(idx)
        val ex  = event.getX(idx)
        val ey  = event.getY(idx)

        when (event.actionMasked) {
            MotionEvent.ACTION_DOWN, MotionEvent.ACTION_POINTER_DOWN -> {
                val key = keyAt(ex, ey) ?: return true
                heldKeys[pid] = key
                onKeyEvent?.invoke(key, true)
                invalidate()
            }
            MotionEvent.ACTION_UP, MotionEvent.ACTION_POINTER_UP,
            MotionEvent.ACTION_CANCEL -> {
                val key = heldKeys.remove(pid) ?: return true
                onKeyEvent?.invoke(key, false)
                invalidate()
            }
        }
        return true
    }

    private fun keyAt(x: Float, y: Float): C64Key? {
        for (row in keyRects) {
            for ((rect, key) in row) {
                if (rect.contains(x, y)) return key
            }
        }
        return null
    }
}
