package com.atlassian.bitbucket.scm;

import javax.annotation.Nonnull;
import java.util.OptionalLong;

import static java.util.OptionalLong.empty;
import static java.util.OptionalLong.of;

/**
 * Provides a simple base class for building compatibility commands, allowing any timeout applied to the
 * command to be applied to other commands that are run to fulfill the request.
 *
 * @since 4.6
 */
@SuppressWarnings("OptionalUsedAsFieldOrParameterType")
abstract class AbstractCompatibilityCommand<T> implements Command<T> {

    private OptionalLong executionTimeout;
    private OptionalLong idleTimeout;

    public AbstractCompatibilityCommand() {
        executionTimeout = empty();
        idleTimeout = empty();
    }

    @Nonnull
    @Override
    public AsyncCommand<T> asynchronous() {
        throw new UnsupportedOperationException(getClass().getSimpleName() +
                " does not support asynchronous execution.");
    }

    @Override
    public void setExecutionTimeout(long executionTimeout) {
        this.executionTimeout = of(executionTimeout);
    }

    @Override
    public void setIdleTimeout(long idleTimeout) {
        this.idleTimeout = of(idleTimeout);
    }

    /**
     * Applies any timeouts which have been set and {@link Command#call calls} the command.
     *
     * @param command the command to configure and call
     * @param <C> the type of data the command will return
     * @return the result of calling the command
     */
    protected <C> C configureAndCall(Command<C> command) {
        executionTimeout.ifPresent(command::setExecutionTimeout);
        idleTimeout.ifPresent(command::setIdleTimeout);

        return command.call();
    }
}
