package com.atlassian.bitbucket.web.conditions;

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

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

/**
 * A condition for testing whether a project is {@link ProjectType#PERSONAL personal}.
 * <p>
 * By default, <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 project
 * is the current user's {@link PersonalProject personal project}.
 */
public class IsPersonalProjectCondition implements Condition {

    public static final String PROJECT = "project";
    public static final String ONLY_MINE = "onlyMine";

    private final AuthenticationContext authenticationContext;

    private boolean onlyMine;

    public IsPersonalProjectCondition(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 project, which is expected to be present in the provided {@code context}
     * under the key {@link #PROJECT "project"}, is a personal project.
     * <p>
     * If {@code onlyMine} is set to {@code true}, project must not only be {@link ProjectType#PERSONAL personal} but
     * must belong to the <i>current user</i>.
     *
     * @param context the context containing the project
     * @return {@code true} if the project is personal (optionally further restricted to only the current user);
     *         otherwise, {@code false}
     */
    @Override
    public boolean shouldDisplay(Map<String, Object> context) {
        Project project = (Project) context.get(PROJECT);
        if (project == null) {
            return false;
        }

        return project.accept(new AbstractProjectVisitor<Boolean>(Boolean.FALSE) {
            @Override
            public Boolean visit(@Nonnull PersonalProject project) {
                return !onlyMine || ApplicationUserEquality.equals(project.getOwner(), authenticationContext.getCurrentUser());
            }
        });
    }
}
