//
//  WebSocketManager.swift
//  AcaMate
//
//  Created by TAnine on 2/17/25.
//

import Foundation
import Combine

import Starscream

// SignalR은 메세지의 끝이 \u{1E} 해당 유니코드 문자를 원함
class WebSocketManager: ObservableObject ,WebSocketDelegate {
    
    @Published var socket: WebSocket?
    @Published var receivedMessage: [String] = []
    
    init() {
        guard let url = URL(string: "\(WS_URL)/chatHub?transport=webSockets") else { return }
        var request = URLRequest(url: url)
        request.timeoutInterval = 5
        request.setValue("application/json", forHTTPHeaderField: "Content-Type")
        
        request.setValue("Upgrade", forHTTPHeaderField: "Connection")
        
        socket = WebSocket(request: request)
        socket?.delegate = self
    }
    
    func connect() {
        socket?.connect()
        printLog("TRY CONNECT SOCKET")
        DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
            let handShakeMsg = """
            {"protocol":"json","version":1}\u{1E}
            """
            self.socket?.write(string: handShakeMsg)
        }
    }
    func disconnect() {
        socket?.disconnect()
        socket?.delegate = nil  // 추가: delegate 해제
        socket = nil            // 필요시, 소켓 객체 해제
        printLog("CLOSE SOCKET")
    
    }
    
    func sendMessage(_ message: String) {
        let json = """
        {
            "type": 1,
            "target":"SendMessage",
            "arguments":["iOS", "\(message)"]
        }\u{1E}
        """
        socket?.write(string: json)
        printLog("SEND THE MESSAGE: \(message)")
    }
    
    func didReceive(event: Starscream.WebSocketEvent, client: any Starscream.WebSocketClient) {
        switch event {
    
        case .connected(let header):
            printLog("CONNECTED : \(header)")
        case .disconnected(let reason, let code):
            printLog("DISCONNECTED: [\(code)] - \(reason)")
        case .text(let text):
            receivedMessage.append(text)
            printLog("SERVER SAID: \(text)")
        case .binary(let binary):
            printLog("BINARY?: \(binary)")
        case .error(let error):
            printLog("ERROR!: \(error)")
        case .cancelled:
            printLog("SOCKET CONNECTED CANCELLED!!!")
        default:
            break
        }
    }
}
