/*
 * 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 org.apache.geode.management.internal.cli.shell;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintStream;
import java.net.URL;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
import java.util.TreeMap;
import java.util.logging.Level;
import java.util.logging.LogManager;
import java.util.logging.Logger;

import jline.Terminal;
import jline.console.ConsoleReader;
import org.springframework.shell.core.AbstractShell;
import org.springframework.shell.core.ExecutionStrategy;
import org.springframework.shell.core.ExitShellRequest;
import org.springframework.shell.core.JLineLogHandler;
import org.springframework.shell.core.JLineShell;
import org.springframework.shell.core.Parser;
import org.springframework.shell.event.ShellStatus.Status;

import org.apache.geode.annotations.internal.MakeNotStatic;
import org.apache.geode.annotations.internal.MutableForTesting;
import org.apache.geode.internal.GemFireVersion;
import org.apache.geode.internal.lang.ClassUtils;
import org.apache.geode.internal.logging.Banner;
import org.apache.geode.internal.process.signal.AbstractSignalNotificationHandler;
import org.apache.geode.internal.serialization.Version;
import org.apache.geode.internal.util.ArgumentRedactor;
import org.apache.geode.internal.util.HostName;
import org.apache.geode.internal.util.SunAPINotFoundException;
import org.apache.geode.logging.internal.executors.LoggingThread;
import org.apache.geode.management.cli.CommandProcessingException;
import org.apache.geode.management.cli.Result;
import org.apache.geode.management.internal.cli.CliUtil;
import org.apache.geode.management.internal.cli.CommandManager;
import org.apache.geode.management.internal.cli.GfshParser;
import org.apache.geode.management.internal.cli.LogWrapper;
import org.apache.geode.management.internal.cli.i18n.CliStrings;
import org.apache.geode.management.internal.cli.result.CommandResult;
import org.apache.geode.management.internal.cli.result.model.ResultModel;
import org.apache.geode.management.internal.cli.shell.jline.ANSIHandler;
import org.apache.geode.management.internal.cli.shell.jline.ANSIHandler.ANSIStyle;
import org.apache.geode.management.internal.cli.shell.jline.GfshHistory;
import org.apache.geode.management.internal.cli.shell.jline.GfshUnsupportedTerminal;
import org.apache.geode.management.internal.cli.shell.unsafe.GfshSignalHandler;
import org.apache.geode.management.internal.cli.util.CommentSkipHelper;

/**
 * Extends an interactive shell provided by
 * <a href="https://github.com/SpringSource/spring-shell">Spring Shell</a> library.
 *
 * <p>
 * This class is used to plug-in implementations of the following Spring (Roo) Shell components
 * customized to suite GemFire Command Line Interface (CLI) requirements:
 * <ul>
 * <li><code>org.springframework.roo.shell.ExecutionStrategy</code>
 * <li><code>org.springframework.roo.shell.Parser</code>
 * </ul>
 * <p />
 * Additionally, this class is used to maintain GemFire SHell (gfsh) specific information like:
 * environment
 *
 * <p>
 * Additionally, this class is used to maintain GemFire SHell (gfsh) specific information
 *
 * @since GemFire 7.0
 */
public class Gfsh extends JLineShell {
  public static final int DEFAULT_APP_FETCH_SIZE = 100;
  public static final int DEFAULT_APP_LAST_EXIT_STATUS = 0;
  public static final int DEFAULT_APP_COLLECTION_LIMIT = 20;
  public static final boolean DEFAULT_APP_QUIET_EXECUTION = false;
  public static final String DEFAULT_APP_QUERY_RESULTS_DISPLAY_MODE = "table";
  public static final String DEFAULT_APP_RESULT_VIEWER = "basic";
  public static final String EXTERNAL_RESULT_VIEWER = "external";

  public static final String GFSH_APP_NAME = "gfsh";

  public static final String LINE_INDENT = "    ";
  public static final String LINE_SEPARATOR = System.getProperty("line.separator");
  // Default Window dimensions
  public static final int DEFAULT_WIDTH = 100;
  public static final String ENV_APP_NAME = "APP_NAME";
  public static final String ENV_APP_CONTEXT_PATH = "APP_CONTEXT_PATH";
  public static final String ENV_APP_FETCH_SIZE = "APP_FETCH_SIZE";
  public static final String ENV_APP_LAST_EXIT_STATUS = "APP_LAST_EXIT_STATUS";
  public static final String ENV_APP_COLLECTION_LIMIT = "APP_COLLECTION_LIMIT";
  public static final String ENV_APP_QUERY_RESULTS_DISPLAY_MODE = "APP_QUERY_RESULTS_DISPLAY_MODE";
  public static final String ENV_APP_QUIET_EXECUTION = "APP_QUIET_EXECUTION";
  public static final String ENV_APP_LOGGING_ENABLED = "APP_LOGGING_ENABLED";
  public static final String ENV_APP_LOG_FILE = "APP_LOG_FILE";
  public static final String ENV_APP_PWD = "APP_PWD";
  public static final String ENV_APP_RESULT_VIEWER = "APP_RESULT_VIEWER";
  // Environment Properties taken from the OS
  public static final String ENV_SYS_USER = "SYS_USER";
  public static final String ENV_SYS_USER_HOME = "SYS_USER_HOME";
  public static final String ENV_SYS_HOST_NAME = "SYS_HOST_NAME";
  public static final String ENV_SYS_CLASSPATH = "SYS_CLASSPATH";
  public static final String ENV_SYS_JAVA_VERSION = "SYS_JAVA_VERSION";
  public static final String ENV_SYS_OS = "SYS_OS";
  public static final String ENV_SYS_OS_LINE_SEPARATOR = "SYS_OS_LINE_SEPARATOR";
  public static final String ENV_SYS_GEODE_HOME_DIR = "SYS_GEODE_HOME_DIR";


