//
//  See LICENSE folder for this template’s licensing information.
//
//  Abstract:
//  Bonjourサービスサーバー

import Foundation
import Network
import UIKit
import PlaygroundSupport

protocol TCPServerDelegate: AnyObject {
    func didReceiveMessage(messageText: String, codeText: String)
}

public class TCPServer {
    let port: NWEndpoint.Port
    var listener: NWListener?
    var netService: NetService?
    weak var delegate: TCPServerDelegate? // デリゲート
    
    private let maxReconnectAttempts = 5
    private var reconnectAttempts = 0
    
    init(port: UInt16) {
        self.port = NWEndpoint.Port(rawValue: port)!
    }
    
    func start() {
        stop() // 最初に既存のリスナーと接続をクリア
        self.delegate?.didReceiveMessage(messageText: "受信を開始しました。", codeText: "")
        setupListener()
    }
    
    func stop() {
        // 既存のリスナーと接続をキャンセル
        listener?.cancel()
        listener = nil

        netService?.stop()
        netService = nil
    }
    
    private func setupListener() {
        do {
            listener = try NWListener(using: .tcp, on: port)
            listener?.newConnectionHandler = { [weak self] connection in
                self?.setupConnection(connection)
            }
            listener?.start(queue: .main)
            
            // Bonjourサービスを公開
            netService = NetService(domain: "local.", type: "_playgnd._tcp.", name: "TeacherServer", port: Int32(port.rawValue))
            netService?.publish()
            
            self.delegate?.didReceiveMessage(messageText: "Server started on port \(port)", codeText: "")

        } catch {
            self.delegate?.didReceiveMessage(messageText: "Failed to start server: \(error)", codeText: "")
            print("Failed to start server: \(error)")
            handleReconnect()
        }
    }
    
    private func setupConnection(_ connection: NWConnection) {
        connection.start(queue: .main)
        connection.receive(minimumIncompleteLength: 1, maximumLength: 65536) { [weak self] data, _, isComplete, error in
            guard let self = self else { return }
            
            if let data = data, !data.isEmpty {
                // 受信したデータをJSONとしてデコードする
                do {
                    if let jsonDict = try JSONSerialization.jsonObject(with: data, options: []) as? [String: String] {
                        let messageText = jsonDict["message"] ?? ""
                        let codeText = jsonDict["code"] ?? ""
                        self.delegate?.didReceiveMessage(messageText: messageText, codeText: codeText)
                    } else {
                        print("Invalid JSON format")
                    }
                } catch {
                    print("Failed to decode JSON data: \(error)")
                }
            }
            if isComplete || error != nil {
                connection.cancel()
                self.handleReconnect()
            }
        }
    }
    
    private func handleReconnect() {
        guard reconnectAttempts < maxReconnectAttempts else {
            self.delegate?.didReceiveMessage(messageText: "Max reconnect attempts reached.", codeText: "")
            return
        }
        
        reconnectAttempts += 1
        DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) { // Wait before retrying
            self.setupListener()
        }
    }
}

