package com.atlassian.bitbucket.scm.ssh;

import com.atlassian.bitbucket.AuthorisationException;
import com.atlassian.bitbucket.repository.NoSuchRepositoryException;

import javax.annotation.Nonnull;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Optional;

/**
 * Plugin point for handling {@link SshScmRequest}s.
 *
 * @see SshScmRequestHandlerModuleDescriptor
 */
public interface SshScmRequestHandler {

    /**
     * Returns an {@link SshScmRequest} if this handler can handle the supplied command string, or
     * {@link Optional#empty()} otherwise.
     *
     * @param command the command String passed from the remote SSH client (e.g. "git-upload-pack path/to/repository")
     * @param in the {@link InputStream} from the remote client
     * @param out the {@link OutputStream} for writing output to the remote client
     * @param error the error {@link OutputStream} for writing to the remote client's error stream
     * @param exitCodeCallback used to set the exit code returned to the remote client. If the callback is not invoked
     *        a return code of 1 will be used
     * @return an {@link SshScmRequest} if this factory supports the specified command, or {@link Optional#empty()} to
     * indicate that this factory does not support the command.
     * @throws NoSuchRepositoryException if this factory supports the specified command, but the repository could not be found
     * @throws AuthorisationException if the repository is not accessible
     */
    @Nonnull
    Optional<SshScmRequest> create(@Nonnull String command, @Nonnull InputStream in, @Nonnull OutputStream out,
                                   @Nonnull OutputStream error, @Nonnull ExitCodeCallback exitCodeCallback);

    /**
     * @param command the command String passed from the remote SSH client (e.g. "git-upload-pack path/to/repository")
     * @return {@code true} if the handler supports the supplied command, {@code false} otherwise
     */
    boolean supports(@Nonnull String command);
}