  private static final String DEFAULT_SECONDARY_PROMPT = ">";
  private static final int DEFAULT_HEIGHT = 100;
  private static final Object INSTANCE_LOCK = new Object();

  @MutableForTesting
  protected static PrintStream gfshout = System.out;
  @MutableForTesting
  protected static PrintStream gfsherr = System.err;
  protected static final ThreadLocal<Gfsh> gfshThreadLocal = new ThreadLocal<>();
  @MakeNotStatic
  private static volatile Gfsh instance;
  // This flag is used to restrict column trimming to table only types
  private static final ThreadLocal<Boolean> resultTypeTL = new ThreadLocal<>();
  private static final String OS = System.getProperty("os.name").toLowerCase();
  private final Map<String, String> env = new TreeMap<>();
  private final List<String> readonlyAppEnv = new ArrayList<>();
  // Map to keep reference to actual user specified Command String
  // Should always have one value at the max
  private final Map<String, String> expandedPropCommandsMap = new HashMap<>();
  private final ExecutionStrategy executionStrategy;
  private final GfshParser parser;
  private final LogWrapper gfshFileLogger;
  private final GfshConfig gfshConfig;
  private final GfshHistory gfshHistory;
  private final ANSIHandler ansiHandler;
  private final boolean isHeadlessMode;
  private OperationInvoker operationInvoker;
  private int lastExecutionStatus;
  private Thread runner;
  private boolean debugON;
  private Terminal terminal;
  private boolean suppressScriptCmdOutput;
  private boolean isScriptRunning;
  private AbstractSignalNotificationHandler signalHandler;

  public Gfsh() {
    this(null);
  }

  /**
   * Create a GemFire shell with console using the specified arguments.
   *
   * @param args arguments to be used to create a GemFire shell instance
   */
  protected Gfsh(String[] args) {
    this(true, args, new GfshConfig());
  }

  /**
   * Create a GemFire shell using the specified arguments. Console for user inputs is made available
   * if <code>launchShell</code> is set to <code>true</code>.
   *
   * @param launchShell whether to make Console available
   * @param args arguments to be used to create a GemFire shell instance or execute command
   */
  protected Gfsh(boolean launchShell, String[] args, GfshConfig gfshConfig) {
    // 1. Disable suppressing of duplicate messages
    JLineLogHandler.setSuppressDuplicateMessages(false);

    // 2. set & use gfshConfig
    this.gfshConfig = gfshConfig;
    // The cache doesn't exist yet, since we are still setting up parsing.
    this.gfshFileLogger = LogWrapper.getInstance(null);
    this.gfshFileLogger.configure(this.gfshConfig);
    this.ansiHandler = ANSIHandler.getInstance(this.gfshConfig.isANSISupported());

    // 3. log system properties & gfsh environment TODO: change GFSH to use Geode logging
    this.gfshFileLogger.info(new Banner().getString());

    // 4. Customized History implementation
    this.gfshHistory = new GfshHistory();

    // 6. Set System Environment here
    initializeEnvironment();
    // 7. Create Roo/SpringShell framework objects
    this.executionStrategy = new GfshExecutionStrategy(this);
    this.parser = new GfshParser(new CommandManager());
    // 8. Set max History file size
    setHistorySize(gfshConfig.getHistorySize());

    String envProps = env.toString();
    envProps = envProps.substring(1, envProps.length() - 1);
    envProps = envProps.replaceAll(",", LINE_SEPARATOR);
    this.gfshFileLogger.config("***** gfsh Environment ******" + LINE_SEPARATOR + envProps);

    if (this.gfshFileLogger.fineEnabled()) {
      String gfshConfigStr = this.gfshConfig.toString();
      gfshConfigStr = gfshConfigStr.substring(0, gfshConfigStr.length() - 1);
      gfshConfigStr = gfshConfigStr.replaceAll(",", LINE_SEPARATOR);
      this.gfshFileLogger.fine("***** gfsh Configuration ******" + LINE_SEPARATOR + gfshConfigStr);
    }

    // Setup signal handler for various signals (such as CTRL-C)...
    try {
      ClassUtils.forName("sun.misc.Signal", new SunAPINotFoundException(
          "WARNING!!! Not running a Sun JVM.  Could not find the sun.misc.Signal class; Signal handling disabled."));
      signalHandler = new GfshSignalHandler();
    } catch (SunAPINotFoundException e) {
      signalHandler = new AbstractSignalNotificationHandler() {};
      this.gfshFileLogger.warning(e.getMessage());
    }

    // For test code only
    if (this.gfshConfig.isTestConfig()) {
      instance = this;
    }
    this.isHeadlessMode = !launchShell;
    if (this.isHeadlessMode) {
      this.gfshFileLogger.config("Running in headless mode");
      // disable jline terminal
      System.setProperty("jline.terminal", GfshUnsupportedTerminal.class.getName());
      env.put(ENV_APP_QUIET_EXECUTION, String.valueOf(true));
      // Only in headless mode, we do not want Gfsh's logger logs on screen
      this.gfshFileLogger.setParentFor(logger);
    }
    // we want to direct internal JDK logging to file in either mode
    redirectInternalJavaLoggers();
  }

