/*
 * Copyright (C) 2021 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.bedstead.nene.utils;

import androidx.annotation.CheckResult;
import androidx.annotation.Nullable;

import com.android.bedstead.nene.exceptions.AdbException;
import com.android.bedstead.nene.exceptions.NeneException;
import com.android.bedstead.nene.users.UserReference;

import java.util.function.Function;

/**
 * A tool for progressively building and then executing a shell command.
 */
public final class ShellCommand {

    // 10 seconds
    private static final int MAX_WAIT_UNTIL_ATTEMPTS = 100;
    private static final long WAIT_UNTIL_DELAY_MILLIS = 100;

    /**
     * Begin building a new {@link ShellCommand}.
     */
    @CheckResult
    public static Builder builder(String command) {
        if (command == null) {
            throw new NullPointerException();
        }
        return new Builder(command);
    }

    /**
     * Create a builder and if {@code userReference} is not {@code null}, add "--user <userId>".
     */
    @CheckResult
    public static Builder builderForUser(@Nullable UserReference userReference, String command) {
        Builder builder = builder(command);
        if (userReference != null) {
            builder.addOption("--user", userReference.id());
        }

        return builder;
    }

    public static final class Builder {
        private String mLinuxUser;
        private final StringBuilder commandBuilder;
        @Nullable
        private byte[] mStdInBytes = null;
        @Nullable
        private boolean mAllowEmptyOutput = false;
        @Nullable
        private Function<String, Boolean> mOutputSuccessChecker = null;

        private Builder(String command) {
            commandBuilder = new StringBuilder(command);
        }

        /**
         * Add an option to the command.
         *
         * <p>e.g. --user 10
         */
        @CheckResult
        public Builder addOption(String key, Object value) {
            // TODO: Deal with spaces/etc.
            commandBuilder.append(" ").append(key).append(" ").append(value);
            return this;
        }

        /**
         * Add an operand to the command.
         */
        @CheckResult
        public Builder addOperand(Object value) {
            // TODO: Deal with spaces/etc.
            commandBuilder.append(" ").append(value);
            return this;
        }

        /**
         * If {@code false} an error will be thrown if the command has no output.
         *
         * <p>Defaults to {@code false}
         */
        @CheckResult
        public Builder allowEmptyOutput(boolean allowEmptyOutput) {
            mAllowEmptyOutput = allowEmptyOutput;
            return this;
        }

        /**
         * Write the given {@code stdIn} to standard in.
         */
        @CheckResult
        public Builder writeToStdIn(byte[] stdIn) {
            mStdInBytes = stdIn;
            return this;
        }

        /**
         * Validate the output when executing.
         *
         * <p>{@code outputSuccessChecker} should return {@code true} if the output is valid.
         */
        @CheckResult
        public Builder validate(Function<String, Boolean> outputSuccessChecker) {
            mOutputSuccessChecker = outputSuccessChecker;
            return this;
        }

        /**
         * Build the full command including all options and operands.
         */
        public String build() {
            if (mLinuxUser != null) {
                return "su " + mLinuxUser + " " + commandBuilder.toString();
            }
            return commandBuilder.toString();
        }

        /**
         * See {@link #execute()} except that any {@link AdbException} is wrapped in a
         * {@link NeneException} with the message {@code errorMessage}.
         */
        public String executeOrThrowNeneException(String errorMessage) throws NeneException {
            try {
                return execute();
            } catch (AdbException e) {
                throw new NeneException(errorMessage, e);
            }
        }

        /** See {@link ShellCommandUtils#executeCommand(java.lang.String)}. */
        public String execute() throws AdbException {
            if (mOutputSuccessChecker != null) {
                return ShellCommandUtils.executeCommandAndValidateOutput(
                        build(),
                        /* allowEmptyOutput= */ mAllowEmptyOutput,
                        mStdInBytes,
                        mOutputSuccessChecker);
            }

            return ShellCommandUtils.executeCommand(
                    build(),
                    /* allowEmptyOutput= */ mAllowEmptyOutput,
                    mStdInBytes);
        }

        /**
         * See {@link #execute} and then extract information from the output using
         * {@code outputParser}.
         *
         * <p>If any {@link Exception} is thrown by {@code outputParser}, and {@link AdbException}
         * will be thrown.
         */
        public <E> E executeAndParseOutput(Function<String, E> outputParser) throws AdbException {
            String output = execute();

            try {
                return outputParser.apply(output);
            } catch (RuntimeException e) {
                throw new AdbException(
                        "Could not parse output", commandBuilder.toString(), output, e);
            }
        }

        /**
         * Execute the command and check that the output meets a given criteria. Run the
         * command repeatedly until the output meets the criteria.
         *
         * <p>{@code outputSuccessChecker} should return {@code true} if the output indicates the
         * command executed successfully.
         */
        public String executeUntilValid() throws InterruptedException, AdbException {
            int attempts = 0;
            while (attempts++ < MAX_WAIT_UNTIL_ATTEMPTS) {
                try {
                    return execute();
                } catch (AdbException e) {
                    // ignore, will retry
                    Thread.sleep(WAIT_UNTIL_DELAY_MILLIS);
                }
            }
            return execute();
        }

        public BytesBuilder forBytes() {
            if (mOutputSuccessChecker != null) {
                throw new IllegalStateException("Cannot call .forBytes after .validate");
            }

            return new BytesBuilder(this);
        }

        @Override
        public String toString() {
            return "ShellCommand$Builder{cmd=" + build() + "}";
        }
    }

    public static final class BytesBuilder {

        private final Builder mBuilder;

        private BytesBuilder(Builder builder) {
            mBuilder = builder;
        }

        /** See {@link ShellCommandUtils#executeCommandForBytes(java.lang.String)}. */
        public byte[] execute() throws AdbException {
            return ShellCommandUtils.executeCommandForBytes(
                    mBuilder.build(),
                    mBuilder.mStdInBytes);
        }
    }
}
