/*
 * Copyright 2011 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.gradle.api.artifacts.repositories;

import org.gradle.api.Action;
import org.gradle.api.Incubating;
import org.gradle.api.credentials.Credentials;
import org.gradle.internal.HasInternalProtocol;

/**
 * An artifact repository which supports username/password authentication.
 */
@HasInternalProtocol
public interface AuthenticationSupported {

    /**
     * Returns the username and password credentials used to authenticate to this repository.
     * <p>
     * If no credentials have been assigned to this repository, an empty set of username and password credentials is assigned to this repository and returned.
     * <p>
     * If you are using a different type of credentials than {@link PasswordCredentials}, please use {@link #getCredentials(Class)} to obtain the credentials.
     *
     * @return the credentials
     * @throws IllegalStateException if the credential type was previously set with {@link #credentials(Class, Action)} where the type was not {@link PasswordCredentials}
     */
    PasswordCredentials getCredentials();

    /**
     * Returns the credentials of the specified type used to authenticate with this repository.
     * <p>
     * If no credentials have been assigned to this repository, an empty set of credentials of the specified type is assigned to this repository and returned.
     *
     * @param credentialsType type of the credential
     * @return The credentials
     * @throws IllegalArgumentException when the credentials assigned to this repository are not assignable to the specified type
     */
    @Incubating
    <T extends Credentials> T getCredentials(Class<T> credentialsType);

    /**
     * Configures the username and password credentials for this repository using the supplied action.
     * <p>
     * If no credentials have been assigned to this repository, an empty set of username and password credentials is assigned to this repository and passed to the action.
     * <pre class='autoTested'>
     * repositories {
     *     maven {
     *         url "${url}"
     *         credentials {
     *             username = 'joe'
     *             password = 'secret'
     *         }
     *     }
     * }
     * </pre>
     *
     * @throws IllegalStateException when the credentials assigned to this repository are not of type {@link PasswordCredentials}
     */
    void credentials(Action<? super PasswordCredentials> action);

    /**
     * Configures the credentials for this repository using the supplied action.
     * <p>
     * If no credentials have been assigned to this repository, an empty set of credentials of the specified type will be assigned to this repository and given to the configuration action.
     * If credentials have already been specified for this repository, they will be passed to the given configuration action.
     * <pre class='autoTested'>
     * repositories {
     *     maven {
     *         url "${url}"
     *         credentials(AwsCredentials) {
     *             accessKey "myAccessKey"
     *             secretKey "mySecret"
     *         }
     *     }
     * }
     * </pre>
     * <p>
     * The following credential types are currently supported for the {@code credentialsType} argument:
     * <ul>
     * <li>{@link org.gradle.api.artifacts.repositories.PasswordCredentials}</li>
     * <li>{@link org.gradle.api.credentials.AwsCredentials}</li>
     * </ul>
     *
     * @throws IllegalArgumentException if {@code credentialsType} is not of a supported type
     * @throws IllegalArgumentException if {@code credentialsType} is of a different type to the credentials previously specified for this repository
     */
    @Incubating
    <T extends Credentials> void credentials(Class<T> credentialsType, Action<? super T> action);

    /**
     * <p>Configures the authentication schemes for this repository.
     *
     * <p>This method executes the given action against the {@link AuthenticationContainer} for this project. The {@link
     * AuthenticationContainer} is passed to the closure as the closure's delegate.
     * <p>
     * If no authentication schemes have been assigned to this repository, a default set of authentication schemes are used based on the repository's transport scheme.
     *
     * <pre class='autoTested'>
     * repositories {
     *     maven {
     *         url "${url}"
     *         authentication {
     *             basic(BasicAuthentication)
     *         }
     *     }
     * }
     * </pre>
     * <p>
     * Supported authentication scheme types extend {@link org.gradle.authentication.Authentication}.
     *
     * @param action the action to use to configure the authentication schemes.
     */
    @Incubating
    void authentication(Action<? super AuthenticationContainer> action);

    /**
     * Returns the authentication schemes for this repository.
     *
     * @return the authentication schemes for this repository
     */
    @Incubating
    AuthenticationContainer getAuthentication();
}