  public static Gfsh getInstance(boolean launchShell, String[] args, GfshConfig gfshConfig) {
    Gfsh localGfshInstance = instance;
    if (localGfshInstance == null) {
      synchronized (INSTANCE_LOCK) {
        localGfshInstance = instance;
        if (localGfshInstance == null) {
          localGfshInstance = new Gfsh(launchShell, args, gfshConfig);
          localGfshInstance.executeInitFileIfPresent();
          instance = localGfshInstance;
        }
      }
    }

    return instance;
  }

  public static boolean isInfoResult() {
    if (resultTypeTL.get() == null) {
      return false;
    }
    return resultTypeTL.get();
  }

  public static void println() {
    gfshout.println();
  }

  public static void println(Object toPrint) {
    gfshout.println(toPrint);
  }

  public static void print(Object toPrint) {
    gfshout.print(toPrint);
  }

  public static void printlnErr(Object toPrint) {
    gfsherr.println(toPrint);
  }

  // See 46369
  private static String readLine(ConsoleReader reader, String prompt) throws IOException {
    String earlierLine = reader.getCursorBuffer().toString();
    String readLine;
    try {
      readLine = reader.readLine(prompt);
    } catch (IndexOutOfBoundsException e) {
      if (earlierLine.length() == 0) {
        reader.println();
        readLine = LINE_SEPARATOR;
        reader.getCursorBuffer().cursor = 0;
      } else {
        readLine = readLine(reader, prompt);
      }
    }
    return readLine;
  }

  private static String removeBackslash(String result) {
    if (result.endsWith(GfshParser.CONTINUATION_CHARACTER)) {
      result = result.substring(0, result.length() - 1);
    }
    return result;
  }

  /**
   * This method sets the parent of all loggers whose name starts with "java" or "javax" to
   * LogWrapper.
   *
   * logWrapper disables any parents's log handler, and only logs to the file if specified. This
   * would prevent JDK's logging show up in the console
   */
  public void redirectInternalJavaLoggers() {
    // Do we need to this on re-connect?
    LogManager logManager = LogManager.getLogManager();

    try {
      Enumeration<String> loggerNames = logManager.getLoggerNames();

      while (loggerNames.hasMoreElements()) {
        String loggerName = loggerNames.nextElement();
        if (loggerName.startsWith("java.") || loggerName.startsWith("javax.")) {
          Logger javaLogger = logManager.getLogger(loggerName);
          /*
           * From Java Docs: It is also important to note that the Logger associated with the String
           * name may be garbage collected at any time if there is no strong reference to the
           * Logger. The caller of this method must check the return value for null in order to
           * properly handle the case where the Logger has been garbage collected.
           */
          if (javaLogger != null) {
            this.gfshFileLogger.setParentFor(javaLogger);
          }
        }
      }
    } catch (SecurityException e) {
      this.gfshFileLogger.warning(e.getMessage(), e);
    }
  }

  public static Gfsh getCurrentInstance() {
    return instance;
  }

  private static String extractKey(String input) {
    return input.substring("${".length(), input.length() - "}".length());
  }

  public static ConsoleReader getConsoleReader() {
    Gfsh gfsh = Gfsh.getCurrentInstance();
    return (gfsh == null ? null : gfsh.reader);
  }

