import Foundation

extension URLComponents {
     static func with(host: String, scheme: String = "https", path: String = "/", queryParameters: [String: Any]? = nil) -> URLComponents {
        var components = URLComponents()
        components.host = host
        components.scheme = scheme
        components.path = path
        components.replacePercentEncodedQueryWithQueryParameters(queryParameters)
        return components
    }
    
    public static func percentEncodedQueryStringFrom(_ queryParameters: [String: Any]) -> String {
        var query = ""
        
        // sort query parameters by key, this allows for consistency when itemKeys are generated for the persistent cache.
        struct KeyValue {
            let key: String
            let value: Any
        }
        
        var unorderedKeyValues: [KeyValue] = []
        
        for (name, value) in queryParameters {
            
            unorderedKeyValues.append(KeyValue(key: name, value: value))
        }
        
        let orderedKeyValues = unorderedKeyValues.sorted { (lhs, rhs) -> Bool in
            return lhs.key < rhs.key
        }
        
        for keyValue in orderedKeyValues {
            guard
                let encodedName = keyValue.key.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryComponentAllowed),
                let encodedValue = String(describing: keyValue.value).addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryComponentAllowed) else {
                    continue
            }
            if query != "" {
                query.append("&")
            }
            
            query.append("\(encodedName)=\(encodedValue)")
        }
        
        return query
    }
    
    mutating func appendQueryParametersToPercentEncodedQuery(_ queryParameters: [String: Any]?) {
        guard let queryParameters = queryParameters else {
            return
        }
        var newPEQ = ""
        if let existing = percentEncodedQuery {
            newPEQ = existing + "&"
        }
        newPEQ = newPEQ + URLComponents.percentEncodedQueryStringFrom(queryParameters)
        percentEncodedQuery = newPEQ
    }
    
    mutating func replacePercentEncodedQueryWithQueryParameters(_ queryParameters: [String: Any]?) {
        guard let queryParameters = queryParameters else {
            percentEncodedQuery = nil
            return
        }
        percentEncodedQuery = URLComponents.percentEncodedQueryStringFrom(queryParameters)
    }
    
    mutating func replacePercentEncodedPathWithPathComponents(_ pathComponents: [String]?) {
        guard let pathComponents = pathComponents else {
            percentEncodedPath = "/"
            return
        }
        let fullComponents = [""] + pathComponents
        #if DEBUG
        for component in fullComponents {
            assert(!component.contains("/"))
        }
        #endif
        percentEncodedPath = fullComponents.joined(separator: "/") // NSString.path(with: components) removes the trailing slash that the reading list API needs
    }
    
    public func wmf_URLWithLanguageVariantCode(_ code: String?) -> URL? {
        return (self as NSURLComponents).wmf_URL(withLanguageVariantCode: code)
    }

}
