//
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you 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.cloud.utils.script;

import com.cloud.utils.PropertiesUtil;
import com.cloud.utils.concurrency.NamedThreadFactory;
import com.cloud.utils.script.OutputInterpreter.TimedOutLogger;
import org.apache.cloudstack.utils.security.KeyStoreUtils;
import org.apache.commons.io.IOUtils;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;
import org.joda.time.Duration;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.Callable;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

public class Script implements Callable<String> {
    protected static Logger LOGGER = LogManager.getLogger(Script.class);

    private final Logger _logger;

    public static final String ERR_EXECUTE = "execute.error";
    public static final String ERR_TIMEOUT = "timeout";
    private int _defaultTimeout = 3600 * 1000; /* 1 hour */
    private volatile boolean _isTimeOut = false;

    private boolean _passwordCommand = false;
    private boolean avoidLoggingCommand = false;

    private static final ScheduledExecutorService s_executors = Executors.newScheduledThreadPool(10, new NamedThreadFactory("Script"));

    String _workDir;
    ArrayList<String> _command;
    long _timeout;
    Process _process;
    Thread _thread;

    public boolean isTimeout() {
        return _isTimeOut;
    }

    public int getExitValue() {
        return _process.exitValue();
    }

    public void setAvoidLoggingCommand(boolean avoid) {
        avoidLoggingCommand = avoid;
    }

    public Script(String command, Duration timeout, Logger logger) {
        this(command, timeout.getMillis(), logger);
    }

    @Deprecated
    public Script(String command, long timeout, Logger logger) {
        _command = new ArrayList<String>();
        _command.add(command);
        _timeout = timeout;
        if (_timeout == 0) {
            /* always using default timeout 1 hour to avoid thread hang */
            _timeout = _defaultTimeout;
        }
        _process = null;
        _logger = logger != null ? logger : Script.LOGGER;
    }

    public Script(boolean runWithSudo, String command, Duration timeout, Logger logger) {
        this(runWithSudo, command, timeout.getMillis(), logger);
    }

    @Deprecated
    public Script(boolean runWithSudo, String command, long timeout, Logger logger) {
        this(command, timeout, logger);
        if (runWithSudo) {
            _command.add(0, "sudo");
        }
    }

    public Script(String command, Logger logger) {
        this(command, 0, logger);
    }

    public Script(String command) {
        this(command, 0, LOGGER);
    }

    public Script(String command, Duration timeout) {
        this(command, timeout.getMillis(), LOGGER);
    }

    @Deprecated
    public Script(String command, long timeout) {
        this(command, timeout, LOGGER);
    }

    public void add(String... params) {
        for (String param : params) {
            _command.add(param);
        }
    }

    public void add(String param) {
        _command.add(param);
    }

    public Script set(String name, String value) {
        _command.add(name);
        _command.add(value);
        return this;
    }

    public void setWorkDir(String workDir) {
        _workDir = workDir;
    }

    protected String buildCommandLine(String[] command) {
        StringBuilder builder = new StringBuilder();
        boolean obscureParam = false;
        for (int i = 0; i < command.length; i++) {
            String cmd = command[i];
            if (obscureParam) {
                builder.append("******").append(" ");
                obscureParam = false;
            } else {
                builder.append(command[i]).append(" ");
            }

            if ("-y".equals(cmd) || "-z".equals(cmd)) {
                obscureParam = true;
                _passwordCommand = true;
            }
        }
        return builder.toString();
    }

    protected String buildCommandLine(List<String> command) {
        StringBuilder builder = new StringBuilder();
        boolean obscureParam = false;
        for (String cmd : command) {
            if (obscureParam) {
                builder.append("******").append(" ");
                obscureParam = false;
            } else {
                builder.append(cmd).append(" ");
            }

            if ("-y".equals(cmd) || "-z".equals(cmd)) {
                obscureParam = true;
                _passwordCommand = true;
            }
        }
        return builder.toString();
    }

    public long getTimeout() {
        return _timeout;
    }

    public String execute() {
        return execute(new OutputInterpreter.OutputLogger(_logger));
    }

    @Override
    public String toString() {
        String[] command = _command.toArray(new String[_command.size()]);
        return buildCommandLine(command);
    }

