//
//  AttractorServer.swift
//  App
//
//  Created by James Magahern on 8/5/22.
//

import Foundation

class AttractorServer
{
    public enum Error: Swift.Error {
        case missingEndpointURL
    }
    
    static let shared = AttractorServer()
    
    private var endpointURL: URL? {
        get {
            if let syncServer = Settings.shared.syncServer {
                return URL(string: syncServer)
            }
            
            return nil
        }
    }
    
    private func getHostname() -> String {
        // Need an entitlement for this...
        return UIDevice.current.name
    }
    
    public func publishTabInfo(_ tabInfos: [TabInfo]) {
        guard let endpointURL else { return }
        
        let hostName = getHostname()
        let rpcURL = endpointURL.appendingPathComponent("publishTabInfo")
        var components = URLComponents(url: rpcURL, resolvingAgainstBaseURL: false)!
        components.queryItems = [
            URLQueryItem(name: "host", value: hostName)
        ]
        
        let encoder = JSONEncoder()
        if let bodyData = try? encoder.encode(tabInfos) {
            var request = URLRequest(url: components.url!)
            request.httpBody = bodyData
            request.httpMethod = "POST"
            
            let dataTask = URLSession.shared.dataTask(with: request) { (data, response, error) in
                if let error {
                    print("Error publishing tab info: \(error.localizedDescription)")
                }
            }
            
            dataTask.resume()
        }
    }
    
    public func getTabInfos(_ completion: @escaping(Result<[String: [TabInfo]], Swift.Error>) -> Void) {
        guard let endpointURL else {
            completion(.failure(Self.Error.missingEndpointURL))
            return 
        }
        
        let rpcURL = endpointURL.appendingPathComponent("getTabInfos")
        let request = URLRequest(url: rpcURL)
        let myHostname = getHostname()
        let dataTask = URLSession.shared.dataTask(with: request) { (data, response, error) in
            if let error {
                print("Error getting tab infos: \(error.localizedDescription)")
                DispatchQueue.main.async { completion(.failure(error)) }
            }
            
            let decoder = JSONDecoder()
            if let data {
                do {
                    let result = try decoder.decode([String: [TabInfo]].self, from: data)
                        .filter({ (host, tabInfo) in
                            // Filter out tabs from the same machine.
                            return host != myHostname
                        })
                    
                    DispatchQueue.main.async { completion(.success(result)) }
                } catch {
                    print("Error decoding tabs: \(error.localizedDescription)")
                    DispatchQueue.main.async { completion(.failure(error)) }
                }
            }
        }
        
        dataTask.resume()
    }
}
