package com.atlassian.bitbucket.mesh.git.builder;

import javax.annotation.Nonnull;
import java.time.Duration;
import java.util.concurrent.Future;

/**
 * Describes a {@code git} process, which can be run synchronously or asynchronously.
 *
 * @param <T> type of the result returned by the process
 */
public interface GitProcess<T> {

    /**
     * Runs the process, blocking the calling thread until the process completes or times out.
     *
     * @return the result of parsing the process's output
     */
    T run();

    /**
     * Sets the maximum interval the process is allowed to run. The process will be aborted automatically
     * if it hasn't completed in this time <i>even if it is still producing output or consuming input</i>.
     *
     * @param duration the maximum interval the process is allowed to run
     */
    void setExecutionInterval(@Nonnull Duration duration);

    /**
     * Sets the maximum interval the process is allowed to run without <i>either</i> producing output or
     * consuming input. Output may be produced on either {@code stdout} or {@code stderr}.
     *
     * @param duration the maximum interval the process is allowed to be idle
     */
    void setIdleInterval(@Nonnull Duration duration);

    /**
     * Sets the {@link #setExecutionInterval execution} and {@link #setIdleInterval idle} intervals to the specified
     * duration. This is useful for processes that do not produce any output until the desired task is complete.
     * Setting the idle and execution intervals to the same value effectively disables applying an idle timeout.
     *
     * @param duration the maximum duration the process is allowed to run or be idle
     */
    void setTimeout(@Nonnull Duration duration);

    /**
     * Starts the process, without blocking the calling thread, and returns a {@link Future} for accessing
     * the process's result. Canceling the returned {@code Future} will also cancel the process, if it is
     * still running when {@link Future#cancel cancel} is called.
     *
     * @return the process's future result
     */
    @Nonnull
    Future<T> start();
}