    static String stackTraceAsString(Throwable throwable) {
        //TODO: a StringWriter is bit to heavy weight
        try(StringWriter out = new StringWriter(); PrintWriter writer = new PrintWriter(out);) {
            throwable.printStackTrace(writer);
            return out.toString();
        } catch (IOException e) {
            return "";
        }
    }

    public String execute(OutputInterpreter interpreter) {
        String[] command = _command.toArray(new String[_command.size()]);
        String commandLine = buildCommandLine(command);
        if (_logger.isDebugEnabled() && !avoidLoggingCommand) {
            _logger.debug(String.format("Executing command [%s].", commandLine.split(KeyStoreUtils.KS_FILENAME)[0]));
        }

        try {
            _logger.trace(String.format("Creating process for command [%s].", commandLine));
            ProcessBuilder pb = new ProcessBuilder(command);
            pb.redirectErrorStream(true);
            if (_workDir != null)
                pb.directory(new File(_workDir));

            _logger.trace(String.format("Starting process for command [%s].", commandLine));
            _process = pb.start();
            if (_process == null) {
                _logger.warn(String.format("Unable to execute command [%s] because no process was created.", commandLine));
                return "Unable to execute the command: " + command[0];
            }

            BufferedReader ir = new BufferedReader(new InputStreamReader(_process.getInputStream()));

            _thread = Thread.currentThread();
            ScheduledFuture<String> future = null;
            if (_timeout > 0) {
                _logger.trace(String.format("Scheduling the execution of command [%s] with a timeout of [%s] milliseconds.", commandLine, _timeout));
                future = s_executors.schedule(this, _timeout, TimeUnit.MILLISECONDS);
            }

            long processPid = _process.pid();
            Task task = null;
            if (interpreter != null && interpreter.drain()) {
                _logger.trace(String.format("Executing interpreting task of process [%s] for command [%s].", processPid, commandLine));
                task = new Task(interpreter, ir);
                s_executors.execute(task);
            }

            while (true) {
                _logger.trace(String.format("Attempting process [%s] execution for command [%s] with timeout [%s].", processPid, commandLine, _timeout));
                try {
                    if (_process.waitFor(_timeout, TimeUnit.MILLISECONDS)) {
                        _logger.trace(String.format("Process [%s] execution for command [%s] completed within timeout period [%s].", processPid, commandLine,
                                _timeout));
                        if (_process.exitValue() == 0) {
                            _logger.debug(String.format("Successfully executed process [%s] for command [%s].", processPid, commandLine));
                            if (interpreter != null) {
                                if (interpreter.drain()) {
                                    _logger.trace(String.format("Returning task result of process [%s] for command [%s].", processPid, commandLine));
                                    return task.getResult();
                                }
                                _logger.trace(String.format("Returning interpretation of process [%s] for command [%s].", processPid, commandLine));
                                return interpreter.interpret(ir);
                            } else {
                                // null return exitValue apparently
                                _logger.trace(String.format("Process [%s] for command [%s] exited with value [%s].", processPid, commandLine,
                                        _process.exitValue()));
                                return String.valueOf(_process.exitValue());
                            }
                        } else {
                            _logger.warn(String.format("Execution of process [%s] for command [%s] failed.", processPid, commandLine));
                            break;
                        }
                    }
                } catch (InterruptedException e) {
                    if (!_isTimeOut) {
                        _logger.debug(String.format("Exception [%s] occurred; however, it was not a timeout. Therefore, proceeding with the execution of process [%s] for command "
                                + "[%s].", e.getMessage(), processPid, commandLine), e);
                        continue;
                    }
                } finally {
                    if (future != null) {
                        future.cancel(false);
                    }
                    Thread.interrupted();
                }

                TimedOutLogger log = new TimedOutLogger(_process);
                Task timedoutTask = new Task(log, ir);

                _logger.trace(String.format("Running timed out task of process [%s] for command [%s].", processPid, commandLine));
                timedoutTask.run();
                if (!_passwordCommand) {
                    _logger.warn(String.format("Process [%s] for command [%s] timed out. Output is [%s].", processPid, commandLine, timedoutTask.getResult()));
                } else {
                    _logger.warn(String.format("Process [%s] for command [%s] timed out.", processPid, commandLine));
                }

                return ERR_TIMEOUT;
            }

            _logger.debug(String.format("Exit value of process [%s] for command [%s] is [%s].", processPid, commandLine, _process.exitValue()));

            BufferedReader reader = new BufferedReader(new InputStreamReader(_process.getInputStream()), 128);

            String error;
            if (interpreter != null) {
                error = interpreter.processError(reader);
            } else {
                error = String.valueOf(_process.exitValue());
            }

            _logger.warn(String.format("Process [%s] for command [%s] encountered the error: [%s].", processPid, commandLine, error));

            return error;
        } catch (SecurityException ex) {
            _logger.warn(String.format("Exception [%s] occurred. This may be due to an attempt of executing command [%s] as non root.", ex.getMessage(), commandLine),
                    ex);
            return stackTraceAsString(ex);
        } catch (Exception ex) {
            _logger.warn(String.format("Exception [%s] occurred when attempting to run command [%s].", ex.getMessage(), commandLine), ex);
            return stackTraceAsString(ex);
        } finally {
            if (_process != null) {
                _logger.trace(String.format("Destroying process [%s] for command [%s].", _process.pid(), commandLine));
                IOUtils.closeQuietly(_process.getErrorStream());
                IOUtils.closeQuietly(_process.getOutputStream());
                IOUtils.closeQuietly(_process.getInputStream());
                _process.destroyForcibly();
            }
        }
    }

