package com.atlassian.bitbucket.commit;

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

/**
 * Describes a callback for receiving the commits that last modified a set of files.
 *
 * @since 4.6
 */
@FunctionalInterface
public interface LastModifiedCallback {

    /**
     * Called after the final {@link #onFile file}'s last modification has been streamed.
     * <p>
     * Note: If the {@link LastModifiedRequest#getPath requested path} contained no files, this method may be called
     * immediately after {@link #onStart(LastModifiedContext)} without any calls to {@link #onFile(String, Commit)}.
     *
     * @param summary summarizes the request and provides the most recent commit to modify the requested path
     * @throws IOException for implementations which perform I/O
     */
    default void onEnd(@Nonnull LastModifiedSummary summary) throws IOException {
    }

    /**
     * Receives a fully-populated {@link Commit commit} which last modified the specified {@code file}. Files are
     * provided as <i>relative</i> to the {@link LastModifiedRequest#getPath requested path}, and only <i>files</i>
     * are provided. Subdirectories of the requested path <i>are not streamed</i>.
     * <p>
     * This method will never be invoked before {@link #onStart(LastModifiedContext)}, and if it is invoked
     * {@link #onEnd(LastModifiedSummary)} is guaranteed to be invoked, whether the end happens because this
     * method returns {@code false} or because the upstream sender runs out of modifications.
     *
     * @param file   a <i>relative</i> path to the modified file
     * @param commit the last commit to modify the file
     * @return {@code true} if more modifications should be provided; otherwise, {@code false} to end streaming,
     *         potentially leaving some number of modifications unread
     * @throws IOException
     */
    boolean onFile(@Nonnull String file, @Nonnull Commit commit) throws IOException;

    /**
     * Called before the first {@link #onFile file} is streamed.
     *
     * @param context provides details about the request
     * @throws IOException for implementations which perform I/O
     */
    default void onStart(@Nonnull LastModifiedContext context) throws IOException {
    }
}
