/*
 * 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;

import static org.apache.geode.internal.util.ProductVersionUtil.getDistributionVersion;

import java.io.PrintStream;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import joptsimple.OptionException;
import joptsimple.OptionParser;
import joptsimple.OptionSet;
import org.apache.commons.lang3.StringUtils;
import org.springframework.shell.core.ExitShellRequest;

import org.apache.geode.internal.ExitCode;
import org.apache.geode.internal.util.ArgumentRedactor;
import org.apache.geode.internal.version.DistributionVersion;
import org.apache.geode.management.internal.cli.shell.Gfsh;
import org.apache.geode.management.internal.cli.shell.GfshConfig;
import org.apache.geode.management.internal.i18n.CliStrings;

/**
 * Launcher class for :
 * <ul>
 * <li>gfsh 7.0
 * <li>server
 * <li>locator
 * <li>Tools (Pulse, VSD, JConsole, JVisualVM)
 * <li>Running Command Line Interface (CLI) Commands from OS prompt like
 * <ol>
 * <li>
 * <ul>
 * <li>compact offline-disk-store - Compact an offline disk store. If the disk store is large,
 * additional memory may need to be allocated to the process using the --J=-Xmx??? parameter.
 * <li>describe offline-disk-store - Display information about an offline disk store.
 * <li>encrypt password - Encrypt a password for use in data source configuration.
 * <li>run - Execute a set of GFSH commands. Commands that normally prompt for additional input will
 * instead use default values.
 * <li>start jconsole - Start the JDK's JConsole tool in a separate process. JConsole will be
 * launched, but connecting to GemFire must be done manually.
 * <li>start jvisualvm - Start the JDK's Java VisualVM (jvisualvm) tool in a separate process. Java
 * VisualVM will be launched, but connecting to GemFire must be done manually.
 * <li>start locator - Start a Locator.
 * <li>start pulse - Open a new window in the default Web browser with the URL for the Pulse
 * application.
 * <li>start server - Start a GemFire Cache Server.
 * <li>start vsd - Start VSD in a separate process.
 * <li>status locator - Display the status of a Locator. Possible statuses are: started, online,
 * offline or not responding.
 * <li>status server - Display the status of a GemFire Cache Server.
 * <li>stop locator - Stop a Locator.
 * <li>stop server - Stop a GemFire Cache Server.
 * <li>validate offline-disk-store - Scan the contents of a disk store to verify that it has no
 * errors.
 * <li>version - Display product version information.
 * </ul>
 * </li>
 * <li>multiple commands specified using an option "-e"
 * </ol>
 * </ul>
 *
 * @since GemFire 7.0
 */
public class Launcher {
  private static final String EXECUTE_OPTION = "execute";
  private static final String HELP_OPTION = "help";
  private static final String HELP = CliStrings.HELP;

  private static final String MSG_INVALID_COMMAND_OR_OPTION = "Invalid command or option : {0}."
      + GfshParser.LINE_SEPARATOR + "Use 'gfsh help' to display additional information.";
  public static final String SEPARATOR = ", ";

  private final Set<String> allowedCommandLineCommands;
  private final OptionParser commandLineParser;
  private final StartupTimeLogHelper startupTimeLogHelper;

  protected Launcher() {
    startupTimeLogHelper = new StartupTimeLogHelper();
    allowedCommandLineCommands = new HashSet<>();
    allowedCommandLineCommands.add(CliStrings.RUN);
    allowedCommandLineCommands.add(CliStrings.START_PULSE);
    allowedCommandLineCommands.add(CliStrings.START_JCONSOLE);
    allowedCommandLineCommands.add(CliStrings.START_JVISUALVM);
    allowedCommandLineCommands.add(CliStrings.START_LOCATOR);
    allowedCommandLineCommands.add(CliStrings.START_MANAGER);
    allowedCommandLineCommands.add(CliStrings.START_SERVER);
    allowedCommandLineCommands.add(CliStrings.START_VSD);
    allowedCommandLineCommands.add(CliStrings.STATUS_LOCATOR);
    allowedCommandLineCommands.add(CliStrings.STATUS_SERVER);
    allowedCommandLineCommands.add(CliStrings.STOP_LOCATOR);
    allowedCommandLineCommands.add(CliStrings.STOP_SERVER);
    allowedCommandLineCommands.add(CliStrings.VERSION);
    allowedCommandLineCommands.add(CliStrings.COMPACT_OFFLINE_DISK_STORE);
    allowedCommandLineCommands.add(CliStrings.DESCRIBE_OFFLINE_DISK_STORE);
    allowedCommandLineCommands.add(CliStrings.EXPORT_OFFLINE_DISK_STORE);
    allowedCommandLineCommands.add(CliStrings.VALIDATE_DISK_STORE);
    allowedCommandLineCommands.add(CliStrings.PDX_DELETE_FIELD);
    allowedCommandLineCommands.add(CliStrings.PDX_RENAME);

    commandLineParser = new OptionParser();
    commandLineParser.accepts(EXECUTE_OPTION).withOptionalArg().ofType(String.class);
    commandLineParser.accepts(HELP_OPTION).withOptionalArg().ofType(Boolean.class);
    commandLineParser.posixlyCorrect(false);
  }

