package com.atlassian.bitbucket.web.conditions;

import com.atlassian.bitbucket.permission.Permission;
import com.atlassian.bitbucket.permission.PermissionService;
import com.atlassian.plugin.PluginParseException;
import com.atlassian.plugin.webresource.condition.SimpleUrlReadingCondition;
import org.apache.commons.lang3.StringUtils;

import java.util.Map;

import static com.google.common.base.Preconditions.checkArgument;

/**
 * Verifies that the current user has a global permission as an {@link com.atlassian.plugin.webresource.condition.UrlReadingCondition}.
 * This condition should be used only in web-resources when required to be combined with other {@link com.atlassian.plugin.webresource.condition.UrlReadingCondition}s.
 *
 * <code>
 * <pre>
 * &lt;condition class="com.atlassian.bitbucket.web.conditions.HasGlobalPermissionUrlReadingCondition">
 *     &lt;param name="permission">ADMIN&lt;/param>
 * &lt;/condition>
 * </pre>
 * </code>
 *
 * @since 4.6
 */
public class HasGlobalPermissionUrlReadingCondition extends SimpleUrlReadingCondition {

    private static final String PERMISSION = "permission";
    private final PermissionService permissionService;
    private Permission permission;

    /**
     * Constructs a new {@code HasGlobalPermissionUrlReadingCondition} which will perform checks using the specified
     * {@link PermissionService}.
     *
     * @param permissionService the service to use when performing the permission check
     */
    public HasGlobalPermissionUrlReadingCondition(PermissionService permissionService) {
        this.permissionService = permissionService;
    }

    /**
     * Retrieves the {@link #PERMISSION permission} from the context. The {@link Permission#isGlobal() global} flag of the
     * parsed permission is validated to ensure the {@link Permission} is global.
     *
     * @param params the initialisation context
     * @throws PluginParseException Thrown if no {@link #PERMISSION permission} is set, or if the set value is not a
     *                              valid {@link Permission}, or the permission's {@link Permission#isGlobal() global}
     *                              flag does not match the required value.
     */
    @Override
    public void init(Map<String, String> params) throws PluginParseException {
        String permissionName = params.get(PERMISSION);
        if (StringUtils.isBlank(permissionName)) {
            throw new PluginParseException(getClass().getSimpleName() + ": The [" + PERMISSION +
                    "] param is required, and must define a global permission");
        }

        try {
            permission = Permission.valueOf(permissionName);
            checkArgument(permission.isGlobal(), "%s requires a global permission",
                    getClass().getSimpleName());
        } catch (IllegalArgumentException e) {
            throw new PluginParseException(e.getMessage());
        }
    }

    @Override
    protected boolean isConditionTrue() {
        return permissionService.hasGlobalPermission(permission);
    }

    @Override
    protected String queryKey() {
        return String.format("has%sPermission", permission.name());
    }
}
