//
//  See LICENSE folder for this template’s licensing information.
//
//  Abstract:
//  Bonjourサービスへの通知クライアント

import Foundation
import Network
import UIKit
import PlaygroundSupport
class TCPClient: NSObject, NetServiceBrowserDelegate, NetServiceDelegate {
    var connection: NWConnection?
    var serviceBrowser: NetServiceBrowser?
    var service: NetService?
    
    private let maxReconnectAttempts = 5
    private var reconnectAttempts = 0
    
    // コールバックプロパティ
    var onConnectionReady: (() -> Void)?

    func start() {
        serviceBrowser = NetServiceBrowser()
        serviceBrowser?.delegate = self
        serviceBrowser?.searchForServices(ofType: "_playgnd._tcp.", inDomain: "local.")
    }
    
    func send(messageDict: [String: String]) {
        guard let connection = self.connection else {
            print("No connection established.")
            return
        }

        do {
            let jsonData = try JSONSerialization.data(withJSONObject: messageDict, options: [])
            connection.send(content: jsonData, completion: .contentProcessed({ error in
                if let error = error {
                    print("Failed to send message: \(error)")
                } else {
                    print("Message sent")
                }
            }))
        } catch {
            print("Failed to encode message to JSON: \(error)")
        }
    }

    private func setupConnection() {
        guard reconnectAttempts < maxReconnectAttempts else {
            print("Max reconnect attempts reached")
            return
        }

        guard let service = self.service, let hostname = service.hostName else {
            print("No service or hostname found")
            return
        }

        let host = NWEndpoint.Host(hostname)
        let port = NWEndpoint.Port(integerLiteral: UInt16(service.port))

        connection = NWConnection(to: .hostPort(host: host, port: port), using: .tcp)
        connection?.start(queue: .main)
        connection?.stateUpdateHandler = { [weak self] state in
            switch state {
            case .ready:
                print("Connected to server")
                self?.reconnectAttempts = 0  // Reset reconnect attempts on successful connection
                
                // 接続が確立された後にコールバックを実行
                self?.onConnectionReady?()
                
            case .failed(_):
                print("Connection failed, retrying...")
                self?.reconnectAttempts += 1
                DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) {
                    self?.setupConnection()
                }
            case .cancelled:
                print("Connection cancelled")
            default:
                break
            }
        }
    }

    // NetServiceBrowserDelegate methods
    func netServiceBrowser(_ browser: NetServiceBrowser, didFind service: NetService, moreComing: Bool) {
        self.service = service
        service.delegate = self
        service.resolve(withTimeout: 10)
    }

    // NetServiceDelegate methods
    func netServiceDidResolveAddress(_ sender: NetService) {
        setupConnection()
    }

    func netService(_ sender: NetService, didNotResolve errorDict: [String : NSNumber]) {
        print("Failed to resolve service: \(errorDict)")
    }
}
