package com.atlassian.bitbucket.event.repository;

import com.atlassian.bitbucket.event.CancelableEvent;
import com.atlassian.bitbucket.i18n.KeyedMessage;
import com.atlassian.bitbucket.repository.RepositoryCreateRequest;
import com.atlassian.bitbucket.repository.RepositoryService;
import com.atlassian.bitbucket.repository.Repository;
import com.atlassian.bitbucket.util.CancelState;

import javax.annotation.Nonnull;

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

/**
 * Raised just before a {@link Repository repository} is created. This event is synchronous, allowing listeners to
 * perform operations in the same database transaction where the repository will be created.
 * <p>
 * This event is {@link CancelableEvent cancelable}. A listener may prevent the repository from being created by
 * {@link #cancel(KeyedMessage) canceling} this event. Throwing an exception <i>will not</i> prevent the repository
 * from being created; the exception will be logged and ignored.
 * <p>
 * Note: The repository attached to the event will <i>not</i> have an {@link Repository#getId() ID}, as it has not
 * been created yet. Any listener which would like to create associations based on that ID must listen for the
 * {@link RepositoryCreatedEvent} instead, which will include it (but will not run in the same transaction).
 * <p>
 * This event is internally audited with a LOW priority.
 *
 * @see RepositoryService#create(RepositoryCreateRequest)
 */
public class RepositoryCreationRequestedEvent extends RepositoryEvent implements CancelableEvent {

    private final CancelState cancelState;

    public RepositoryCreationRequestedEvent(@Nonnull Object source, @Nonnull Repository repository,
                                            @Nonnull CancelState cancelState) {
        super(source, repository);

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

    /**
     * Cancels repository creation, providing a message explaining why.
     *
     * @param message a descriptive message explaining why the operation has been canceled
     */
    @Override
    public void cancel(@Nonnull KeyedMessage message) {
        cancelState.cancel(message);
    }

    /**
     * Retrieves a flag indicating whether repository creation has already been canceled by another listener.
     *
     * @return {@code true} if another listener has already canceled repository creation; otherwise, {@code false}
     */
    @Override
    public boolean isCanceled() {
        return cancelState.isCanceled();
    }
}
