package com.atlassian.bitbucket.mesh.process.handler;

import com.atlassian.bitbucket.mesh.process.OsProcess;
import com.atlassian.bitbucket.mesh.process.ProcessStdioHandler;

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

/**
 * A base class for {@link ProcessStdioHandler} implementations which stores the {@link OsProcess} and
 * provides some convenience methods for interacting with it.
 *
 * @param <T> the type returned by {@link #getResult()}
 */
public abstract class AbstractProcessStdioHandler<T> implements ProcessStdioHandler<T> {

    protected volatile OsProcess process;

    @Override
    public void onPreStart(@Nonnull OsProcess process) {
        this.process = process;
    }

    @Override
    public boolean onStdinReady(@Nonnull ByteBuffer buffer) {
        buffer.flip();
        closeStdin();

        return false;
    }

    /**
     * Cancels the process, if {@link #onStart} has been called. Otherwise, does nothing.
     */
    protected void cancel() {
        OsProcess process = this.process;
        if (process != null) {
            process.cancel();
        }
    }

    /**
     * Closes the process's {@code stdin}.
     * <p>
     * <b>Note</b>: Calling this method has no effect before {@link #onStart} has been called.
     *
     * @return {@code true} if {@link #onStart} has been called and {@link OsProcess#closeStdin} was called;
     *         otherwise, {@code false} to indicate {@code stdin} was not closed
     */
    protected boolean closeStdin() {
        OsProcess process = this.process;
        if (process == null) {
            return false;
        }

        process.closeStdin(false);
        return true;
    }

    /**
     * Checks whether the process has already been canceled.
     *
     * @return {@code true} if the process has been canceled; otherwise, {@code false}
     */
    protected boolean isCanceled() {
        OsProcess process = this.process;

        return process != null && process.isCanceled();
    }
}
