package com.atlassian.bitbucket.web.conditions;

import com.atlassian.bitbucket.project.AbstractProjectVisitor;
import com.atlassian.bitbucket.project.PersonalProject;
import com.atlassian.bitbucket.project.ProjectType;
import com.atlassian.plugin.web.Condition;
import com.atlassian.bitbucket.repository.Repository;
import com.atlassian.bitbucket.auth.AuthenticationContext;
import com.atlassian.bitbucket.user.ApplicationUserEquality;

import javax.annotation.Nonnull;
import java.util.Map;

/**
 * A condition for determining whether a given repository resides in a personal project; ergo, it is a personal
 * repository.
 * <p>
 * By default, repositories in <i>any</i> {@link ProjectType#PERSONAL personal project} will match this condition.
 * Setting the {@code onlyMine} parameter to {@code true} restricts the condition to only return {@code true} if the
 * repository is in the current user's {@link PersonalProject personal project}.
 */
public class IsPersonalRepositoryCondition implements Condition {

    public static final String REPOSITORY = "repository";
    public static final String ONLY_MINE = "onlyMine";

    private final AuthenticationContext authenticationContext;

    private boolean onlyMine;

    public IsPersonalRepositoryCondition(AuthenticationContext authenticationContext) {
        this.authenticationContext = authenticationContext;
    }

    /**
     * Parses parameters for this condition. Supported parameters are:
     * <ul>
     *     <li>{@code onlyMine}: {@code true} if the condition should only match the current user's personal project;
     *     {@code false} if all personal project should match (Default: {@code false})</li>
     * </ul>
     *
     * @param params configuration parameters for this condition
     */
    @Override
    public void init(Map<String, String> params) {
        onlyMine = Boolean.parseBoolean(params.get(ONLY_MINE));
    }

    /**
     * Retrieves a flag indicating whether the repository, which is expected to be present in the provided
     * {@code context} under the key {@link #REPOSITORY "repository"}, belongs to a personal project.
     * <p>
     * If {@code onlyMine} is set to {@code true}, the repository must not only belong to a personal project
     * but must belong to the <i>current user's</i> personal project.
     *
     * @param context the context containing the repository
     * @return {@code true} if the repository is in a personal project (optionally further restricted to only
     *         the current user's personal project); otherwise, {@code false}
     */
    @Override
    public boolean shouldDisplay(Map<String, Object> context) {
        Repository repository = (Repository) context.get(REPOSITORY);
        if (repository == null) {
            return false;
        }
        return repository.getProject().accept(new AbstractProjectVisitor<Boolean>(Boolean.FALSE) {
            @Override
            public Boolean visit(@Nonnull PersonalProject project) {
                return !onlyMine || ApplicationUserEquality.equals(project.getOwner(), authenticationContext.getCurrentUser());
            }
        });
    }
}