  /**
   * Take a string and wrap it into multiple lines separated by CliConstants.LINE_SEPARATOR. Lines
   * are separated based upon the terminal width, separated on word boundaries and may have extra
   * spaces added to provide indentation.
   *
   * For example: if the terminal width were 5 and the string "123 456789 01234" were passed in with
   * an indentation level of 2, then the returned string would be:
   *
   * <pre>
   *         123
   *         45678
   *         9
   *         01234
   * </pre>
   *
   * @param string String to wrap (add breakpoints and indent)
   * @param indentationLevel The number of indentation levels to use.
   * @return The wrapped string.
   */
  public static String wrapText(final String string, final int indentationLevel,
      final int terminalWidth) {
    if (terminalWidth <= 1) {
      return string;
    }

    final int maxLineLength = terminalWidth - 1;
    final StringBuffer stringBuf = new StringBuffer();
    int index = 0;
    int startOfCurrentLine = 0;
    while (index < string.length()) {
      // Add the indentation
      for (int i = 0; i < indentationLevel; i++) {
        stringBuf.append(LINE_INDENT);
      }
      int currentLineLength = LINE_INDENT.length() * indentationLevel;

      // Find the end of a line:
      // 1. If the end of string is reached
      // 2. If the width of the terminal has been reached
      // 3. If a newline character was found in the string
      while (index < string.length() && currentLineLength < maxLineLength
          && string.charAt(index) != '\n') {
        index++;
        currentLineLength++;
      }

      // If the line was terminated with a newline character
      if (index != string.length() && string.charAt(index) == '\n') {
        stringBuf.append(string.substring(startOfCurrentLine, index));
        stringBuf.append(LINE_SEPARATOR);
        index++;
        startOfCurrentLine = index;

        // If the end of the string was reached or the last character just happened to be a space
        // character
      } else if (index == string.length() || string.charAt(index) == ' ') {
        stringBuf.append(string.substring(startOfCurrentLine, index));
        if (index != string.length()) {
          stringBuf.append(LINE_SEPARATOR);
          index++;
        }

      } else {
        final int spaceCharIndex = string.lastIndexOf(" ", index);

        // If no spaces were found then there's no logical way to split the string
        if (spaceCharIndex == -1 || spaceCharIndex < startOfCurrentLine) {
          stringBuf.append(string.substring(startOfCurrentLine, index)).append(LINE_SEPARATOR);

          // Else split the string cleanly between words
        } else {
          stringBuf.append(string.substring(startOfCurrentLine, spaceCharIndex))
              .append(LINE_SEPARATOR);
          index = spaceCharIndex + 1;
        }
      }

      startOfCurrentLine = index;
    }
    return stringBuf.toString();
  }

  /**
   * Initializes default environment variables to default values
   */
  private void initializeEnvironment() {
    env.put(ENV_SYS_USER, System.getProperty("user.name"));
    env.put(ENV_SYS_USER_HOME, System.getProperty("user.home"));
    env.put(ENV_SYS_HOST_NAME, new HostName().determineHostName());
    env.put(ENV_SYS_CLASSPATH, System.getProperty("java.class.path"));
    env.put(ENV_SYS_JAVA_VERSION, System.getProperty("java.version"));
    env.put(ENV_SYS_OS, System.getProperty("os.name"));
    env.put(ENV_SYS_OS_LINE_SEPARATOR, System.getProperty("line.separator"));
    env.put(ENV_SYS_GEODE_HOME_DIR, System.getenv("GEODE_HOME"));

    env.put(ENV_APP_NAME, Gfsh.GFSH_APP_NAME);
    readonlyAppEnv.add(ENV_APP_NAME);
    env.put(ENV_APP_LOGGING_ENABLED,
        String.valueOf(!Level.OFF.equals(this.gfshConfig.getLogLevel())));
    readonlyAppEnv.add(ENV_APP_LOGGING_ENABLED);
    env.put(ENV_APP_LOG_FILE, this.gfshConfig.getLogFilePath());
    readonlyAppEnv.add(ENV_APP_LOG_FILE);
    env.put(ENV_APP_PWD, System.getProperty("user.dir"));
    readonlyAppEnv.add(ENV_APP_PWD);
    env.put(ENV_APP_FETCH_SIZE, String.valueOf(DEFAULT_APP_FETCH_SIZE));
    env.put(ENV_APP_LAST_EXIT_STATUS, String.valueOf(DEFAULT_APP_LAST_EXIT_STATUS));
    readonlyAppEnv.add(ENV_APP_LAST_EXIT_STATUS);
    env.put(ENV_APP_COLLECTION_LIMIT, String.valueOf(DEFAULT_APP_COLLECTION_LIMIT));
    env.put(ENV_APP_QUERY_RESULTS_DISPLAY_MODE, DEFAULT_APP_QUERY_RESULTS_DISPLAY_MODE);
    env.put(ENV_APP_QUIET_EXECUTION, String.valueOf(DEFAULT_APP_QUIET_EXECUTION));
    env.put(ENV_APP_RESULT_VIEWER, String.valueOf(DEFAULT_APP_RESULT_VIEWER));
  }

  public AbstractSignalNotificationHandler getSignalHandler() {
    return signalHandler;
  }

  public String readPassword(String textToPrompt) {
    if (isHeadlessMode && isQuietMode())
      return null;

    return readWithMask(textToPrompt, '*');
  }

  public String readText(String textToPrompt) {
    if (isHeadlessMode && isQuietMode())
      return null;

    return interact(textToPrompt);

  }

  /**
   * Starts this GemFire Shell with console.
   */
  public void start() {
    runner = new LoggingThread(getShellName(), false, this);
    runner.start();
  }

  protected String getShellName() {
    return "Gfsh Launcher";
  }

  /**
   * Stops this GemFire Shell.
   */
  public void stop() {
    closeShell();
    LogWrapper.close();
    if (operationInvoker != null && operationInvoker.isConnected()) {
      operationInvoker.stop();
    }
    instance = null;
  }