    public String executeIgnoreExitValue(OutputInterpreter interpreter, int exitValue) {
        String[] command = _command.toArray(new String[_command.size()]);

        if (_logger.isDebugEnabled()) {
            _logger.debug(String.format("Executing: %s", buildCommandLine(command).split(KeyStoreUtils.KS_FILENAME)[0]));
        }

        try {
            ProcessBuilder pb = new ProcessBuilder(command);
            pb.redirectErrorStream(true);
            if (_workDir != null)
                pb.directory(new File(_workDir));

            _process = pb.start();
            if (_process == null) {
                _logger.warn(String.format("Unable to execute: %s", buildCommandLine(command)));
                return String.format("Unable to execute the command: %s", command[0]);
            }

            BufferedReader ir = new BufferedReader(new InputStreamReader(_process.getInputStream()));

            _thread = Thread.currentThread();
            ScheduledFuture<String> future = null;
            if (_timeout > 0) {
                future = s_executors.schedule(this, _timeout, TimeUnit.MILLISECONDS);
            }

            Task task = null;
            if (interpreter != null && interpreter.drain()) {
                task = new Task(interpreter, ir);
                s_executors.execute(task);
            }

            while (true) {
                _logger.debug(String.format("Executing while with timeout : %d", _timeout));
                try {
                    //process execution completed within timeout period
                    if (_process.waitFor(_timeout, TimeUnit.MILLISECONDS)) {
                        //process completed successfully
                        if (_process.exitValue() == 0 || _process.exitValue() == exitValue) {
                            _logger.debug("Execution is successful.");
                            if (interpreter != null) {
                                return interpreter.drain() ? task.getResult() : interpreter.interpret(ir);
                            } else {
                                // null return exitValue apparently
                                return String.valueOf(_process.exitValue());
                            }
                        } else { //process failed
                            break;
                        }
                    } //timeout
                } catch (InterruptedException e) {
                    if (!_isTimeOut) {
                        /*
                         * This is not timeout, we are interrupted by others,
                         * continue
                         */
                        _logger.debug("We are interrupted but it's not a timeout, just continue");
                        continue;
                    }
                } finally {
                    if (future != null) {
                        future.cancel(false);
                    }
                    Thread.interrupted();
                }

                //timeout without completing the process
                TimedOutLogger log = new TimedOutLogger(_process);
                Task timedoutTask = new Task(log, ir);

                timedoutTask.run();
                if (!_passwordCommand) {
                    _logger.warn(String.format("Timed out: %s.  Output is: %s", buildCommandLine(command), timedoutTask.getResult()));
                } else {
                    _logger.warn(String.format("Timed out: %s", buildCommandLine(command)));
                }

                return ERR_TIMEOUT;
            }

            _logger.debug(String.format("Exit value is %d", _process.exitValue()));

            BufferedReader reader = new BufferedReader(new InputStreamReader(_process.getInputStream()), 128);

            String error;
            if (interpreter != null) {
                error = interpreter.processError(reader);
            } else {
                error = String.valueOf(_process.exitValue());
            }

            if (_logger.isDebugEnabled()) {
                _logger.debug(error);
            }
            return error;
        } catch (SecurityException ex) {
            _logger.warn("Security Exception....not running as root?", ex);
            return stackTraceAsString(ex);
        } catch (Exception ex) {
            _logger.warn(String.format("Exception: %s", buildCommandLine(command)), ex);
            return stackTraceAsString(ex);
        } finally {
            if (_process != null) {
                IOUtils.closeQuietly(_process.getErrorStream());
                IOUtils.closeQuietly(_process.getOutputStream());
                IOUtils.closeQuietly(_process.getInputStream());
                _process.destroyForcibly();
            }
        }
    }

