package de.ladkau.schwertundmagieonpebblecompanionapp

import android.content.Context
import android.graphics.Bitmap
import android.graphics.Canvas
import android.graphics.Rect
import android.util.AttributeSet
import android.view.View
import java.nio.ByteBuffer

/**
 * Renders the VICE 320×200 ARGB framebuffer into a View.
 *
 * Frame data is written from the emulator thread via captureFrame(), then the
 * view is invalidated so onDraw() runs on the main thread under Choreographer
 * vsync.  All canvas operations stay on the main thread, giving smooth rendering
 * synchronized with the hardware display refresh rate.
 */
class C64DisplayView @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null
) : View(context, attrs) {

    private val bitmap = Bitmap.createBitmap(320, 200, Bitmap.Config.ARGB_8888)

    /* Two ByteBuffers: the emulator thread writes to backBuf, then atomically
     * swaps it to frontBuf.  onDraw() reads frontBuf without holding the lock. */
    private val buf0: ByteBuffer = ByteBuffer.allocateDirect(320 * 200 * 4)
    private val buf1: ByteBuffer = ByteBuffer.allocateDirect(320 * 200 * 4)
    @Volatile private var frontBuf: ByteBuffer = buf0
    private var backBuf: ByteBuffer = buf1

    private val srcRect = Rect(0, 0, 320, 200)
    private var dstRect = Rect()

    init {
        setBackgroundColor(android.graphics.Color.BLACK)
        setLayerType(LAYER_TYPE_HARDWARE, null)
    }

    /** Called from the emulator thread — copies one C64 frame into the back buffer. */
    fun captureFrame(engine: C64Engine) {
        backBuf.rewind()
        engine.getVideoBuffer(backBuf)
        /* Swap: make the freshly-written buffer visible to onDraw() */
        val tmp = frontBuf
        frontBuf = backBuf
        backBuf = tmp
    }

    override fun onDraw(canvas: Canvas) {
        val buf = frontBuf
        buf.rewind()
        bitmap.copyPixelsFromBuffer(buf)
        canvas.drawBitmap(bitmap, srcRect, dstRect, null)
    }

    override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
        if (w <= 0 || h <= 0) return
        val scale = minOf(w.toFloat() / 320f, h.toFloat() / 200f)
        val sw = (320 * scale).toInt()
        val sh = (200 * scale).toInt()
        val ox = ((w - sw) / 2).toInt()
        val oy = ((h - sh) / 2).toInt()
        dstRect = Rect(ox, oy, ox + sw, oy + sh)
    }
}