  public void waitForComplete() throws InterruptedException {
    runner.join();
  }

  /*
   * If an init file is provided, as a system property or in the default location, run it as a
   * command script.
   */
  private void executeInitFileIfPresent() {

    String initFileName = this.gfshConfig.getInitFileName();
    if (initFileName != null) {
      this.gfshFileLogger.info("Using " + initFileName);
      try {
        File gfshInitFile = new File(initFileName);
        boolean continueOnError = false;
        this.executeScript(gfshInitFile, isQuietMode(), continueOnError);
      } catch (Exception exception) {
        this.gfshFileLogger.severe(initFileName, exception);
        setLastExecutionStatus(-1);
      }
    }

  }

  /**
   * See findResources in {@link AbstractShell}
   */
  protected Collection<URL> findResources(String resourceName) {
    return null;
  }

  /**
   * Returns the {@link ExecutionStrategy} implementation used by this implementation of
   * {@link AbstractShell}. {@link Gfsh} uses {@link GfshExecutionStrategy}.
   *
   * @return ExecutionStrategy used by Gfsh
   */
  @Override
  protected ExecutionStrategy getExecutionStrategy() {
    return executionStrategy;
  }

  /**
   * Returns the {@link Parser} implementation used by this implementation of
   * {@link AbstractShell}.{@link Gfsh} uses {@link GfshParser}.
   *
   * @return Parser used by Gfsh
   */
  @Override
  public Parser getParser() {
    return parser;
  }

  public LogWrapper getGfshFileLogger() {
    return gfshFileLogger;
  }

  /**
   * Executes a single command string.
   * It substitutes the variables defined within the command, if any, and then delegates to the
   * default execution.
   *
   * @param line command string to be executed
   * @return command execution result.
   */
  @Override
  public org.springframework.shell.core.CommandResult executeCommand(String line) {
    return super.executeCommand(!line.contains("$") ? line : expandProperties(line));
  }

  /**
   * Executes the given command string. We have over-ridden the behavior to extend the original
   * implementation to store the 'last command execution status'.
   *
   * @param line command string to be executed
   * @return true if execution is successful; false otherwise
   */
  @Override
  public boolean executeScriptLine(final String line) {
    boolean success = false;
    String withPropsExpanded = line;

    try {
      // expand env property if the string contains $
      if (line.contains("$")) {
        withPropsExpanded = expandProperties(line);
      }
      String logMessage = "Command String to execute .. ";
      if (!line.equals(withPropsExpanded)) {
        if (!isQuietMode()) {
          Gfsh.println("Post substitution: " + withPropsExpanded);
        }
        logMessage = "Command String after substitution : ";
        expandedPropCommandsMap.put(withPropsExpanded, line);
      }
      if (gfshFileLogger.fineEnabled()) {
        gfshFileLogger.fine(logMessage + ArgumentRedactor.redact(withPropsExpanded));
      }
      success = super.executeScriptLine(withPropsExpanded);
    } catch (Exception e) {
      setLastExecutionStatus(-1);
    } finally { // Add all commands to in-memory GfshHistory
      gfshHistory.setAutoFlush(true);
      gfshHistory.addToHistory(line);
      gfshHistory.setAutoFlush(false);

      // clear the map
      expandedPropCommandsMap.clear();
    }
    return success;
  }

  public String interact(String textToPrompt) {
    try {
      return reader.readLine(textToPrompt);
    } catch (IOException e) {
      throw new RuntimeException(e);
    }
  }

  public String readWithMask(String textToPrompt, Character mask) {
    try {
      return reader.readLine(textToPrompt, mask);
    } catch (IOException e) {
      throw new RuntimeException(e);
    }
  }

  @Override
  public void printBannerAndWelcome() {
    printAsInfo(getBanner());
    printAsInfo(getWelcomeMessage());
  }

  public String getBanner() {
    StringBuilder sb = new StringBuilder();
    sb.append("    _________________________     __").append(LINE_SEPARATOR);
    sb.append("   / _____/ ______/ ______/ /____/ /").append(LINE_SEPARATOR);
    sb.append("  / /  __/ /___  /_____  / _____  / ").append(LINE_SEPARATOR);
    sb.append(" / /__/ / ____/  _____/ / /    / /  ").append(LINE_SEPARATOR);
    sb.append("/______/_/      /______/_/    /_/   ").append(" ").append(this.getVersion())
        .append(LINE_SEPARATOR);
    return ansiHandler.decorateString(sb.toString(), ANSIStyle.BLUE);
  }

  @Override
  protected String getProductName() {
    return "gfsh";
  }

  @Override
  public String getVersion() {
    return getVersion(false);
  }

  public String getVersion(boolean full) {
    if (full) {
      return GemFireVersion.asString();
    } else {

      return GemFireVersion.getGemFireVersion();
    }
  }

  public String getGeodeSerializationVersion() {
    return Version.CURRENT.getName();
  }

  public String getWelcomeMessage() {
    return ansiHandler.decorateString("Monitor and Manage " + GemFireVersion.getProductName(),
        ANSIStyle.CYAN);
  }

