/*
 * 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.distributed.ConfigurationProperties.USER_COMMAND_PACKAGES;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Properties;
import java.util.ServiceLoader;
import java.util.Set;

import org.springframework.shell.converters.EnumConverter;
import org.springframework.shell.converters.SimpleFileConverter;
import org.springframework.shell.core.CommandMarker;
import org.springframework.shell.core.Converter;
import org.springframework.shell.core.MethodTarget;
import org.springframework.shell.core.annotation.CliAvailabilityIndicator;
import org.springframework.shell.core.annotation.CliCommand;

import org.apache.geode.annotations.Immutable;
import org.apache.geode.distributed.ConfigurationProperties;
import org.apache.geode.internal.cache.InternalCache;
import org.apache.geode.internal.classloader.ClassPathLoader;
import org.apache.geode.management.cli.Disabled;
import org.apache.geode.management.cli.GfshCommand;
import org.apache.geode.management.internal.cli.help.Helper;
import org.apache.geode.management.internal.cli.shell.Gfsh;
import org.apache.geode.management.internal.util.ClasspathScanLoadHelper;
import org.apache.geode.util.internal.GeodeGlossary;

/**
 *
 * this only takes care of loading all available command markers and converters from the application
 *
 * @since GemFire 7.0
 */
public class CommandManager {

  private static final String USER_CMD_PACKAGES_PROPERTY =
      GeodeGlossary.GEMFIRE_PREFIX + USER_COMMAND_PACKAGES;
  private static final String USER_CMD_PACKAGES_ENV_VARIABLE = "GEMFIRE_USER_COMMAND_PACKAGES";
  private static final String SPRING_CONVERTER_PACKAGE = "org.springframework.shell.converters";

  /** Skip some of the Converters from Spring Shell for our customization */
  @Immutable
  private static final List<Class<?>> SPRING_CONVERTERS_TO_SKIP =
      Collections.unmodifiableList(Arrays.asList(
          // skip springs SimpleFileConverter to use our own FilePathConverter
          SimpleFileConverter.class,
          // skip spring's EnumConverter to use our own EnumConverter
          EnumConverter.class));

  private final Helper helper = new Helper();

  private final List<Converter<?>> converters = new ArrayList<>();
  private final List<CommandMarker> commandMarkers = new ArrayList<>();

  private final Properties cacheProperties = new Properties();
  private final LogWrapper logWrapper;
  private final InternalCache cache;

  /**
   * this constructor is used from Gfsh VM. We are getting the user-command-package from system
   * environment. used by Gfsh.
   */
  public CommandManager() {
    this(null, null);
  }

  /**
   * this is used when getting the instance in a cache server. We are getting the
   * user-command-package from distribution properties. used by OnlineCommandProcessor.
   */
  public CommandManager(final Properties newCacheProperties, InternalCache cache) {
    if (newCacheProperties != null) {
      cacheProperties.putAll(newCacheProperties);
    }
    this.cache = cache;
    logWrapper = LogWrapper.getInstance(cache);
    loadCommands();
    loadConverters();
  }

  private static void raiseExceptionIfEmpty(Set<?> foundClasses, String errorFor)
      throws IllegalStateException {
    if (foundClasses == null || foundClasses.isEmpty()) {
      throw new IllegalStateException(
          "Required " + errorFor + " classes were not loaded. Check logs for errors.");
    }
  }

  private Set<String> getUserCommandPackages() {
    final Set<String> userCommandPackages = new HashSet<>();

    List<String> userCommandSources = new ArrayList<>();
    // Find by packages specified by the system property
    if (System.getProperty(USER_CMD_PACKAGES_PROPERTY) != null) {
      userCommandSources.add(System.getProperty(USER_CMD_PACKAGES_PROPERTY));
    }

    // Find by packages specified by the environment variable
    if (System.getenv().containsKey(USER_CMD_PACKAGES_ENV_VARIABLE)) {
      userCommandSources.add(System.getenv().get(USER_CMD_PACKAGES_ENV_VARIABLE));
    }

    // Find by packages specified in the distribution config
    String cacheUserCmdPackages =
        cacheProperties.getProperty(ConfigurationProperties.USER_COMMAND_PACKAGES, "");
    if (!cacheUserCmdPackages.isEmpty()) {
      userCommandSources.add(cacheUserCmdPackages);
    }

    for (String source : userCommandSources) {
      userCommandPackages.addAll(Arrays.asList(source.split(",")));
    }

    return userCommandPackages;
  }

  private void loadUserDefinedCommands() {
    String[] userCommandPackages = getUserCommandPackages().toArray(new String[] {});

    if (userCommandPackages.length == 0) {
      return;
    }

    // Load commands found in all of the packages
    try (ClasspathScanLoadHelper scanner = new ClasspathScanLoadHelper(userCommandPackages)) {
      Set<Class<?>> foundClasses =
          scanner.scanPackagesForClassesImplementing(CommandMarker.class, userCommandPackages);
      for (Class<?> klass : foundClasses) {
        try {
          add((CommandMarker) klass.newInstance());
        } catch (Exception e) {
          logWrapper.warning("Could not load User Commands from: " + klass + " due to "
              + e.getLocalizedMessage()); // continue
        }
      }
      raiseExceptionIfEmpty(foundClasses, "User Command");
    } catch (IllegalStateException e) {
      logWrapper.warning(e.getMessage(), e);
      throw e;
    }
  }