    @Override
    public String call() {
        try {
            _logger.trace("Checking exit value of process");
            _process.exitValue();
            _logger.trace("Script ran within the allocated time");
        } catch (IllegalThreadStateException e) {
            _logger.warn("Interrupting script.");
            _isTimeOut = true;
            _thread.interrupt();
        }
        return null;
    }

    public static class Task implements Runnable {
        OutputInterpreter interpreter;
        BufferedReader reader;
        String result;
        boolean done;

        public Task(OutputInterpreter interpreter, BufferedReader reader) {
            this.interpreter = interpreter;
            this.reader = reader;
            result = null;
        }

        @Override
        public void run() {
            synchronized(this) {
                done = false;
                try {
                    result = interpreter.interpret(reader);
                } catch (IOException ex) {
                    result = stackTraceAsString(ex);
                } catch (Exception ex) {
                    result = stackTraceAsString(ex);
                } finally {
                        done = true;
                        notifyAll();
                        IOUtils.closeQuietly(reader);
                }
            }
        }

        public synchronized String getResult() throws InterruptedException {
            if (!done) {
                wait();
            }
            return result;
        }
    }

    public static String findScript(String path, String script) {
        LOGGER.debug("Looking for " + script + " in the classpath");

        URL url = ClassLoader.getSystemResource(script);
        LOGGER.debug("System resource: " + url);
        File file = null;
        if (url != null) {
            file = new File(url.getFile());
            LOGGER.debug("Absolute path =  " + file.getAbsolutePath());
            return file.getAbsolutePath();
        }

        if (path == null) {
            LOGGER.warn("No search path specified, unable to look for " + script);
            return null;
        }
        path = path.replace("/", File.separator);

        /**
         * Look in WEB-INF/classes of the webapp
         * URI workaround the URL encoding of url.getFile
         */
        if (path.endsWith(File.separator)) {
            url = Script.class.getClassLoader().getResource(path + script);
        } else {
            url = Script.class.getClassLoader().getResource(path + File.separator + script);
        }
        LOGGER.debug("Classpath resource: " + url);
        if (url != null) {
            try {
                file = new File(new URI(url.toString()).getPath());
                LOGGER.debug("Absolute path =  " + file.getAbsolutePath());
                return file.getAbsolutePath();
            } catch (URISyntaxException e) {
                LOGGER.warn("Unable to convert " + url.toString() + " to a URI");
            }
        }

        if (path.endsWith(File.separator)) {
            path = path.substring(0, path.lastIndexOf(File.separator));
        }

        if (path.startsWith(File.separator)) {
            // Path given was absolute so we assume the caller knows what they want.
            file = new File(path + File.separator + script);
            return file.exists() ? file.getAbsolutePath() : null;
        }

        LOGGER.debug("Looking for " + script);
        String search = null;
        for (int i = 0; i < 3; i++) {
            if (i == 0) {
                String cp = Script.class.getResource(Script.class.getSimpleName() + ".class").toExternalForm();
                int begin = cp.indexOf(File.separator);

                // work around with the inconsistency of java classpath and file separator on Windows 7
                if (begin < 0)
                    begin = cp.indexOf('/');

                int endBang = cp.lastIndexOf("!");
                int end = cp.lastIndexOf(File.separator, endBang);
                if (end < 0)
                    end = cp.lastIndexOf('/', endBang);
                if (end < 0)
                    cp = cp.substring(begin);
                else
                    cp = cp.substring(begin, end);

                LOGGER.debug("Current binaries reside at " + cp);
                search = cp;
            } else if (i == 1) {
                LOGGER.debug("Searching in environment.properties");
                try {
                    final File propsFile = PropertiesUtil.findConfigFile("environment.properties");
                    if (propsFile == null) {
                        LOGGER.debug("environment.properties could not be opened");
                    } else {
                        final Properties props = PropertiesUtil.loadFromFile(propsFile);
                        search = props.getProperty("paths.script");
                    }
                } catch (IOException e) {
                    LOGGER.debug("environment.properties could not be opened");
                    continue;
                }
                LOGGER.debug("environment.properties says scripts should be in " + search);
            } else {
                LOGGER.debug("Searching in the current directory");
                search = ".";
            }

            search += File.separatorChar + path + File.separator;
            do {
                search = search.substring(0, search.lastIndexOf(File.separator));
                file = new File(search + File.separator + script);
                LOGGER.debug("Looking for " + script + " in " + file.getAbsolutePath());
            } while (!file.exists() && search.lastIndexOf(File.separator) != -1);

            if (file.exists()) {
                return file.getAbsolutePath();
            }

        }

        search = System.getProperty("paths.script");

        search += File.separatorChar + path + File.separator;
        do {
            search = search.substring(0, search.lastIndexOf(File.separator));
            file = new File(search + File.separator + script);
            LOGGER.debug("Looking for " + script + " in " + file.getAbsolutePath());
        } while (!file.exists() && search.lastIndexOf(File.separator) != -1);

        if (file.exists()) {
            return file.getAbsolutePath();
        }

        LOGGER.warn("Unable to find script " + script);
        return null;
    }