  // Over-ridden to avoid default behavior which is:
  // For Iterable: go through all elements & call toString
  // For others: call toString
  @Override
  protected void handleExecutionResult(Object result) {
    try {
      if (result instanceof Result) {
        Result commandResult = (Result) result;
        boolean isError = Result.Status.ERROR.equals(commandResult.getStatus());

        if (isError) {
          setLastExecutionStatus(-2);
        } else {
          setLastExecutionStatus(0);
        }

        if (useExternalViewer(commandResult)) {
          // - Save file and pass to less so that viewer can scroll through
          // results
          CliUtil.runLessCommandAsExternalViewer(commandResult);
        } else {
          if (!isScriptRunning) {
            // Normal Command
            while (commandResult.hasNextLine()) {
              String nextLine = commandResult.nextLine();
              write(nextLine, isError);
            }
          } else if (!suppressScriptCmdOutput) {
            // Command is part of script. Show output only when quite=false
            while (commandResult.hasNextLine()) {
              write(commandResult.nextLine(), isError);
            }
          }
          commandResult.resetToFirstLine();
        }

        resultTypeTL.set(null);
      }
      if (result != null && !(result instanceof Result)) {
        printAsInfo(result.toString());
      }
    } catch (Exception e) {
      printAsWarning(e.getMessage());
      logToFile(e.getMessage(), e);
    }
  }

  private boolean useExternalViewer(Result result) {
    boolean flag =
        EXTERNAL_RESULT_VIEWER.equals(getEnvProperty(Gfsh.ENV_APP_RESULT_VIEWER)) && isUnix();
    if (result instanceof CommandResult) {
      CommandResult commandResult = (CommandResult) result;
      resultTypeTL.set(commandResult.getType().equals("info"));
      return flag && !commandResult.getType().equals("info");
    } else
      return false;
  }

  private boolean isUnix() {
    return !(OS.contains("win"));
  }

  private void write(String message, boolean isError) {
    if (isError) {
      printAsWarning(message);
    } else {
      Gfsh.println(message);
    }
  }

  @Override
  protected ConsoleReader createConsoleReader() {
    ConsoleReader consoleReader = super.createConsoleReader();
    consoleReader.setHistory(gfshHistory);
    terminal = consoleReader.getTerminal();
    return consoleReader;
  }

  @Override
  protected void logCommandToOutput(String processedLine) {
    String originalString = expandedPropCommandsMap.get(processedLine);
    if (originalString != null) {
      // In history log the original command string & expanded line as a comment
      super.logCommandToOutput(ArgumentRedactor.redact(originalString));
      super.logCommandToOutput(ArgumentRedactor.redact("// Post substitution"));
      super.logCommandToOutput(ArgumentRedactor.redact("//" + processedLine));
    } else {
      super.logCommandToOutput(ArgumentRedactor.redact(processedLine));
    }
  }

  @Override
  public String versionInfo() {
    return getVersion();
  }

  public int getTerminalHeight() {
    return terminal != null ? terminal.getHeight() : DEFAULT_HEIGHT;
  }

  public int getTerminalWidth() {
    if (terminal != null) {
      return terminal.getWidth();
    }

    Map<String, String> env = System.getenv();
    String columnsFromEnv = env.get("COLUMNS");
    if (columnsFromEnv != null) {
      return Integer.parseInt(columnsFromEnv);
    }

    return DEFAULT_WIDTH;
  }

  /**
   * @return the lastExecutionStatus
   */
  public int getLastExecutionStatus() {
    // APP_LAST_EXIT_STATUS
    return lastExecutionStatus;
  }

  /**
   * Set the last command execution status
   *
   * @param lastExecutionStatus last command execution status
   */
  public void setLastExecutionStatus(int lastExecutionStatus) {
    this.lastExecutionStatus = lastExecutionStatus;
    env.put(ENV_APP_LAST_EXIT_STATUS, String.valueOf(lastExecutionStatus));
  }

  public void printAsInfo(String message) {
    if (isHeadlessMode) {
      println(message);
    } else {
      logger.info(message);
    }
  }

  public void printAsWarning(String message) {
    if (isHeadlessMode) {
      printlnErr(message);
    } else {
      logger.warning(message);
    }
  }

  public void printAsSevere(String message) {
    if (isHeadlessMode) {
      printlnErr(message);
    } else {
      logger.severe(message);
    }
  }

  public void logInfo(String message, Throwable t) {
    // No level enabled check for logger - it prints on console in colors as per level
    if (debugON) {
      logger.log(Level.INFO, message, t);
    } else {
      logger.info(message);
    }
    if (gfshFileLogger.infoEnabled()) {
      gfshFileLogger.info(message, t);
    }
  }

  public void logWarning(String message, Throwable t) {
    // No level enabled check for logger - it prints on console in colors as per level
    if (debugON) {
      logger.log(Level.WARNING, message, t);
    } else {
      logger.warning(message);
    }
    if (gfshFileLogger.warningEnabled()) {
      gfshFileLogger.warning(message, t);
    }
  }

