package com.atlassian.stash.sal.api.auth;

import com.atlassian.sal.api.auth.LoginUriProvider;
import com.atlassian.sal.api.page.PageCapability;
import com.atlassian.sal.api.user.UserRole;
import com.atlassian.bitbucket.nav.NavBuilder;
import com.atlassian.bitbucket.util.UrlUtils;

import java.net.URI;
import java.util.EnumSet;

import static com.atlassian.bitbucket.nav.NavBuilder.Login;

public class LoginUriProviderImpl implements LoginUriProvider {

    private final NavBuilder navBuilder;

    public LoginUriProviderImpl(NavBuilder navBuilder) {
        this.navBuilder = navBuilder;
    }

    @Override
    public URI getLoginUri(final URI uri) {
        Login login = basicLogin();

        return buildLoginUri(login, uri);
    }

    @Override
    public URI getLoginUri(URI uri, EnumSet<PageCapability> pageCapabilities) {
        Login login = basicLogin();
        login = maybeEmbedded(login, pageCapabilities);

        return buildLoginUri(login, uri);
    }

    @Override
    public URI getLoginUriForRole(URI uri, UserRole userRole) {
        Login login = basicLogin();
        login = maybeWithRole(login, userRole);

        return buildLoginUri(login, uri);
    }

    @Override
    public URI getLoginUriForRole(URI uri, UserRole userRole, EnumSet<PageCapability> pageCapabilities) {
        Login login = basicLogin();
        login = maybeEmbedded(login, pageCapabilities);
        login = maybeWithRole(login, userRole);

        return buildLoginUri(login, uri);
    }

    private Login basicLogin() {
        return navBuilder.login();
    }

    private URI buildLoginUri(Login login, URI uri) {
        return UrlUtils.uncheckedCreateURI(login.next(uri.toASCIIString()).buildAbsolute());
    }

    private Login maybeEmbedded(Login login, EnumSet<PageCapability> pageCapabilities) {
        if (pageCapabilities.contains(PageCapability.IFRAME)) {
            return login.embedded();
        }

        return login;
    }

    private Login maybeWithRole(Login login, UserRole role) {
        switch(role) {
            case SYSADMIN:
                return login.sysadmin();
            case ADMIN:
                return login.admin();
            default:
                return login;
        }
    }
}
