package com.example.gesturerecognition

import android.content.Context
import android.media.AudioAttributes
import android.media.SoundPool
import android.util.Log

class SoundManager(private val context: Context) {
    private var soundPool: SoundPool? = null
    private val soundMap = mutableMapOf<String, Int>()
    private val TAG = "SoundManager"

    // Máximo de sons simultâneos
    private val maxStreams = 10

    // Controle de loops (sons que ficam tocando)
    private var currentLoopStreamId: Int? = null
    private var currentLoopGesture: String? = null

    init {
        initializeSoundPool()
        loadSounds()
    }

    private fun initializeSoundPool() {
        val audioAttributes = AudioAttributes.Builder()
            .setUsage(AudioAttributes.USAGE_MEDIA)
            .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
            .build()

        soundPool = SoundPool.Builder()
            .setMaxStreams(maxStreams)
            .setAudioAttributes(audioAttributes)
            .build()
    }

    private fun loadSounds() {
        try {
            // Carrega os sons específicos do usuário
            loadSound("gesture2", R.raw.eraser)
            loadSound("gesture3", R.raw.explosion)
            loadSound("gesture4", R.raw.do_it_again_baby)
            loadSound("gesture7", R.raw.brush_beat_brazil)
            loadSound("gesture8", R.raw.loose_brazil2)

            Log.d(TAG, "Todos os sons carregados com sucesso")

        } catch (e: Exception) {
            Log.e(TAG, "Erro ao carregar sons: ${e.message}")
        }
    }

    private fun loadSound(gestureId: String, resourceId: Int) {
        try {
            soundPool?.let { pool ->
                val soundId = pool.load(context, resourceId, 1)
                soundMap[gestureId] = soundId
                Log.d(TAG, "Som carregado: $gestureId -> $soundId")
            }
        } catch (e: Exception) {
            Log.e(TAG, "Erro ao carregar som $gestureId: ${e.message}")
        }
    }

    /**
     * Reproduz o som correspondente ao gesto reconhecido
     * Gesto 1: Para todos os sons
     * Gestos 2, 3, 4: Tocam uma vez
     * Gestos 7, 8: Tocam em loop (um por vez)
     */
    fun playGestureSound(gestureId: String, volume: Float = 1.0f) {
        try {
            when (gestureId) {
                "gesture1" -> {
                    // Gesto 1: Para todos os sons
                    stopAllSounds()
                    Log.d(TAG, "Todos os sons parados pelo gesto 1")
                }

                "gesture7", "gesture8" -> {
                    // Gestos 7 e 8: Loop (um por vez)
                    playLoopSound(gestureId, volume)
                }

                "gesture2", "gesture3", "gesture4" -> {
                    // Gestos 2, 3, 4: Tocam uma vez
                    playOneShotSound(gestureId, volume)
                }

                else -> {
                    Log.w(TAG, "Gesto não mapeado: $gestureId")
                }
            }
        } catch (e: Exception) {
            Log.e(TAG, "Erro ao reproduzir som para gesto $gestureId: ${e.message}")
        }
    }

    /**
     * Toca sons que devem tocar apenas uma vez
     */
    private fun playOneShotSound(gestureId: String, volume: Float) {
        val soundId = soundMap[gestureId]

        if (soundId != null) {
            soundPool?.play(soundId, volume, volume, 1, 0, 1.0f) // loop = 0 (uma vez)
            Log.d(TAG, "Som one-shot reproduzido: $gestureId")
        } else {
            Log.w(TAG, "Som não encontrado para gesto: $gestureId")
        }
    }

    /**
     * Toca sons em loop (gestos 7 e 8)
     * Para o loop anterior e inicia o novo
     */
    private fun playLoopSound(gestureId: String, volume: Float) {
        val soundId = soundMap[gestureId]

        if (soundId != null) {
            // Se já há um loop tocando, para ele
            currentLoopStreamId?.let { streamId ->
                soundPool?.stop(streamId)
                Log.d(TAG, "Loop anterior parado: $currentLoopGesture")
            }

            // Inicia novo loop
            val streamId = soundPool?.play(soundId, volume, volume, 1, -1, 1.0f) // loop = -1 (infinito)
            currentLoopStreamId = streamId
            currentLoopGesture = gestureId

            Log.d(TAG, "Novo loop iniciado: $gestureId")
        } else {
            Log.w(TAG, "Som não encontrado para gesto: $gestureId")
        }
    }

    /**
     * Para todos os sons que estão tocando
     */
    fun stopAllSounds() {
        try {
            // Para o loop atual se existir
            currentLoopStreamId?.let { streamId ->
                soundPool?.stop(streamId)
                Log.d(TAG, "Loop parado: $currentLoopGesture")
            }
            currentLoopStreamId = null
            currentLoopGesture = null

            // Para todos os outros sons
            soundPool?.autoPause()
            Log.d(TAG, "Todos os sons parados")
        } catch (e: Exception) {
            Log.e(TAG, "Erro ao parar sons: ${e.message}")
        }
    }

    /**
     * Resume todos os sons pausados (não reativa loops parados)
     */
    fun resumeAllSounds() {
        try {
            soundPool?.autoResume()
            Log.d(TAG, "Sons one-shot resumidos")
        } catch (e: Exception) {
            Log.e(TAG, "Erro ao resumir sons: ${e.message}")
        }
    }

    /**
     * Ajusta o volume de todos os sons
     */
    fun setVolume(volume: Float) {
        try {
            soundMap.values.forEach { soundId ->
                soundPool?.setVolume(soundId, volume, volume)
            }
            Log.d(TAG, "Volume ajustado para: $volume")
        } catch (e: Exception) {
            Log.e(TAG, "Erro ao ajustar volume: ${e.message}")
        }
    }

    /**
     * Libera recursos do SoundPool
     */
    fun release() {
        try {
            stopAllSounds()
            soundPool?.release()
            soundPool = null
            soundMap.clear()
            currentLoopStreamId = null
            currentLoopGesture = null
            Log.d(TAG, "SoundManager liberado")
        } catch (e: Exception) {
            Log.e(TAG, "Erro ao liberar SoundManager: ${e.message}")
        }
    }

    /**
     * Mapeia o resultado do classificador para ID do gesto
     * Ajuste esta função de acordo com os resultados do seu modelo
     */
    fun mapGestureResultToId(gestureResult: String): String {
        return when (gestureResult.lowercase().trim()) {
            "1", "gesture1", "gesto 1" -> "gesture1"  // Para todos os sons
            "2", "gesture2", "gesto 2" -> "gesture2"  // Eraser (uma vez)
            "3", "gesture3", "gesto 3" -> "gesture3"  // Explosion (uma vez)
            "4", "gesture4", "gesto 4" -> "gesture4"  // Do It Again Baby (uma vez)
            "7", "gesture7", "gesto 7" -> "gesture7"  // brush_beat_brazil (loop)
            "8", "gesture8", "gesto 8"-> "gesture8"  // loose_brazil2 (loop)
            else -> "unknown" // Não faz nada para gestos não mapeados
        }
    }
}