/*
 * 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.admin.internal;

import static org.apache.geode.distributed.ConfigurationProperties.CLUSTER_SSL_CIPHERS;
import static org.apache.geode.distributed.ConfigurationProperties.CLUSTER_SSL_ENABLED;
import static org.apache.geode.distributed.ConfigurationProperties.CLUSTER_SSL_PROTOCOLS;
import static org.apache.geode.distributed.ConfigurationProperties.CLUSTER_SSL_REQUIRE_AUTHENTICATION;
import static org.apache.geode.distributed.ConfigurationProperties.MCAST_PORT;
import static org.apache.geode.internal.net.InetAddressUtils.isLocalHost;

import java.io.File;
import java.util.Iterator;
import java.util.Properties;

import org.apache.logging.log4j.Logger;

import org.apache.geode.admin.AdminDistributedSystem;
import org.apache.geode.admin.DistributedSystemConfig;
import org.apache.geode.admin.ManagedEntity;
import org.apache.geode.admin.ManagedEntityConfig;
import org.apache.geode.distributed.internal.DistributionConfig;
import org.apache.geode.internal.ProcessOutputReader;
import org.apache.geode.logging.internal.executors.LoggingThread;
import org.apache.geode.logging.internal.log4j.api.LogService;

/**
 * Implements the actual administration (starting, stopping, etc.) of GemFire
 * {@link ManagedEntity}s. It {@link Runtime#exec(java.lang.String) executes} commands to administer
 * the entities based on information provided by the {@link InternalManagedEntity} object. Note that
 * it does not use <code>SystemAdmin</code> to manage "local" entities; it always execs the scripts.
 *
 * <P>
 *
 * This class is a refactoring of <code>Systemcontroller</code>, <code>RemoteCommand</code>, and
 * <code>LocatorRemoteCommand</code>.
 *
 * @since GemFire 4.0
 */
class EnabledManagedEntityController implements ManagedEntityController {
  private static final Logger logger = LogService.getLogger();

  /** Known strings found in output indicating error. */
  private static final String[] ERROR_OUTPUTS = new String[] {"No such file or directory",
      "The system cannot find the file specified.", "Access is denied.", "cannot open", "ERROR"};

  /** Token in command prefix to be replaced with actual HOST */
  private static final String HOST = "{HOST}";

  /** Token in command prefix to be replaced with actual execution CMD */
  private static final String CMD = "{CMD}";

  ////////////////////// Instance Fields //////////////////////

  /** System to which the managed entities belong */
  private final AdminDistributedSystem system;

  /////////////////////// Constructors ///////////////////////

  /**
   * Creates a new <code>ManagedEntityController</code> for entities in the given distributed
   * system.
   */
  EnabledManagedEntityController(AdminDistributedSystem system) {
    this.system = system;
  }

  ///////////////////// Instance Methods /////////////////////

  /**
   * Returns <code>true</code> if the <code>output</code> string contains a known error message.
   */
  private boolean outputIsError(String output) {
    if (output == null)
      return false;
    boolean error = false;
    for (int i = 0; i < ERROR_OUTPUTS.length; i++) {
      error = output.indexOf(ERROR_OUTPUTS[i]) > -1;
      if (error)
        return error;
    }
    return error;
  }

  /**
   * Executes a command using {@link Runtime#exec(java.lang.String)}.
   *
   * @param command The full command to remotely execute
   *
   * @return Output from the command that was executed or <code>null</code> if the executing the
   *         command failed.
   */
  protected String execute(String command, InternalManagedEntity entity) {
    /*
     * TODO: this is getting ugly... clients of this method really need to have the ability to do
     * their own parsing/checking of 'output'
     */
    if (command == null || command.length() == 0) {
      throw new IllegalArgumentException(
          "Execution command is empty");
    }

    File workingDir = new File(entity.getEntityConfig().getWorkingDirectory());
    logger.info("Executing remote command: {} in directory {}",
        command, workingDir);
    Process p = null;
    try {
      p = Runtime.getRuntime().exec(command, null /* env */, workingDir);

    } catch (java.io.IOException e) {
      logger.fatal("While executing " + command, e);
      return null;
    }

    final ProcessOutputReader pos = new ProcessOutputReader(p);
    int retCode = pos.getExitCode();
    final String output = pos.getOutput();
    logger.info("Result of executing {} is {}", command, Integer.valueOf(retCode));
    logger.info("Output of {} is {}", command, output);

    if (retCode != 0 || outputIsError(output)) {
      logger.warn("Remote execution of {} failed.", command);
      return null;
    }

    return output;
  }

