import Foundation
import Network
import Combine

class BonjourService: NSObject, ObservableObject, NetServiceBrowserDelegate, NetServiceDelegate {
    @Published var foundServer: String?
    
    private var netServiceBrowser: NetServiceBrowser?
    private var services = [NetService]()
    
    func start() {
        print("BonjourService: Starting browsing (NetService)...")
        netServiceBrowser = NetServiceBrowser()
        netServiceBrowser?.delegate = self
        netServiceBrowser?.searchForServices(ofType: "_bemyears._tcp", inDomain: "local.")
    }
    
    func stop() {
        netServiceBrowser?.stop()
        netServiceBrowser = nil
        services.removeAll()
    }
    
    // MARK: - NetServiceBrowserDelegate
    
    func netServiceBrowser(_ browser: NetServiceBrowser, didFind service: NetService, moreComing: Bool) {
        print("BonjourService: Found service \(service.name)")
        services.append(service)
        service.delegate = self
        // 5 seconds timeout for resolution
        service.resolve(withTimeout: 5.0)
    }
    
    func netServiceBrowser(_ browser: NetServiceBrowser, didRemove service: NetService, moreComing: Bool) {
        print("BonjourService: Removed service \(service.name)")
        if let index = services.firstIndex(of: service) {
            services.remove(at: index)
        }
    }
    
    func netServiceBrowser(_ browser: NetServiceBrowser, didNotSearch errorDict: [String : NSNumber]) {
        print("BonjourService: Search failed: \(errorDict)")
    }
    
    // MARK: - NetServiceDelegate
    
    func netServiceDidResolveAddress(_ sender: NetService) {
        guard let addresses = sender.addresses else { return }
        
        for address in addresses {
            let data = address as NSData
            var storage = sockaddr_storage()
            data.getBytes(&storage, length: MemoryLayout<sockaddr_storage>.size)
            
            if Int32(storage.ss_family) == AF_INET {
                let ipStr = String(cString: inet_ntoa(data.bytes.load(as: sockaddr_in.self).sin_addr))
                print("BonjourService: Resolved IPv4: \(ipStr)")
                
                // Found, update UI
                DispatchQueue.main.async {
                    self.foundServer = ipStr
                }
                // Stop specifically resolving this one or just keep going?
                // We'll just stop searching once we find a valid IPv4
                stop() 
                return
            } else if Int32(storage.ss_family) == AF_INET6 {
                // Ignore IPv6
                print("BonjourService: Ignoring IPv6 address found.")
            }
        }
    }
    
    func netService(_ sender: NetService, didNotResolve errorDict: [String : NSNumber]) {
        print("BonjourService: Resolve failed: \(errorDict)")
    }
}
