package com.atlassian.bitbucket.content;

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

/**
 * A callback for the contents of a file
 * <p>
 * Note: Implementors are <i>strongly</i> encouraged to extend from {@link AbstractFileContentCallback}. 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 AbstractFileContentCallback
 */
public interface FileContentCallback {

    /**
     * If annotations were requested and at least one {@link #onLine(int, String, boolean) line} was streamed, this
     * method will be called <i>before</i> {@link #onEnd(FileSummary)} to provide {@link Blame blame} for the streamed
     * lines.
     *
     * @param blames {@link Blame blame} for the streamed lines
     * @throws IOException May be thrown by implementations which perform I/O.
     */
    void offerBlame(@Nonnull List<Blame> blames) throws IOException;

    /**
     * Called once if the file is binary. None of the other methods will be called.
     *
     * @throws IOException if the callback fails
     */
    void onBinary() throws IOException;

    /**
     * Called after the final {@link #onLine(int, String, boolean) line}, <i>and {@link #offerBlame(List) blame} if
     * requested</i>, has been streamed.
     * <p>
     * Note: If there were no lines, this method may be called immediately after {@link #onStart(FileContext)} without
     * any calls to {@link #onLine(int, String, boolean)}.
     *
     * @param summary summarizes the file request and the streamed lines
     * @throws IOException may be thrown by implementations which perform I/O.
     */
    void onEnd(@Nonnull FileSummary summary) throws IOException;

    /**
     * Called once for each line in the file. {@link #onStart(FileContext)} is called before any invocation of this
     * method. {@link #onEnd(FileSummary)} is called after all invocations of this method.
     *
     * @param lineNumber the line number of the line in the file
     * @param line       a truncated line of code. The line character limit can be set at a system level via a system property
     * @param truncated  where the received line was truncated
     * @return {@code true} if additional lines should be provided; otherwise, {@code false} if sufficient lines have
     *         been processed
     * @throws IOException if the callback fails
     */
    boolean onLine(int lineNumber, String line, boolean truncated) throws IOException;

    /**
     * Called before the first {@link #onLine(int, String, boolean)}.
     *
     * @param context provides details about the file request for which lines are being streamed
     * @throws IOException may be thrown by implementations which perform I/O.
     */
    void onStart(@Nonnull FileContext context) throws IOException;
}