  /** Returns true if the path ends with a path separator. */
  private boolean endsWithSeparator(String path) {
    return path.endsWith("/") || path.endsWith("\\");
  }

  /** Translates the path between Windows and UNIX. */
  private String getOSPath(String path) {
    if (pathIsWindows(path)) {
      return path.replace('/', '\\');
    } else {
      return path.replace('\\', '/');
    }
  }

  /** Returns true if the path is on Windows. */
  private boolean pathIsWindows(String path) {
    if (path != null && path.length() > 1) {
      return (Character.isLetter(path.charAt(0)) && path.charAt(1) == ':')
          || (path.startsWith("//") || path.startsWith("\\\\"));
    }
    return false;
  }

  /**
   * If the managed entity resides on a remote host, then <code>command</code> is munged to take the
   * remote command into account.
   *
   * @throws IllegalStateException If a remote command is required, but one has not been specified.
   */
  private String arrangeRemoteCommand(InternalManagedEntity entity, String cmd) {

    String host = entity.getEntityConfig().getHost();
    if (isLocalHost(host)) {
      // No arranging necessary
      return cmd;
    }

    String prefix = entity.getEntityConfig().getRemoteCommand();
    if (prefix == null || prefix.length() <= 0) {
      prefix = entity.getDistributedSystem().getRemoteCommand();
    }

    if (prefix == null || prefix.length() <= 0) {
      throw new IllegalStateException(
          String.format(
              "A remote command must be specified to operate on a managed entity on host %s",
              host));
    }

    int hostIdx = prefix.indexOf(HOST);
    int cmdIdx = prefix.indexOf(CMD);
    if (hostIdx == -1 && cmdIdx == -1) {
      return prefix + " " + host + " " + cmd;
    }

    if (hostIdx >= 0) {
      String start = prefix.substring(0, hostIdx);
      String end = null;
      if (hostIdx + HOST.length() >= prefix.length()) {
        end = "";
      } else {
        end = prefix.substring(hostIdx + HOST.length());
      }
      prefix = start + host + end;
      cmdIdx = prefix.indexOf(CMD); // recalculate
    }

    if (cmdIdx >= 0) {
      String start = prefix.substring(0, cmdIdx);
      String end = null;
      if (cmdIdx + CMD.length() >= prefix.length()) {
        end = "";
      } else {
        end = prefix.substring(cmdIdx + CMD.length());
      }
      prefix = start + cmd + end;
    }
    return prefix;
  }

  /**
   * Returns the full path to the executable in <code>$GEMFIRE/bin</code> taking into account the
   * {@linkplain ManagedEntityConfig#getProductDirectory product directory} and the platform's file
   * separator.
   *
   * <P>
   *
   * Note: we should probably do a better job of determine whether or not the machine on which the
   * entity runs is Windows or Linux.
   *
   * @param executable The name of the executable that resides in <code>$GEMFIRE/bin</code>.
   */
  @Override
  public String getProductExecutable(InternalManagedEntity entity, String executable) {
    String productDirectory = entity.getEntityConfig().getProductDirectory();
    String path = null;
    File productDir = new File(productDirectory);
    {
      path = productDir.getPath();
      if (!endsWithSeparator(path)) {
        path += File.separator;
      }
      path += "bin" + File.separator;
    }

    String bat = "";
    if (pathIsWindows(path)) {
      bat = ".bat";
    }
    return getOSPath(path) + executable + bat;
  }

