package com.example.cmpt362_group30_maze_game.game

import android.content.Context
import android.hardware.Sensor
import android.hardware.SensorEvent
import android.hardware.SensorEventListener
import android.hardware.SensorManager
import kotlin.math.abs

/**
 * Provides physical acceleration data when the phone is slid
 * flat on a table. The phone is expected to be face-up.
 *
 * We only use the Y-axis for forward/back sliding.
 * Convention: ay > 0 == phone pushed FORWARD (toward the front camera).
 */
class MotionController(context: Context) : SensorEventListener {

    private val sm = context.getSystemService(Context.SENSOR_SERVICE) as SensorManager
    private val accel: Sensor? = sm.getDefaultSensor(Sensor.TYPE_LINEAR_ACCELERATION)

    // Low-pass filter smoothing factor.
    // 0.4–0.5 is a good compromise between smoothness and responsiveness.
    private val alpha = 0.45f

    // Latest raw readings (for debugging if needed)
    private var rawX = 0f
    private var rawY = 0f
    private var rawZ = 0f

    // Filtered outputs
    var ax: Float = 0f
        private set

    // Forward / back component (screen-up, long edge direction).
    // Positive = phone pushed FORWARD.
    var ay: Float = 0f
        private set

    // Deadband: ignore tiny jitters from sensor noise
    var deadband = 0.04f

    fun start() {
        accel?.also { sm.registerListener(this, it, SensorManager.SENSOR_DELAY_GAME) }
    }

    fun stop() {
        sm.unregisterListener(this)
        ax = 0f
        ay = 0f
    }

    override fun onSensorChanged(ev: SensorEvent) {
        if (ev.sensor.type != Sensor.TYPE_LINEAR_ACCELERATION) return

        rawX = ev.values[0]
        rawY = ev.values[1]
        rawZ = ev.values[2]

        // Map device axis so that:
        //  - Sliding the phone TOWARD the front camera => ay > 0 (forward)
        var forward = -rawY   // the minus usually matches real device behaviour

        // Clamp to a moderate range so extreme spikes don't fling the sub
        forward = forward.coerceIn(-3f, 3f)

        // Ignore tiny jitter
        if (abs(forward) < deadband) forward = 0f

        // Smooth using low-pass filter
        ay = alpha * forward + (1f - alpha) * ay

        // We don't use sideways motion right now
        ax = 0f
    }

    override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) {
        // Not used
    }
}