  public void logSevere(String message, Throwable t) {
    // No level enabled check for logger - it prints on console in colors as per level
    if (debugON) {
      logger.log(Level.SEVERE, message, t);
    } else {
      logger.severe(message);
    }
    if (gfshFileLogger.severeEnabled()) {
      gfshFileLogger.severe(message, t);
    }
  }

  public boolean logToFile(String message, Throwable t) {
    boolean loggedMessage = false;
    if (gfshFileLogger != null) {
      gfshFileLogger.info(message, t);
      loggedMessage = true;
    }
    return loggedMessage;
  }

  public ResultModel executeScript(File scriptFile, boolean quiet, boolean continueOnError) {
    ResultModel result = null;
    String initialIsQuiet = getEnvProperty(ENV_APP_QUIET_EXECUTION);
    try {
      this.isScriptRunning = true;
      if (scriptFile == null) {
        throw new IllegalArgumentException("Given script file is null.");
      } else if (!scriptFile.exists()) {
        throw new IllegalArgumentException("Given script file does not exist.");
      } else if (scriptFile.exists() && scriptFile.isDirectory()) {
        throw new IllegalArgumentException(scriptFile.getPath() + " is a directory.");
      }

      ScriptExecutionDetails scriptInfo = new ScriptExecutionDetails(scriptFile.getPath());
      if (scriptFile.exists()) {
        setEnvProperty(ENV_APP_QUIET_EXECUTION, String.valueOf(quiet));
        this.suppressScriptCmdOutput = quiet;
        BufferedReader reader = new BufferedReader(new FileReader(scriptFile));
        String lineRead = "";
        StringBuilder linesBuffer = new StringBuilder();
        String linesBufferString = "";
        int commandSrNum = 0;
        CommentSkipHelper commentSkipper = new CommentSkipHelper();

        LINEREAD_LOOP: while (exitShellRequest == null && (lineRead = reader.readLine()) != null) {
          if (linesBuffer == null) {
            linesBuffer = new StringBuilder();
          }
          String lineWithoutComments = commentSkipper.skipComments(lineRead);
          if (lineWithoutComments == null || lineWithoutComments.isEmpty()) {
            continue;
          }

          if (linesBuffer.length() != 0) {// add " " between lines
            linesBuffer.append(" ");
          }
          linesBuffer.append(lineWithoutComments);
          linesBufferString = linesBuffer.toString();
          // NOTE: Similar code is in promptLoop()
          if (!linesBufferString.endsWith(GfshParser.CONTINUATION_CHARACTER)) { // see 45893

            List<String> commandList = MultiCommandHelper.getMultipleCommands(linesBufferString);
            for (String cmdLet : commandList) {
              if (!cmdLet.isEmpty()) {
                String redactedCmdLet = ArgumentRedactor.redact(cmdLet);
                ++commandSrNum;
                Gfsh.println(commandSrNum + ". Executing - " + redactedCmdLet);
                Gfsh.println();
                boolean executeSuccess = executeScriptLine(cmdLet);
                if (!executeSuccess) {
                  setLastExecutionStatus(-1);
                }
                scriptInfo.addCommandAndStatus(cmdLet,
                    getLastExecutionStatus() == -1 || getLastExecutionStatus() == -2 ? "FAILED"
                        : "PASSED");
                if ((getLastExecutionStatus() == -1 || getLastExecutionStatus() == -2)
                    && !continueOnError) {
                  break LINEREAD_LOOP;
                }
              }
            }

            // reset buffer
            linesBuffer = null;
            linesBufferString = null;
          } else {
            linesBuffer.deleteCharAt(linesBuffer.length() - 1);
          }
        }
        reader.close();
      } else {
        throw new CommandProcessingException(scriptFile.getPath() + " doesn't exist.",
            CommandProcessingException.ARGUMENT_INVALID, scriptFile);
      }
      result = scriptInfo.getResult();
      scriptInfo.logScriptExecutionInfo(gfshFileLogger, result);
      if (quiet) {
        // Create empty result when in quiet mode
        result = ResultModel.createInfo("");
      }
    } catch (IOException e) {
      throw new CommandProcessingException("Error while reading file " + scriptFile,
          CommandProcessingException.RESOURCE_ACCESS_ERROR, e);
    } finally {
      // reset to original Quiet Execution value
      setEnvProperty(ENV_APP_QUIET_EXECUTION, initialIsQuiet);
      this.isScriptRunning = false;
    }

    return result;
  }


  public String setEnvProperty(String propertyName, String propertyValue) {
    if (propertyName == null || propertyValue == null) {
      throw new IllegalArgumentException(
          "Environment Property name and/or value can not be set to null.");
    }
    if (propertyName.startsWith("SYS") || readonlyAppEnv.contains(propertyName)) {
      throw new IllegalArgumentException("The Property " + propertyName + " can not be modified.");
    }
    return env.put(propertyName, propertyValue);
  }

  public String getEnvProperty(String propertyName) {
    return env.get(propertyName);
  }

