package io.stellarfrontier.stellarplugin

import org.java_websocket.client.WebSocketClient
import org.java_websocket.handshake.ServerHandshake
import java.net.URI
import java.util.logging.Logger
import java.util.concurrent.ConcurrentLinkedQueue

class SocketClient(uri: URI, private val logger: Logger) : WebSocketClient(uri) {

    private @Volatile var shouldReconnect = true

    private val messageQueue = ConcurrentLinkedQueue<String>()
    private val lock = Any()

    fun shutdown() {
        shouldReconnect = false
        close()
    }

    override fun onOpen(handshakedata: ServerHandshake?) {
        logger.info("Connected to WebSocket server")
        // Socket.IO connection is established when we receive the Open packet (0)
        // We must send the Connect packet (40) to join the default namespace
        send("40")
        logger.info("Sent Socket.IO Connect packet")

        flushQueue()
    }

    private fun flushQueue() {
        synchronized(lock) {
            while (!messageQueue.isEmpty()) {
                val msg = messageQueue.poll()
                send(msg)
                logger.info("Flushed queued message: $msg")
            }
        }
    }

    override fun onMessage(message: String?) {
        if (message == "2") {
            send("3")
            return
        }
        logger.info("Received message: $message")
    }
    
    fun sendSocketEvent(eventName: String, jsonObject: String) {
        val packet = "42[\"$eventName\",$jsonObject]"
        if (isOpen) {
            logger.info("Sending event directly (via queue): $packet")
            messageQueue.add(packet)
            flushQueue()
        } else {
            messageQueue.add(packet)
            logger.info("Connection closed, queued event: $packet")
        }
    }

    override fun onClose(code: Int, reason: String?, remote: Boolean) {
        if (shouldReconnect) {
            logger.info("Disconnected from WebSocket server: $reason. Reconnecting in 5 seconds...")
            Thread {
                try {
                    Thread.sleep(5000)
                    reconnect()
                } catch (e: Exception) {
                    logger.severe("Failed to reconnect: ${e.message}")
                }
            }.start()
        } else {
            logger.info("Disconnected from WebSocket server: $reason")
        }
    }

    override fun onError(ex: Exception?) {
        logger.severe("WebSocket error: ${ex?.message}")
    }
}