    public static String runSimpleBashScript(String command) {
        return Script.runSimpleBashScript(command, 0);
    }

    public static String runSimpleBashScript(String command, int timeout) {

        Script s = new Script("/bin/bash", timeout);
        s.add("-c");
        s.add(command);

        OutputInterpreter.OneLineParser parser = new OutputInterpreter.OneLineParser();
        if (s.execute(parser) != null)
            return null;

        String result = parser.getLine();
        if (result == null || result.trim().isEmpty())
            return null;
        else
            return result.trim();
    }

    public static int runSimpleBashScriptForExitValue(String command) {
        return runSimpleBashScriptForExitValue(command, 0, false);
    }

    public static int runSimpleBashScriptForExitValueAvoidLogging(String command) {
        return runSimpleBashScriptForExitValue(command, 0, true);
    }

    /**
     * Executes a bash script and returns the exit value of the script.
     *
     * @param command
     *         The bash command to be executed.
     * @param timeout
     *         The maximum time (in milliseconds) that the script is allowed to run before it is forcibly terminated.
     * @param avoidLogging
     *         If set to true, some logging is avoided.
     *
     * @return The exit value of the script. Returns -1 if the result is null or empty, or if it cannot be parsed into
     *         an integer which can happen in case of a timeout.
     */
    public static int runSimpleBashScriptForExitValue(String command, int timeout, boolean avoidLogging) {

        Script s = new Script("/bin/bash", timeout);
        s.add("-c");
        s.add(command);
        s.setAvoidLoggingCommand(avoidLogging);

        String result = s.execute(null);
        if (result == null || result.trim().isEmpty())
            return -1;
        else {
            try {
                return Integer.parseInt(result.trim());
            } catch (NumberFormatException e) {
                return -1;
            }
        }
    }

    public static String runBashScriptIgnoreExitValue(String command, int exitValue) {
        return runBashScriptIgnoreExitValue(command, exitValue, 0);
    }

    public static String runBashScriptIgnoreExitValue(String command, int exitValue, int timeout) {

        Script s = new Script("/bin/bash", timeout);
        s.add("-c");
        s.add(command);

        OutputInterpreter.AllLinesParser parser = new OutputInterpreter.AllLinesParser();
        s.executeIgnoreExitValue(parser, exitValue);

        String result = parser.getLines();
        if (result == null || result.trim().isEmpty()) {
            return null;
        } else {
            return result.trim();
        }
    }
}