  /**
   * Loads commands via {@link ServiceLoader} from {@link ClassPathLoader}.
   *
   * @since GemFire 8.1
   */
  private void loadGeodeCommands() {
    ServiceLoader<CommandMarker> commandMarkers =
        ServiceLoader.load(CommandMarker.class, ClassPathLoader.getLatest().asClassLoader());

    boolean loadedAtLeastOneCommand = false;
    for (CommandMarker commandMarker : commandMarkers) {
      add(commandMarker);
      loadedAtLeastOneCommand = true;
    }
    if (!loadedAtLeastOneCommand) {
      throw new IllegalStateException(
          "Required Command classes were not loaded. Check logs for errors.");
    }
  }

  private void loadConverters() {
    loadGeodeDefinedConverters();
    loadSpringDefinedConverters();
  }

  private void loadCommands() {
    loadGeodeCommands();
    loadUserDefinedCommands();
  }

  private void loadSpringDefinedConverters() {
    try (ClasspathScanLoadHelper scanner = new ClasspathScanLoadHelper(SPRING_CONVERTER_PACKAGE)) {
      // Spring shell's converters
      Set<Class<?>> foundClasses =
          scanner.scanPackagesForClassesImplementing(Converter.class, SPRING_CONVERTER_PACKAGE);
      for (Class<?> klass : foundClasses) {
        if (!SPRING_CONVERTERS_TO_SKIP.contains(klass)) {
          try {
            add((Converter<?>) klass.newInstance());
          } catch (Exception e) {
            logWrapper.warning(
                "Could not load Converter from: " + klass + " due to " + e.getLocalizedMessage()); // continue
          }
        }
      }
      raiseExceptionIfEmpty(foundClasses, "Spring Converter");
    } catch (IllegalStateException e) {
      logWrapper.warning(e.getMessage(), e);
      throw e;
    }
  }

  private void loadGeodeDefinedConverters() {
    ServiceLoader<Converter> converters =
        ServiceLoader.load(Converter.class, ClassPathLoader.getLatestAsClassLoader());

    boolean loadedAtLeastOneConverter = false;
    for (Converter<?> converter : converters) {
      add(converter);
      loadedAtLeastOneConverter = true;
    }
    if (!loadedAtLeastOneConverter) {
      throw new IllegalStateException(
          "Required Converter classes were not loaded. Check logs for errors.");
    }
  }

  public List<Converter<?>> getConverters() {
    return converters;
  }

  public List<CommandMarker> getCommandMarkers() {
    return commandMarkers;
  }

  /**
   * Method to add new Converter
   */
  private void add(Converter<?> converter) {
    if (CommandManagerAware.class.isAssignableFrom(converter.getClass())) {
      ((CommandManagerAware) converter).setCommandManager(this);
    }
    converters.add(converter);
  }

  /**
   * Method to add new Commands to the parser
   */
  void add(CommandMarker commandMarker) {
    Disabled classDisabled = commandMarker.getClass().getAnnotation(Disabled.class);
    if (classDisabled != null && (classDisabled.unlessPropertyIsSet().isEmpty()
        || System.getProperty(classDisabled.unlessPropertyIsSet()) == null)) {
      return;
    }

    // inject the cache into the commands
    if (GfshCommand.class.isAssignableFrom(commandMarker.getClass())) {
      ((GfshCommand) commandMarker).setCache(cache);
    }

    // inject the commandManager into the commands
    if (CommandManagerAware.class.isAssignableFrom(commandMarker.getClass())) {
      ((CommandManagerAware) commandMarker).setCommandManager(this);
    }
    commandMarkers.add(commandMarker);
    for (Method method : commandMarker.getClass().getMethods()) {
      CliCommand cliCommand = method.getAnnotation(CliCommand.class);
      CliAvailabilityIndicator availability = method.getAnnotation(CliAvailabilityIndicator.class);
      if (cliCommand == null && availability == null) {
        continue;
      }

      if (cliCommand != null) {
        helper.addCommand(cliCommand, method);
      }

      if (availability != null) {
        helper.addAvailabilityIndicator(availability, new MethodTarget(method, commandMarker));
      }
    }
  }

  public Helper getHelper() {
    return helper;
  }

  public String obtainHelp(String buffer) {
    int terminalWidth = -1;
    Gfsh gfsh = Gfsh.getCurrentInstance();
    if (gfsh != null) {
      terminalWidth = gfsh.getTerminalWidth();
    }
    return helper.getHelp(buffer, terminalWidth);
  }

  public String obtainHint(String topic) {
    return helper.getHint(topic);
  }
}
