package com.atlassian.bitbucket.scm.mirror;

import com.atlassian.bitbucket.repository.MinimalRef;
import com.atlassian.bitbucket.repository.RefChange;

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

/**
 * Describes a callback for receiving streaming {@link RefChange ref changes}.
 * <p>
 * Implementations of this callback performing internal paging may return {@code false} from
 * {@link #onRefChange(RefChange)} to indicate no more ref changes are desired. Such implementations are
 * <i>encouraged</i> to also implement the {@link com.atlassian.bitbucket.util.PagedCallback PagedCallback} interface to
 * allow the system to optimise output handling, where possible, based on the page being requested.
 *
 * @since 4.1
 */
@SuppressWarnings("UnusedParameters")
public interface MirrorSyncCallback {

    /**
     * Called after the final {@link #onRefChange(RefChange) ref change} has been streamed.
     * <p>
     * Note: If there were no ref changes, this method may be called immediately after {@link #onStart(MirrorSyncContext)}
     * without any calls to {@link #onRefChange(RefChange)}.
     *
     * @param summary summarizes the request and the streamed changes
     * @throws IOException May be thrown by implementations which perform I/O.
     */
    default void onEnd(@Nonnull MirrorSyncSummary summary) throws IOException {
    }

    /**
     * Called when a ref failed to synchronize.
     * <p>
     * If the callback is performing internal paging, it may signal the end of the page by returning {@code false} here.
     *
     * @param ref the ref that failed
     * @return {@code true} if additional ref changes should be provided; otherwise, {@code false} if the callback has
     *         received as many ref changes as desired
     * @throws IOException
     * @since 4.2
     */
    default boolean onFailedRef(@Nonnull MinimalRef ref) throws IOException {
        return true;
    }

    /**
     * Provides a {@link RefChange ref change} to the callback for processing.
     * <p>
     * If the callback is performing internal paging, it may signal the end of the page by returning {@code false} here.
     *
     * @param refChange the ref change to process
     * @return {@code true} if additional ref changes should be provided; otherwise, {@code false} if the callback has
     *         received as many ref changes as desired
     * @throws IOException may be thrown by implementations which perform I/O
     */
    default boolean onRefChange(@Nonnull RefChange refChange) throws IOException {
        return true;
    }

    /**
     * Called before the <i>first</i> {@link #onRefChange(RefChange) ref change} is streamed.
     *
     * @param context provides details about the request for which ref changes are being streamed
     * @throws IOException May be thrown by implementations which perform I/O.
     */
    default void onStart(@Nonnull MirrorSyncContext context) throws IOException {
    }
}
