
import SwiftUI
import Foundation

struct BlockedCount: View {

    @EnvironmentObject
    private var viewModel: ViewModel

    @State private var txtRecord: String = "…"

    private static let startIndex = 44

    private static let formatter: NumberFormatter = {
        let formatter = NumberFormatter()
        formatter.numberStyle = .decimal

        return formatter
    }()

    var body: some View {
        Text(txtRecord)
        .onAppear {
            fetchTXTRecord()
        }
        .onChange(of: viewModel.blocklist) { _ in
            fetchTXTRecord()
        }
    }

    func parseResponse(data: Data) -> String? {
        // This is a DNS wire format response and we make a lot of assumptions
        // It is not critical functionality so just let it fail if it fails

        guard data.count > Self.startIndex else {
            return nil
        }

        // Find the first space character (ASCII 32).
        guard let endIndex = data.suffix(from: Self.startIndex).firstIndex(of: 32) else {
            return nil
        }

        guard let numberString = String(data: data[Self.startIndex ..< endIndex], encoding: .utf8)
        else {
            return nil
        }

        return Self.formatter.string(for: Int(numberString))
    }
    
    func fetchTXTRecord() {
        let dohURL = URL(string: "https://\(viewModel.blocklist.server)/dns-query?dns=DoQBAAABAAAAAAAABXN0YXRzB2ludmFsaWQAABAAAQ")!
        let request = URLRequest(url: dohURL)

        txtRecord = "…"

        Task {
            do {
                let (data, _) = try await URLSession.shared.data(for: request)

                if let count = parseResponse(data: data) {
                    txtRecord = count
                }
                else {
                    txtRecord = NSLocalizedString("Error", comment: "")
                }
            }
            catch {
                txtRecord = NSLocalizedString("Error", comment: "")
            }
        }
    }
}

#Preview {
    BlockedCount()
        .environmentObject(ViewModel())
}
