package com.atlassian.bitbucket.commit;

import javax.annotation.Nonnull;
import java.io.IOException;

/**
 * Describes a callback for receiving a stream of {@link Commit commits}.
 * <p>
 * Note: Implementors are <i>strongly</i> encouraged to extend from {@link AbstractCommitCallback}. This interface
 * <i>will</i> change over time, and any class implementing it directly will be broken by such changes. Extending
 * from the abstract class will help prevent such breakages.
 * @see AbstractCommitCallback
 */
@FunctionalInterface
public interface CommitCallback {

    /**
     * Receives a fully-populated {@link Commit commit} for processing.
     * <p>
     * This method will never be invoked before {@link #onStart(CommitContext)}, and if it is invoked
     * {@link #onEnd(CommitSummary)} is guaranteed to be invoked, whether the end happens because this
     * method returns {@code false} or because the upstream sender runs out of commits.
     *
     * @param commit the commit
     * @return {@code true} if more commits should be provided; otherwise {@code false} to end streaming,
     *         potentially leaving some number of commits unread
     * @throws IOException for implementations which perform I/O
     */
    boolean onCommit(@Nonnull Commit commit) throws IOException;

    /**
     * Called after the final {@link #onCommit(Commit) commit} has been streamed.
     * <p>
     * Note: If there were no commits, this method may be called immediately after {@link #onStart(CommitContext)}
     * without any calls to {@link #onCommit(Commit)}.
     *
     * @param summary summarizes the request and the streamed commits
     * @throws IOException for implementations which perform I/O
     */
    default void onEnd(@Nonnull CommitSummary summary) throws IOException {
    }

    /**
     * Called before the first {@link #onCommit(Commit) commit} is streamed.
     *
     * @param context provides details about the request for which commits are being streamed
     * @throws IOException for implementations which perform I/O
     */
    default void onStart(@Nonnull CommitContext context) throws IOException {
    }
}
