package com.atlassian.bitbucket.internal.mirroring.mirror.auth;

import com.atlassian.bitbucket.auth.AuthenticationContext;
import com.atlassian.bitbucket.internal.mirroring.mirror.jwt.JwtClaims;
import com.atlassian.bitbucket.internal.mirroring.mirror.jwt.SimpleJwtUser;
import com.atlassian.bitbucket.internal.mirroring.user.SimpleApplicationUserWithPermissions;
import com.atlassian.bitbucket.permission.Permission;
import com.atlassian.bitbucket.permission.SimpleEffectiveGlobalPermission;
import com.atlassian.bitbucket.permission.SimpleEffectiveRepositoryPermission;
import com.atlassian.bitbucket.request.RequestManager;
import com.atlassian.bitbucket.user.ApplicationUser;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.util.Optional;

import static com.google.common.collect.ImmutableList.of;

@Component("mirrorLfsAuthenticationContext")
public class MirrorLfsAuthenticationContext extends AbstractMirrorAuthenticationContext {

    public MirrorLfsAuthenticationContext(AuthenticationContext authenticationContext, RequestManager requestManager) {
        super(authenticationContext, requestManager);
    }

    @Override
    public Optional<ApplicationUser> doGetImpersonatedUser(HttpServletRequest req) {
        Optional<JwtClaims> jwtClaims = getJwtClaims(req);
        return jwtClaims.flatMap(JwtClaims::getContextUser)
                .map(SimpleJwtUser::new)
                .flatMap(user -> userWithSingleRepoAccess(jwtClaims, user));
    }

    @Override
    boolean isImpersonatedUserReturned(ApplicationUser ignored) {
        return true;
    }

    private Optional<ApplicationUser> userWithSingleRepoAccess(Optional<JwtClaims> jwtClaims, ApplicationUser user) {
        //We know jwtClaims is non empty because of the flatMap in doGetImpersonatedUser
        return jwtClaims.get().getRepository().map(repositoryId ->
                new SimpleApplicationUserWithPermissions(user, of(
                        new SimpleEffectiveGlobalPermission(Permission.LICENSED_USER),
                        new SimpleEffectiveRepositoryPermission(repositoryId, Permission.REPO_READ)
                )));
    }
}
