package audio

import audio.Bass.BASS_STREAM_DECODE
import codes.Somecodes.Companion.ValidFile
import com.sun.jna.Memory
import java.net.DatagramPacket
import java.net.DatagramSocket
import java.net.InetSocketAddress
import java.net.SocketAddress
import java.util.function.BiConsumer
import kotlinx.coroutines.CoroutineName
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch

@Deprecated("Sepertinya gak jadi pake ini")
@Suppress("unused")
class UDPSenderFromFile(val fileName: String, val bytesPerPackage: Int=1024, targetIP: Array<String>, targetPort: Int ) {
    val bass: Bass = Bass.Instance
    var filehandle: Int = 0
    var listSocketAddress = ArrayList<SocketAddress>()

    var initialized: Boolean = false; private set
    var isRunning: Boolean = false; private set
    var bytesSent: Int = 0; private set

    init {
        if (ValidFile(fileName)){
            bass.BASS_SetDevice(0)
            val handle = bass.BASS_StreamCreateFile(false, fileName, 0,0, BASS_STREAM_DECODE)
            if (handle!=0){
                // test buka file berhasil, tutup lagi
                bass.BASS_StreamFree(handle)
                if (targetPort>0 && targetPort<65535){
                    if (targetIP.isNotEmpty()){
                        var validIPs = true
                        for(ip in targetIP){
                            try{
                                var so = InetSocketAddress(ip, targetPort)
                                listSocketAddress.add(so)
                            } catch (e : Exception){
                                validIPs = false
                            }
                        }

                        if (validIPs){
                            initialized = true
                        }

                    }
                }
            }

        }
    }

    fun Start(callback: BiConsumer<Boolean, String>){
        if (initialized){

            val scope = CoroutineScope(Dispatchers.Default)
            scope.launch(CoroutineName("UDPSenderFromFile $fileName")) {
                try {
                    val socket = DatagramSocket()
                    bass.BASS_SetDevice(0) // Set to No Sound Device
                    val handle = bass.BASS_StreamCreateFile(false, fileName, 0, 0, BASS_STREAM_DECODE)
                    if (handle!=0){
                        isRunning = true
                        bytesSent = 0
                        callback.accept(true,"UDPSenderFromFile started, sending $fileName to ${listSocketAddress.size} targets")
                        while(isRunning){
                            val buffer = Memory(bytesPerPackage.toLong())
                            val bytesRead = bass.BASS_ChannelGetData(handle, buffer, bytesPerPackage)
                            if (bytesRead > 0) {
                                for(so in listSocketAddress){
                                    val bytes = buffer.getByteArray(0, bytesRead)
                                    socket.send(DatagramPacket(bytes, bytes.size, so))
                                    bytesSent += bytes.size
                                }

                            } else isRunning = false
                        }
                        callback.accept(false,"UDPSenderFromFile finished sending $fileName")
                        bass.BASS_StreamFree(handle)
                        socket.close()
                    } else callback.accept(false, "Failed to open file $fileName for reading")
                } catch (e : Exception){
                    callback.accept(false, "Error in UDPSenderFromFile: ${e.message}")
                    isRunning = false
                }
            }


        } else callback.accept(false, "UDP Sender not initialized, check file and target IP/Port")

    }

    fun Stop(){
        isRunning = false
    }
}