  public static void main(final String[] args) {
    // first check whether required dependencies exist in the classpath
    // should we start without tomcat/servlet jars?
    String nonExistingDependency = CliUtils.cliDependenciesExist(true);
    if (nonExistingDependency != null) {
      System.err.println("Required (" + nonExistingDependency
          + ") libraries not found in the classpath. gfsh can't start.");
      return;
    }

    Launcher launcher = new Launcher();
    int exitValue = launcher.parseCommandLine(args);
    ExitCode.fromValue(exitValue).doSystemExit();
  }

  private int parseCommandLineCommand(final String... args) {
    Gfsh gfsh = null;
    try {
      gfsh = Gfsh.getInstance(false, args, new GfshConfig());
      startupTimeLogHelper.logStartupTime();
    } catch (IllegalStateException isex) {
      System.err.println("ERROR : " + isex.getMessage());
    }

    ExitShellRequest exitRequest = ExitShellRequest.NORMAL_EXIT;

    if (gfsh != null) {
      final String commandLineCommand = combineStrings(args);

      if (commandLineCommand.startsWith(HELP)) {
        if (commandLineCommand.equals(HELP)) {
          printUsage(gfsh, System.out);
        } else {
          // help is also available for commands which are not available under
          // allowedCommandLineCommands
          gfsh.executeCommand(commandLineCommand);
        }
      } else {
        boolean commandIsAllowed = false;
        for (String allowedCommandLineCommand : allowedCommandLineCommands) {
          if (commandLineCommand.startsWith(allowedCommandLineCommand)) {
            commandIsAllowed = true;
            break;
          }
        }

        if (!commandIsAllowed) {
          System.err.println(
              CliStrings.format(MSG_INVALID_COMMAND_OR_OPTION, StringUtils.join(args, SEPARATOR)));
          exitRequest = ExitShellRequest.FATAL_EXIT;
        } else {
          if (!gfsh.executeScriptLine(commandLineCommand)) {
            if (gfsh.getLastExecutionStatus() != 0) {
              exitRequest = ExitShellRequest.FATAL_EXIT;
            }
          } else if (gfsh.getLastExecutionStatus() != 0) {
            exitRequest = ExitShellRequest.FATAL_EXIT;
          }
        }
      }
    }

    return exitRequest.getExitCode();
  }

