package com.atlassian.bitbucket.event.permission;

import com.atlassian.bitbucket.event.CancelableEvent;
import com.atlassian.bitbucket.event.annotation.TransactionAware;
import com.atlassian.bitbucket.i18n.KeyedMessage;
import com.atlassian.bitbucket.project.Project;
import com.atlassian.bitbucket.permission.Permission;
import com.atlassian.bitbucket.user.ApplicationUser;
import com.atlassian.bitbucket.util.CancelState;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;

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

/**
 * This event is raised before a user or group are granted a project permission. This event is synchronous,
 * allowing listeners to perform operations in the same database transaction where the permission is granted.
 * <p>
 * This event is {@link CancelableEvent cancelable}. A listener may prevent the permission
 * from being granted by {@link #cancel(KeyedMessage) canceling} this event.
 * Throwing an exception <i>will not</i> prevent the permission from being granted;
 * the exception will be logged and ignored.
 */
@TransactionAware(value = TransactionAware.When.IMMEDIATE) // Override PermissionEvent
public class ProjectPermissionGrantRequestedEvent extends ProjectPermissionEvent implements PermissionGrantRequestedEvent {

    private final CancelState cancelState;

    public ProjectPermissionGrantRequestedEvent(@Nonnull Object source, @Nonnull Permission permission,
                                                @Nonnull Project project,
                                                @Nullable String affectedGroup, @Nullable ApplicationUser affectedUser,
                                                @Nonnull CancelState cancelState) {
        super(source, permission, project, affectedGroup, affectedUser);

        this.cancelState = checkNotNull(cancelState, "cancelState");
    }

    @Override
    public void cancel(@Nonnull KeyedMessage message) {
        cancelState.cancel(message);
    }

    @Override
    public boolean isCanceled() {
        return cancelState.isCanceled();
    }

}
