package com.atlassian.bitbucket.scm.http;

import com.atlassian.bitbucket.AuthorisationException;
import com.atlassian.bitbucket.repository.NoSuchRepositoryException;
import com.atlassian.bitbucket.scm.AuthenticationState;

import javax.annotation.Nonnull;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Optional;

/**
 * Plugin point for providing handlers for HTTP requests for SCM hosting operations.
 * <p/>
 * Bitbucket will automatically attempt to authenticate requests using its standard authentication stack
 * (which includes support for Basic Auth). If authentication is required but was not provided or there were invalid
 * credentials, {@link #sendAuthenticationError} will be called.
 *
 * @see HttpScmRequestHandlerModuleDescriptor
 * @see HttpScmRequest
 */
public interface HttpScmRequestHandler {

    /**
     * Returns an {@link HttpScmRequest} to service the supplied request, or {@link Optional#empty()} if the request
     * could not be created. This method is only called when {@link #supports} returned {@code true} for that request.
     *
     * @param request an {@link HttpServletRequest} targeting /scm/* (e.g. an HTTP request from the git client binary)
     * @param response the {@link HttpServletResponse}
     * @return an {@link HttpScmRequest} to service the request, or {@link Optional#empty()}
     * @throws NoSuchRepositoryException if the repository could not be found
     * @throws AuthorisationException if the repository is not accessible
     */
    @Nonnull
    Optional<HttpScmRequest> create(@Nonnull HttpServletRequest request, @Nonnull HttpServletResponse response);

    /**
     * @param state the current state of the user's authentication, see {@link AuthenticationState} for details
     * @param summary an i18n'd message to (optionally) send to the client if it supports displaying custom messages
     * @param detailMessage a longer detailed explanation of the problem
     * @throws java.io.IOException if there was a problem reading from the request or writing to the response
     */
    void sendAuthenticationError(@Nonnull AuthenticationState state, @Nonnull String summary, @Nonnull String detailMessage,
                                 @Nonnull HttpServletRequest request, @Nonnull HttpServletResponse response) throws IOException;

    /**
     * @param summary an i18n'd message to (optionally) send to the client if it supports displaying custom messages
     * @param detailMessage a longer detailed explanation of the problem
     * @param request an {@link HttpServletRequest} targeting /scm/* (e.g. an HTTP request from the git client binary)
     * @param response the {@link HttpServletResponse}
     * @throws java.io.IOException if there was a problem writing to the response
     */
    void sendError(@Nonnull String summary, @Nonnull String detailMessage,
                   @Nonnull HttpServletRequest request, @Nonnull HttpServletResponse response) throws IOException;

    /**
     * Returns whether the handler can service the supplied request. {@code false} means that the request will be passed
     * on to the {@link HttpScmRequestHandler} provided by the {@link HttpScmRequestHandlerModuleDescriptor} with the
     * next heaviest weight.
     *
     * @param requestDetails {@link HttpRequestDetails} from the request targeting /scm/* (e.g. an HTTP request from the git client binary)
     * @return {@code true} if the handler can service this request, {@code false} otherwise
     */
    boolean supports(@Nonnull HttpRequestDetails requestDetails);
}
