// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//

public protocol URLAuthenticationChallengeSender : NSObjectProtocol {
    
    
    /*!
     @method useCredential:forAuthenticationChallenge:
     */
    func use(_ credential: URLCredential, for challenge: URLAuthenticationChallenge)
    
    
    /*!
     @method continueWithoutCredentialForAuthenticationChallenge:
     */
    func continueWithoutCredential(for challenge: URLAuthenticationChallenge)
    
    
    /*!
     @method cancelAuthenticationChallenge:
     */
    func cancel(_ challenge: URLAuthenticationChallenge)
    
    
    /*!
     @method performDefaultHandlingForAuthenticationChallenge:
     */
    func performDefaultHandling(for challenge: URLAuthenticationChallenge)
    
    
    /*!
     @method rejectProtectionSpaceAndContinueWithChallenge:
     */
    func rejectProtectionSpaceAndContinue(with challenge: URLAuthenticationChallenge)
}

/*!
    @class NSURLAuthenticationChallenge
    @discussion This class represents an authentication challenge. It
    provides all the information about the challenge, and has a method
    to indicate when it's done.
*/
open class URLAuthenticationChallenge : NSObject, NSSecureCoding {
    
    static public var supportsSecureCoding: Bool {
        return true
    }
    
    public required init?(coder aDecoder: NSCoder) {
        NSUnimplemented()
    }
    
    open func encode(with aCoder: NSCoder) {
        NSUnimplemented()
    }
    
    
    /*!
     @method initWithProtectionSpace:proposedCredential:previousFailureCount:failureResponse:error:
     @abstract Initialize an authentication challenge
     @param space The NSURLProtectionSpace to use
     @param credential The proposed NSURLCredential for this challenge, or nil
     @param previousFailureCount A count of previous failures attempting access.
     @param response The NSURLResponse for the authentication failure, if applicable, else nil
     @param error The NSError for the authentication failure, if applicable, else nil
     @result An authentication challenge initialized with the specified parameters
     */
    public init(protectionSpace space: URLProtectionSpace, proposedCredential credential: URLCredential?, previousFailureCount: Int, failureResponse response: URLResponse?, error: Error?, sender: URLAuthenticationChallengeSender) {
        NSUnimplemented()
    }
    
    
    /*!
     @method initWithAuthenticationChallenge:
     @abstract Initialize an authentication challenge copying all parameters from another one.
     @param challenge
     @result A new challenge initialized with the parameters from the passed in challenge
     @discussion This initializer may be useful to subclassers that want to proxy
     one type of authentication challenge to look like another type.
     */
    public init(authenticationChallenge challenge: URLAuthenticationChallenge, sender: URLAuthenticationChallengeSender) {
        NSUnimplemented()
    }
    
    
    /*!
     @method protectionSpace
     @abstract Get a description of the protection space that requires authentication
     @result The protection space that needs authentication
     */
    /*@NSCopying*/ open var protectionSpace: URLProtectionSpace {
        get {
            NSUnimplemented()
        }
    }
    
    
    /*!
     @method proposedCredential
     @abstract Get the proposed credential for this challenge
     @result The proposed credential
     @discussion proposedCredential may be nil, if there is no default
     credential to use for this challenge (either stored or in the
     URL). If the credential is not nil and returns YES for
     hasPassword, this means the NSURLConnection thinks the credential
     is ready to use as-is. If it returns NO for hasPassword, then the
     credential is not ready to use as-is, but provides a default
     username the client could use when prompting.
     */
    /*@NSCopying*/ open var proposedCredential: URLCredential? {
        get {
            NSUnimplemented()
        }
    }
    
    
    /*!
     @method previousFailureCount
     @abstract Get count of previous failed authentication attempts
     @result The count of previous failures
     */
    open var previousFailureCount: Int {
        get {
            NSUnimplemented()
        }
    }
    
    
    /*!
     @method failureResponse
     @abstract Get the response representing authentication failure.
     @result The failure response or nil
     @discussion If there was a previous authentication failure, and
     this protocol uses responses to indicate authentication failure,
     then this method will return the response. Otherwise it will
     return nil.
     */
    /*@NSCopying*/ open var failureResponse: URLResponse? {
        get {
            NSUnimplemented()
        }
    }
    
    
    /*!
     @method error
     @abstract Get the error representing authentication failure.
     @discussion If there was a previous authentication failure, and
     this protocol uses errors to indicate authentication failure,
     then this method will return the error. Otherwise it will
     return nil.
     */
    /*@NSCopying*/ open var error: Error? {
        get {
            NSUnimplemented()
        }
    }
    
    
    /*!
     @method sender
     @abstract Get the sender of this challenge
     @result The sender of the challenge
     @discussion The sender is the object you should reply to when done processing the challenge.
     */
    open var sender: URLAuthenticationChallengeSender? {
        get {
            NSUnimplemented()
        }
    }
}
