package com.atlassian.stash.internal.auth;

import com.atlassian.bitbucket.Product;
import com.atlassian.bitbucket.auth.HttpAuthenticationContext;
import com.atlassian.bitbucket.auth.HttpAuthenticationFailureContext;
import com.atlassian.bitbucket.auth.HttpAuthenticationFailureHandler;
import com.atlassian.bitbucket.i18n.I18nService;
import com.atlassian.bitbucket.scm.AuthenticationState;

import javax.annotation.Nonnull;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * Handles BASIC authentication failures by sending a 401 challenge with an appropriate error message. Note that this
 * handler only handles failures that have not been handled by the {@link ScmAuthenticationFailureHandler} or the
 * {@code RestAuthenticationFailureHandler}.
 *
 * @since 2.3
 */
public class BasicAuthChallengeFailureHandler implements  HttpAuthenticationFailureHandler {

    private final I18nService i18nService;

    public BasicAuthChallengeFailureHandler(I18nService i18nService) {
        this.i18nService = i18nService;
    }

    @Override
    public boolean onAuthenticationFailure(@Nonnull HttpAuthenticationFailureContext context) throws ServletException, IOException {
        if (!HttpAuthenticationContext.METHOD_BASIC.equals(context.getMethod())) {
            return false;
        }

        // send a 401 challenge
        HttpServletResponse response = context.getResponse();
        response.addHeader("WWW-Authenticate", "Basic realm=\"" + Product.FULL_NAME + "\"");
        response.sendError(HttpServletResponse.SC_UNAUTHORIZED, getMessage(context.getAuthenticationState()));

        return true;
    }

    private String getMessage(AuthenticationState reason) {
        switch (reason) {
            case CAPTCHA_REQUIRED:
                return i18nService.getMessage("bitbucket.auth.failed.captcha.required", Product.NAME);
            case UNLICENSED:
                return i18nService.getMessage("bitbucket.auth.failed.unlicensed.user", Product.NAME);
            default:
                return i18nService.getMessage("bitbucket.auth.failed.credentials");
        }
    }
}
