//
//  ServersBrowser.swift
//  MockuprViewer
//
//  Created by Sergii Kryvoblotskyi on 3/30/21.
//

import Foundation

final class ServersBrowser: NSObject, ObservableObject {
    
    var onServersChanged: (([Server]) -> Void)?
    
    @Published private(set) var servers: [Server]
    
    private let mockuprServiceType = "_mt_broadcasting_protocol._tcp.";
    private let workingQueue = DispatchQueue(label: "ServersBrowser.workingQueue")
    private let receiverQueue = DispatchQueue.main
    private let bonjourBrowser: NetServiceBrowser
    
    init(bonjourBrowser: NetServiceBrowser = .init(), servers: [Server] = []) {
        self.bonjourBrowser = bonjourBrowser
        self.servers = servers
        super.init()
        self.bonjourBrowser.delegate = self
    }
    
    func start() {
        bonjourBrowser.searchForServices(ofType: mockuprServiceType, inDomain: "")
    }
    
    func stop() {
        bonjourBrowser.stop()
    }
}

extension ServersBrowser: NetServiceBrowserDelegate {
    
    func netServiceBrowser(_ browser: NetServiceBrowser, didFind service: NetService, moreComing: Bool) {
        workingQueue.async {
            let server = Server(service: service)
            print(server)
            self.receiverQueue.async {
                self.servers = self.servers.byAppending(element: server)
                DispatchQueue.main.async {
                    self.onServersChanged?(self.servers)
                }
            }
        }
    }
    
    func netServiceBrowser(_ browser: NetServiceBrowser, didRemove service: NetService, moreComing: Bool) {
        workingQueue.async {
            let server = Server(service: service)
            self.receiverQueue.async {
                self.servers = self.servers.byRemoving(element: server)
                DispatchQueue.main.async {
                    self.onServersChanged?(self.servers)
                }
            }
        }
    }
}

struct Server: Equatable, Identifiable {
    
    let service: NetService
    
    typealias ID = String
    var id: String { name }
    
    var name: String { service.name }
    var type: String { service.type }
    var host: String { service.hostName ?? "" }
    
    static let mock: Server = Server(service: NetService(domain: "Local", type: "Local", name: "MockServer"))
}
