import android.content.ContentValues.TAG
import android.media.MediaCodec
import android.media.MediaCodecInfo
import android.media.MediaCodecList
import android.media.MediaFormat
import android.util.Log
import java.nio.ByteBuffer



fun listMediaCodecDecoders() {
    val codecList = MediaCodecList(MediaCodecList.ALL_CODECS) // Get all codecs
    val codecs = codecList.codecInfos

    Log.e(TAG, "Available MediaCodec Decoders:")
    for (codec in codecs) {
        if (!codec.isEncoder) { // Check if the codec is a decoder
            Log.e(TAG, "Decoder: ${codec.name}")
            // List the MIME types supported by the decoder
            val supportedTypes = codec.supportedTypes
            Log.e(TAG, "  Supported Types:")
            for (type in supportedTypes) {
                Log.e(TAG, "    $type")
            }
        }
    }
}


fun decodeAACToPCM(inputData: ByteArray): ShortArray {
//    listMediaCodecDecoders();
    // Media format configuration for AAC
    val mediaFormat = MediaFormat.createAudioFormat(
        MediaFormat.MIMETYPE_AUDIO_OPUS, // MIME type for AAC
        48000, // Sample rate, change this based on your input data
        1      // Channel count, change this based on your input data
    )
//    mediaFormat.setInteger(MediaFormat.KEY_BIT_RATE, 64000)  // 128kbps
//    mediaFormat.setInteger(MediaFormat.KEY_IS_ADTS, 0) // AAC should use ADTS header
//    mediaFormat.setInteger(MediaFormat.KEY_AAC_PROFILE, MediaCodecInfo.CodecProfileLevel.AACObjectLC)

    // Create a decoder for AAC
    val mediaCodec = MediaCodec.createDecoderByType( MediaFormat.MIMETYPE_AUDIO_OPUS);
    mediaCodec.configure(mediaFormat, null, null, 0)
    mediaCodec.start()

    val decodedSamples = mutableListOf<Short>()

    // Variables for handling input and output buffers

    val bufferInfo = MediaCodec.BufferInfo()

    var inputOffset = 0;

    while (inputOffset < inputData.size || true) {
        // Feed input data to the codec
        val inputBufferIndex = mediaCodec.dequeueInputBuffer(100000) // Timeout in microseconds
        if (inputBufferIndex >= 0 && inputOffset < inputData.size) {
            val inputBuffer: ByteBuffer? = mediaCodec.getInputBuffer(inputBufferIndex)
            inputBuffer?.clear()

            // Calculate the number of bytes to write to the buffer
            val chunkSize = kotlin.math.min(inputBuffer?.capacity() ?: 0, inputData.size - inputOffset)
            Log.e(TAG, "Chunk size: " + chunkSize.toString())
            inputBuffer?.put(inputData, inputOffset, chunkSize)
            inputOffset += chunkSize

            // Pass the data to the codec
            mediaCodec.queueInputBuffer(inputBufferIndex, 0, chunkSize, 0, 0)
        }

        // Process output data
        val outputBufferIndex = mediaCodec.dequeueOutputBuffer(bufferInfo, 10000)
        Log.e(TAG, "Output buffer index: " + outputBufferIndex.toString())
        if (outputBufferIndex >= 0) {
            val outputBuffer: ByteBuffer? = mediaCodec.getOutputBuffer(outputBufferIndex)

            // Convert byte buffer to PCM data (16-bit integers)
            val pcmData = ShortArray(bufferInfo.size / 2)
            outputBuffer?.asShortBuffer()?.get(pcmData)

            // Add PCM data to the final output array
            decodedSamples.addAll(pcmData.toList())

            // Release the output buffer
            mediaCodec.releaseOutputBuffer(outputBufferIndex, false)
        } else if (outputBufferIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
            // Handle format changes, if needed
            mediaCodec.outputFormat
        } else if (outputBufferIndex == MediaCodec.INFO_TRY_AGAIN_LATER) {
            // Output buffer not available, retry later
            if (inputOffset >= inputData.size) break
        }
    }

    // Release the codec when done
    mediaCodec.stop()
    mediaCodec.release()

    return decodedSamples.toShortArray()
}