  public String getEnvAppContextPath() {
    String path = getEnvProperty(Gfsh.ENV_APP_CONTEXT_PATH);
    if (path == null) {
      return "";
    }
    return path;
  }

  public Map<String, String> getEnv() {
    Map<String, String> map = new TreeMap<>(env);
    return map;
  }

  public boolean isQuietMode() {
    return Boolean.parseBoolean(env.get(ENV_APP_QUIET_EXECUTION));
  }

  @Override
  public void promptLoop() {
    String line = null;
    String prompt = getPromptText();
    try {
      gfshHistory.setAutoFlush(false);
      // NOTE: Similar code is in executeScript()
      while (exitShellRequest == null && (line = readLine(reader, prompt)) != null) {
        if (!line.endsWith(GfshParser.CONTINUATION_CHARACTER)) { // see 45893
          List<String> commandList = MultiCommandHelper.getMultipleCommands(line);
          for (String cmdLet : commandList) {
            String trimmedCommand = cmdLet.trim();
            if (!trimmedCommand.isEmpty()) {
              executeCommand(cmdLet);
            }
          }
          prompt = getPromptText();
        } else {
          prompt = getDefaultSecondaryPrompt();
          reader.getCursorBuffer().cursor = 0;
          reader.getCursorBuffer().write(removeBackslash(line) + LINE_SEPARATOR);
        }
      }
      if (line == null) {
        // Possibly Ctrl-D was pressed on empty prompt. ConsoleReader.readLine
        // returns null on Ctrl-D
        this.exitShellRequest = ExitShellRequest.NORMAL_EXIT;
        gfshFileLogger.info("Exiting gfsh, it seems Ctrl-D was pressed.");
      }
    } catch (IOException e) {
      logSevere(e.getMessage(), e);
    }
    println((line == null ? LINE_SEPARATOR : "") + "Exiting... ");
    setShellStatus(Status.SHUTTING_DOWN);
  }

  String getDefaultSecondaryPrompt() {
    return ansiHandler.decorateString(DEFAULT_SECONDARY_PROMPT, ANSIStyle.YELLOW);
  }

  public boolean isConnectedAndReady() {
    return operationInvoker != null && operationInvoker.isConnected() && operationInvoker.isReady();
  }

  public static boolean isCurrentInstanceConnectedAndReady() {
    return (getCurrentInstance() != null && getCurrentInstance().isConnectedAndReady());
  }

  /**
   * @return the operationInvoker
   */
  public OperationInvoker getOperationInvoker() {
    return operationInvoker;
  }

  /**
   * @param operationInvoker the operationInvoker to set
   */
  public void setOperationInvoker(final OperationInvoker operationInvoker) {
    this.operationInvoker = operationInvoker;
  }

  public GfshConfig getGfshConfig() {
    return this.gfshConfig;
  }

  @Override
  protected String getHistoryFileName() {
    return gfshConfig.getHistoryFileName();
  }

  public void clearHistory() {
    gfshHistory.clear();
    if (!gfshConfig.deleteHistoryFile()) {
      printAsWarning("Gfsh history file is not deleted");
    }
  }

  public String getLogFilePath() {
    return gfshConfig.getLogFilePath();
  }

  public boolean isLoggingEnabled() {
    return gfshConfig.isLoggingEnabled();
  }

  @Override
  protected String getPromptText() {
    String defaultPrompt = gfshConfig.getDefaultPrompt();
    String contextPath = "";
    String clusterString = "";

    if (getOperationInvoker() != null && isConnectedAndReady()) {
      int clusterId = getOperationInvoker().getClusterId();
      if (clusterId != OperationInvoker.CLUSTER_ID_WHEN_NOT_CONNECTED) {
        clusterString = "Cluster-" + clusterId + " ";
      }
    }

    defaultPrompt = MessageFormat.format(defaultPrompt, clusterString, contextPath);

    return ansiHandler.decorateString(defaultPrompt, ANSIStyle.YELLOW);
  }

  public void notifyDisconnect(String endPoints) {
    String message =
        CliStrings.format(CliStrings.GFSH__MSG__NO_LONGER_CONNECTED_TO_0, new Object[] {endPoints});
    printAsSevere(LINE_SEPARATOR + message);
    if (gfshFileLogger.severeEnabled()) {
      gfshFileLogger.severe(message);
    }
    setPromptPath(getEnvAppContextPath());
  }

  public boolean getDebug() {
    return debugON;
  }

  public void setDebug(boolean flag) {
    debugON = flag;
  }

  public boolean isHeadlessMode() {
    return isHeadlessMode;
  }

  public GfshHistory getGfshHistory() {
    return gfshHistory;
  }

  protected String expandProperties(final String input) {
    String output = input;
    Scanner s = new Scanner(output);
    String foundInLine;
    while ((foundInLine = s.findInLine("(\\$[\\{]\\w+[\\}])")) != null) {
      String envProperty = getEnvProperty(extractKey(foundInLine));
      envProperty = envProperty != null ? envProperty : "";
      output = output.replace(foundInLine, envProperty);
    }
    return output;
  }
}