  /**
   * Builds optional SSL command-line arguments. Returns null if SSL is not enabled for the
   * distributed system.
   */
  @Override
  public String buildSSLArguments(DistributedSystemConfig config) {
    Properties sslProps = buildSSLProperties(config, true);
    if (sslProps == null)
      return null;

    StringBuffer sb = new StringBuffer();
    for (Iterator iter = sslProps.keySet().iterator(); iter.hasNext();) {
      String key = (String) iter.next();
      String value = sslProps.getProperty(key);
      sb.append(" -J-D" + key + "=" + value);
    }

    return sb.toString();
  }

  /**
   * Builds optional SSL properties for DistributionLocator. Returns null if SSL is not enabled for
   * the distributed system.
   *
   * @param forCommandLine true indicates that {@link DistributionConfig#GEMFIRE_PREFIX} should be
   *        prepended so the argument will become -Dgemfire.xxxx
   */
  private Properties buildSSLProperties(DistributedSystemConfig config, boolean forCommandLine) {
    if (!config.isSSLEnabled())
      return null;

    String prefix = "";
    if (forCommandLine)
      prefix = DistributionConfig.GEMFIRE_PREFIX;

    Properties sslProps = (Properties) config.getSSLProperties().clone();
    // add ssl-enabled, etc...
    sslProps.setProperty(prefix + MCAST_PORT, "0");
    sslProps.setProperty(prefix + CLUSTER_SSL_ENABLED, String.valueOf(config.isSSLEnabled()));
    sslProps.setProperty(prefix + CLUSTER_SSL_CIPHERS, config.getSSLCiphers());
    sslProps.setProperty(prefix + CLUSTER_SSL_PROTOCOLS, config.getSSLProtocols());
    sslProps.setProperty(prefix + CLUSTER_SSL_REQUIRE_AUTHENTICATION,
        String.valueOf(config.isSSLAuthenticationRequired()));
    return sslProps;
  }


  /**
   * Starts a managed entity.
   */
  @Override
  public void start(final InternalManagedEntity entity) {
    final String command = arrangeRemoteCommand(entity, entity.getStartCommand());
    Thread start = new LoggingThread("Start " + entity.getEntityType(),
        false, () -> execute(command, entity));
    start.start();
  }

  /**
   * Stops a managed entity.
   */
  @Override
  public void stop(final InternalManagedEntity entity) {
    final String command = arrangeRemoteCommand(entity, entity.getStopCommand());
    Thread stop = new LoggingThread("Stop " + entity.getEntityType(),
        false, () -> execute(command, entity));
    stop.start();
  }

  /**
   * Returns whether or not a managed entity is running
   */
  @Override
  public boolean isRunning(InternalManagedEntity entity) {
    final String command = arrangeRemoteCommand(entity, entity.getIsRunningCommand());
    String output = execute(command, entity);

    if (output == null || (output.indexOf("stop" /* "ing" "ped" */) != -1)
        || (output.indexOf("killed") != -1) || (output.indexOf("starting") != -1)) {
      return false;

    } else if (output.indexOf("running") != -1) {
      return true;

    } else {
      throw new IllegalStateException(
          String.format("Could not determine if managed entity was running: %s",
              output));
    }
  }

  /**
   * Returns the contents of a locator's log file. Other APIs are used to get the log file of
   * managed entities that are also system members.
   */
  @Override
  public String getLog(DistributionLocatorImpl locator) {
    String command = arrangeRemoteCommand(locator, locator.getLogCommand());
    return execute(command, locator);
  }

  /**
   * Returns the contents of the given directory using the given managed entity to determine the
   * host and remote command.
   */
  private String listDirectory(InternalManagedEntity entity, String dir) {
    ManagedEntityConfig config = entity.getEntityConfig();
    String listFile = pathIsWindows(config.getProductDirectory()) ? "dir " : "ls ";
    String command = arrangeRemoteCommand(entity, listFile + dir);
    return execute(command, entity);
  }
}
