package org.implab.gradle.common.exec.model;

import java.io.File;

import org.eclipse.jdt.annotation.NonNullByDefault;
import org.implab.gradle.common.core.lang.Values;

/** Command builder interface, used to specify the executable and parameters */
@NonNullByDefault
public interface CommandBuilder extends CommandArgumentsBuilder<CommandBuilder> {

    @Override
    default CommandBuilder self() {
        return this;
    }

    /** Sets the executable, the parameters are left intact. */
    CommandBuilder executable(String executable);

    default CommandBuilder executable(File executable) {
        executable(executable.toString());
        return this;
    }

    /**
     * Sets the specified executable and parameters, old executable and parameters
     * are discarded.
     */
    default CommandBuilder commandLine(String executable, String... args) {
        return executable(executable)
                .arguments(args);
    }

    /**
     * Sets the specified executable and parameters, old executable and parameters
     * are discarded.
     *
     * @param command The command line. Must contain at least one element
     *                (executable).
     *
     */
    default CommandBuilder commandLine(Iterable<? extends String> command) {
        var iterator = command.iterator();

        // set executable
        executable(Values.take(iterator).orElseThrow());
        // cleat arguments
        arguments();

        // set new arguments
        while (iterator.hasNext())
            addArguments(iterator.next());

        return this;
    }

    default CommandBuilder from(CommandSpec commandSpec) {
        return executable(commandSpec.executable())
                .arguments(commandSpec.arguments());
    }

    CommandSpec build();
}
