package com.atlassian.bitbucket.mesh.process;

import javax.annotation.Nonnull;
import java.nio.ByteBuffer;

/**
 * Describes a {@code git} process, allowing interaction with {@code stdin} as well as the ability to cancel the
 * process.
 */
public interface OsProcess {

    /**
     * Cancels the process.
     * <p>
     * <b>Note</b>: When running a process asynchronously, canceling the process is <i>not</i> the same as canceling
     * the returned {@code Future}. Canceling the process indicates the {@link ProcessStdioHandler} has completed its
     * processing and further input and output are not necessary. Canceling the {@code Future} indicates the caller
     * is no longer interested in receiving a result from the process.
     */
    void cancel();

    /**
     * Closes the process's {@code stdin} pipe, to signal no more input will be provided.
     *
     * @param force {@code true} to close {@code stdin} immediately, even if there are
     *              {@link #hasPendingWrites pending writes}; otherwise, {@code false}
     *              to close {@code stdin} after any pending writes have completed
     */
    void closeStdin(boolean force);

    /**
     * Retrieves a flag indicating whether there are pending {@link #writeStdin writes} to {@code stdin}.
     * <p>
     * <b>Note</b>: Writes from {@link ProcessStdioHandler#onStdinReady} <i>are not considered</i> by this value;
     * only incomplete {@link #writeStdin} buffers are considered.
     *
     * @return {@code true} if one or more {@link #writeStdin} buffers are still pending write; otherwise,
     *         {@code false} if there are no pending buffers
     */
    boolean hasPendingWrites();

    /**
     * Retrieves a flag indicating whether the process has been canceled.
     * <p>
     * <b>Note</b>: This is not mutually exclusive with {@link #isRunning()}. If a process has been canceled
     * but has not yet terminated, both properties may be {@code true} at once.
     *
     * @return {@code true} if the process has been {@link #cancel canceled}; otherwise, {@code false}
     */
    boolean isCanceled();

    /**
     * Retrieves a flag indicating whether the process is still running.
     * <p>
     * <b>Note</b>: This is not mutually exclusive with {@link #isCanceled()}. If a process has been canceled
     * but has not yet terminated, both properties may be {@code true} at once.
     *
     * @return {@code true} if the process is still running; otherwise, {@code false} if it has terminated
     */
    boolean isRunning();

    /**
     * Signals to the process that the {@link ProcessStdioHandler} has {@code stdin} to provide and is waiting for
     * a {@link ProcessStdioHandler#onStdinReady} call.
     * <p>
     * <b>Note</b>: If {@code stdin} has been {@link #closeStdin closed}, this method will throw an exception.
     */
    void wantWrite();

    /**
     * Queues the provided buffer to be written to the process's {@code stdin} pipe when space is available.
     * Multiple buffers can be queued for writing, and will be written sequentially.
     *
     * @param buffer a buffer containing one or more bytes to write to {@code stdin}
     */
    void writeStdin(@Nonnull ByteBuffer buffer);
}