  private int parseOptions(final String... args) {
    OptionSet parsedOptions;
    try {
      parsedOptions = commandLineParser.parse(args);
    } catch (OptionException e) {
      System.err.println(
          CliStrings.format(MSG_INVALID_COMMAND_OR_OPTION, StringUtils.join(args, SEPARATOR)));
      return ExitShellRequest.FATAL_EXIT.getExitCode();
    }
    boolean launchShell = true;
    boolean onlyPrintUsage = parsedOptions.has(HELP_OPTION);
    if (parsedOptions.has(EXECUTE_OPTION) || onlyPrintUsage) {
      launchShell = false;
    }

    Gfsh gfsh = null;
    try {
      gfsh = Gfsh.getInstance(launchShell, args, new GfshConfig());
      startupTimeLogHelper.logStartupTime();
    } catch (IllegalStateException isex) {
      System.err.println("ERROR : " + isex.getMessage());
    }

    ExitShellRequest exitRequest = ExitShellRequest.NORMAL_EXIT;

    if (gfsh != null) {
      try {
        if (launchShell) {
          gfsh.start();
          gfsh.waitForComplete();
          exitRequest = gfsh.getExitShellRequest();
        } else if (onlyPrintUsage) {
          printUsage(gfsh, System.out);
        } else {
          @SuppressWarnings("unchecked")
          List<String> commandsToExecute = (List<String>) parsedOptions.valuesOf(EXECUTE_OPTION);

          // Execute all of the commands in the list, one at a time.
          for (int i = 0; i < commandsToExecute.size()
              && exitRequest == ExitShellRequest.NORMAL_EXIT; i++) {
            String command = commandsToExecute.get(i);
            // sanitize the output string to not show the password
            System.out.println(GfshParser.LINE_SEPARATOR + "(" + (i + 1) + ") Executing - "
                + ArgumentRedactor.redact(command) + GfshParser.LINE_SEPARATOR);
            if (!gfsh.executeScriptLine(command) || gfsh.getLastExecutionStatus() != 0) {
              exitRequest = ExitShellRequest.FATAL_EXIT;
            }
          }
        }
      } catch (InterruptedException iex) {
        log(iex, gfsh);
      }
    }

    return exitRequest.getExitCode();
  }

  private int parseCommandLine(final String... args) {
    if (args.length > 0 && !args[0].startsWith(GfshParser.SHORT_OPTION_SPECIFIER)) {
      return parseCommandLineCommand(args);
    }

    return parseOptions(args);
  }

  private void log(Throwable t, Gfsh gfsh) {
    if (!(gfsh != null && gfsh.logToFile(t.getMessage(), t))) {
      t.printStackTrace();
    }
  }

  private String combineStrings(String... strings) {
    StringBuilder stringBuilder = new StringBuilder();
    for (String string : strings) {
      stringBuilder.append(string).append(" ");
    }

    return stringBuilder.toString().trim();
  }

  private void printUsage(final Gfsh gfsh, final PrintStream stream) {
    int terminalWidth = gfsh.getTerminalWidth();
    final DistributionVersion distributionVersion = getDistributionVersion();
    stream.print(distributionVersion.getName() + " v");
    stream.print(distributionVersion.getVersion());
    stream.println(" Command Line Shell" + GfshParser.LINE_SEPARATOR);
    stream.println("USAGE");
    stream.println(
        "gfsh [ <command> [option]* | <help> [command] | [--help | -h] | [-e \"<command> [option]*\"]* ]"
            + GfshParser.LINE_SEPARATOR);
    stream.println("OPTIONS");
    stream.println("-e  Execute a command");
    stream.println(Gfsh.wrapText(
        "Commands may be any that are available from the interactive gfsh prompt.  "
            + "For commands that require a Manager to complete, the first command in the list must be \"connect\".",
        1, terminalWidth));
    stream.println("EXAMPLES");
    stream.println("gfsh");
    stream.println(Gfsh.wrapText("Start GFSH in interactive mode.", 1, terminalWidth));
    stream.println("gfsh -h");
    stream.println(Gfsh.wrapText(
        "Displays 'this' help. ('gfsh --help' or 'gfsh help' is equivalent)", 1, terminalWidth));
    stream.println("gfsh help start locator");
    stream.println(
        Gfsh.wrapText("Display help for the \"start locator\" command.", 1, terminalWidth));
    stream.println("gfsh start locator --name=locator1");
    stream.println(Gfsh.wrapText("Start a Locator with the name \"locator1\".", 1, terminalWidth));
    stream.println("gfsh -e \"connect\" -e \"list members\"");
    stream.println(Gfsh.wrapText(
        "Connect to a running Locator using the default connection information and run the \"list members\" command.",
        1, terminalWidth));
    stream.println();
  }

  private static class StartupTimeLogHelper {
    private final long start = System.currentTimeMillis();
    private long done;

    public void logStartupTime() {
      done = System.currentTimeMillis();
      LogWrapper.getInstance(null)
          .info("Startup done in " + ((done - start) / 1000.0) + " seconds.");
    }

    @Override
    public String toString() {
      return StartupTimeLogHelper.class.getName() + " [start=" + start + ", done=" + done + "]";
    }
  }
}
