/*
 * 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.session.tests;

import static org.apache.geode.test.util.ResourceUtils.getResource;
import static org.assertj.core.api.Assertions.assertThat;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Properties;
import java.util.function.IntSupplier;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.logging.log4j.Logger;
import org.codehaus.cargo.container.installer.Installer;
import org.codehaus.cargo.container.installer.ZipURLInstaller;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import org.apache.geode.logging.internal.log4j.api.LogService;
import org.apache.geode.management.internal.configuration.utils.ZipUtils;

/**
 * Base class for handling downloading and configuring J2EE containers.
 *
 * This class contains common logic for downloading and configuring J2EE containers with cargo, and
 * some common methods for applying geode session replication configuration to those containers.
 *
 * Subclasses provide installation of specific containers.
 */
public abstract class ContainerInstall {

  private final IntSupplier portSupplier;
  static final Logger logger = LogService.getLogger();
  static final String TMP_DIR = createTempDir();
  static final String GEODE_BUILD_HOME = System.getenv("GEODE_HOME");
  static final String GEODE_BUILD_HOME_LIB = GEODE_BUILD_HOME + "/lib/";
  private static final String DEFAULT_INSTALL_DIR = TMP_DIR + "/cargo_containers/";
  private static final String DEFAULT_MODULE_EXTRACTION_DIR = TMP_DIR + "/cargo_modules/";
  static final String DEFAULT_MODULE_LOCATION = GEODE_BUILD_HOME + "/tools/Modules/";

  protected IntSupplier portSupplier() {
    return portSupplier;
  }

  private final ConnectionType connType;
  private final String installPath;
  private final String modulePath;
  private final String warFilePath;

  private final String defaultLocatorAddress;
  private int defaultLocatorPort;

  /**
   * Represents the type of connection used in this installation
   *
   * Supports either PEER_TO_PEER or CLIENT_SERVER. Also containers several useful strings needed to
   * identify XML files or connection types when setting up containers.
   */
  public enum ConnectionType {
    PEER_TO_PEER("peer-to-peer", "cache-peer.xml", false, false),
    CLIENT_SERVER("client-server", "cache-client.xml", false, true),
    CACHING_CLIENT_SERVER("client-server", "cache-client.xml", true, true);

    private final String name;

    private final String cacheXMLFileName;

    private final boolean enableLocalCache;
    private final boolean isClientServer;

    ConnectionType(String name, String cacheXMLFileName, boolean enableLocalCache,
        boolean isClientServer) {
      this.name = name;
      this.cacheXMLFileName = cacheXMLFileName;
      this.enableLocalCache = enableLocalCache;
      this.isClientServer = isClientServer;
    }

    public String getName() {
      return name;
    }

    public String getCacheXMLFileName() {
      return cacheXMLFileName;
    }

    public boolean enableLocalCache() {
      return enableLocalCache;
    }

    public boolean isClientServer() {
      return isClientServer;
    }
  }

  public ContainerInstall(String name, String downloadURL, ConnectionType connectionType,
      String moduleName, IntSupplier portSupplier) throws IOException {
    this(name, downloadURL, connectionType, moduleName, DEFAULT_MODULE_LOCATION, portSupplier);
  }

  /**
   * @param name used to name install directory
   * @param connType Enum representing the connection type of this installation (either client
   *        server or peer to peer)
   * @param moduleName The module name of the installation being setup (i.e. tomcat, appserver,
   *        etc.)
   */
  public ContainerInstall(String name, String downloadURL, ConnectionType connType,
      String moduleName, String geodeModuleLocation, IntSupplier portSupplier) throws IOException {
    this.connType = connType;
    this.portSupplier = portSupplier;

    String installDir = DEFAULT_INSTALL_DIR + name;

    clearPreviousInstall(installDir);

    String resource = getResource(getClass(), "/" + downloadURL).getPath();
    URL url = Paths.get(resource).toUri().toURL();
    logger.info("Installing container from URL " + url);

    // Optional step to install the container from a URL pointing to its distribution
    Installer installer =
        new ZipURLInstaller(url, TMP_DIR + "/downloads", installDir);
    installer.install();

    // Set install home
    installPath = installer.getHome();
    // Find and extract the module path
    modulePath = findAndExtractModule(geodeModuleLocation, moduleName);
    logger.info("Extracted module " + moduleName + " to " + modulePath);
    // Find the session testing war path
    warFilePath = findSessionTestingWar();

    // Default locator
    defaultLocatorPort = 8080;
    defaultLocatorAddress = "localhost";

    logger.info("Installed container into " + getHome());
  }

  ServerContainer generateContainer(String containerDescriptors) throws IOException {
    return generateContainer(null, containerDescriptors);
  }

  /**
   * Cleans up the installation by deleting the extracted module and downloaded installation folders
   */
  private void clearPreviousInstall(String installDir) throws IOException {
    File installFolder = new File(installDir);
    // Remove installs from previous runs in the same folder
    if (installFolder.exists()) {
      logger.info("Deleting previous install folder " + installFolder.getAbsolutePath());
      FileUtils.deleteDirectory(installFolder);
    }
  }

  void setDefaultLocatorPort(int port) {
    defaultLocatorPort = port;
  }

  /**
   * Whether the installation is client server
   *
   * Since an installation can only be client server or peer to peer there is no need for a function
   * which checks for a peer to peer installation (just check if not client server).
   */
  boolean isClientServer() {
    return connType.isClientServer();
  }

  /**
   * Where the installation is located
   */
  public String getHome() {
    return installPath;
  }

  /**
   * Where the module is located
   *
   * The module contains jars needed for geode session setup as well as default templates for some
   * needed XML files.
   */
  String getModulePath() {
    return modulePath;
  }

  /**
   * The path to the session testing WAR file
   */
  String getWarFilePath() {
    return warFilePath;
  }

  /**
   * @return The enum {@link #connType} which represents the type of connection for this
   *         installation
   */
  ConnectionType getConnectionType() {
    return connType;
  }

  /**
   * Gets the {@link #defaultLocatorAddress}
   *
   * This is the address that a container uses by default. Containers themselves can have their own
   * personal locator address, but will default to this address unless specifically set.
   */
  String getDefaultLocatorAddress() {
    return defaultLocatorAddress;
  }

  /**
   * Gets the {@link #defaultLocatorPort}
   *
   * This is the port that a container uses by default. Containers themselves can have their own
   * personal locator port, but will default to this port unless specifically set.
   */
  int getDefaultLocatorPort() {
    return defaultLocatorPort;
  }

  /**
   * Gets the cache XML file to use by default for this installation
   */
  File getCacheXMLFile() {
    return new File(modulePath + "/conf/" + getConnectionType().getCacheXMLFileName());
  }

  /**
   * Cargo specific string to identify the container with
   */
  public abstract String getInstallId();

  /**
   * A human readable description of the installation
   */
  public abstract String getInstallDescription();

  /**
   * Get the session manager class to use
   */
  public abstract String getContextSessionManagerClass();

  /**
   * Generates a {@link ServerContainer} from the given {@link ContainerInstall}
   *
   * @param containerDescriptors Additional descriptors used to identify a container
   */
  public abstract ServerContainer generateContainer(File containerConfigHome,
      String containerDescriptors) throws IOException;

  /**
   * Get the path to the session testing war by walking up directories to the correct folder.
   *
   * NOTE::This walks into the extensions folder and then uses a hardcoded path from there making it
   * very unreliable if things are moved.
   */
  private static String findSessionTestingWar() {
    // Start out searching directory above current
    String curPath = "../";

    // Looking for extensions folder
    final String warModuleDirName = "extensions";
    File warModuleDir = null;

    // While directory searching for is not found
    while (warModuleDir == null) {
      // Try to find the find the directory in the current directory
      File[] files = new File(curPath).listFiles();
      for (File file : files) {
        if (file.isDirectory() && file.getName().equals(warModuleDirName)) {
          warModuleDir = file;
          break;
        }
      }

      // Keep moving up until you find it
      curPath += "../";
    }

    // Return path to extensions plus hardcoded path from there to the WAR
    return warModuleDir.getAbsolutePath()
        + "/session-testing-war/build/libs/session-testing-war.war";
  }

  /**
   * Finds and extracts the geode module associated with the specified module.
   *
   * @param moduleName The module name (i.e. tomcat, appserver, etc.) of the module that should be
   *        extract. Used as a search parameter to find the module archive.
   * @return The path to the non-archive (extracted) version of the module files
   */
  private static String findAndExtractModule(String geodeModuleLocation, String moduleName)
      throws IOException {
    File modulesDir = new File(geodeModuleLocation);

    logger.info("Trying to access build dir " + modulesDir);

    // Search directory for tomcat module folder/zip
    boolean archive = false;
    File modulePath = null;
    for (File file : modulesDir.listFiles()) {

      if (file.getName().toLowerCase().contains(moduleName)) {
        modulePath = file;

        archive = !file.isDirectory();
        if (!archive) {
          break;
        }
      }
    }

    assertThat(modulePath).describedAs("module path").isNotNull();

    String extractedModulePath =
        modulePath.getName().substring(0, modulePath.getName().length() - 4);
    // Get the name of the new module folder within the extraction directory
    File newModuleFolder = new File(DEFAULT_MODULE_EXTRACTION_DIR + extractedModulePath);
    // Remove any previous module folders extracted here
    if (newModuleFolder.exists()) {
      logger.info("Deleting previous modules directory " + newModuleFolder.getAbsolutePath());
      FileUtils.deleteDirectory(newModuleFolder);
    }

    // Unzip if it is a zip file
    if (archive) {
      if (!FilenameUtils.getExtension(modulePath.getAbsolutePath()).equals("zip")) {
        throw new IOException("Bad module archive " + modulePath);
      }

      // Extract folder to location if not already there
      if (!newModuleFolder.exists()) {
        ZipUtils.unzip(modulePath.getAbsolutePath(), newModuleFolder.getAbsolutePath());
      }

      modulePath = newModuleFolder;
    }

    // No module found within directory throw IOException
    if (modulePath == null) {
      throw new IOException("No module found in " + modulesDir);
    }
    return modulePath.getAbsolutePath();
  }

  /**
   * Edits the specified property within the given property file
   *
   * @param filePath path to the property file
   * @param propertyName property name to edit
   * @param propertyValue new property value
   * @param append whether or not to append the given property value. If true appends the given
   *        property value the current value. If false, replaces the current property value with the
   *        given property value
   */
  static void editPropertyFile(String filePath, String propertyName, String propertyValue,
      boolean append) throws Exception {
    FileInputStream input = new FileInputStream(filePath);
    Properties properties = new Properties();
    properties.load(input);

    String val;
    if (append) {
      val = properties.getProperty(propertyName) + propertyValue;
    } else {
      val = propertyValue;
    }

    properties.setProperty(propertyName, val);
    properties.store(new FileOutputStream(filePath), null);

    logger.info("Modified container Property file " + filePath);
  }

  static void editXMLFile(String XMLPath, String tagId, String tagName,
      String parentTagName, HashMap<String, String> attributes) {
    editXMLFile(XMLPath, tagId, tagName, tagName, parentTagName, attributes, false);
  }

  static void editXMLFile(String XMLPath, String tagName, String parentTagName,
      HashMap<String, String> attributes, boolean writeOnSimilarAttributeNames) {
    editXMLFile(XMLPath, null, tagName, tagName, parentTagName, attributes,
        writeOnSimilarAttributeNames);
  }

  /**
   * Edit the given xml file
   *
   * Uses {@link #findNodeWithAttribute(Document, String, String, String)},
   * {@link #rewriteNodeAttributes(Node, HashMap)},
   * {@link #nodeHasExactAttributes(Node, HashMap, boolean)} to edit the required parts of the XML
   * file.
   *
   * @param XMLPath The path to the xml file to edit
   * @param tagId The id of tag to edit. If null, then this method will add a new xml element,
   *        unless writeOnSimilarAttributeNames is set to true.
   * @param tagName The name of the xml element to edit
   * @param replacementTagName The new name of the XML attribute that is being edited
   * @param parentTagName The parent element of the element we should edit
   * @param attributes the xml attributes for the element to edit
   * @param writeOnSimilarAttributeNames If true, find an existing element with the same set of
   *        attributes as the attributes parameter, and modifies the attributes of that element,
   *        rather than adding a new element. If false, create a new XML element (unless tagId is
   *        not null).
   */
  private static void editXMLFile(String XMLPath, String tagId, String tagName,
      String replacementTagName, String parentTagName, HashMap<String, String> attributes,
      boolean writeOnSimilarAttributeNames) {

    try {
      // Get XML file to edit
      DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
      DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
      Document doc = docBuilder.parse(XMLPath);

      Node node = null;
      // Get node with specified tagId
      if (tagId != null) {
        node = findNodeWithAttribute(doc, tagName, "id", tagId);
      }
      // If writing on similar attributes then search by tag name
      else if (writeOnSimilarAttributeNames) {
        // Get all the nodes with the given tag name
        NodeList nodes = doc.getElementsByTagName(tagName);
        for (int i = 0; i < nodes.getLength(); i++) {
          Node n = nodes.item(i);
          // If the node being iterated across has the exact attributes then it is the one that
          // should be edited
          if (nodeHasExactAttributes(n, attributes, false)) {
            node = n;
            break;
          }
        }
      }
      // If a node if found
      if (node != null) {
        doc.renameNode(node, null, replacementTagName);
        // Rewrite the node attributes
        rewriteNodeAttributes(node, attributes);
        // Write the tagId so that it can be found easier next time
        if (tagId != null)
          ((Element) node).setAttribute("id", tagId);
      }
      // No node found creates new element under the parent tag passed in
      else {
        Element e = doc.createElement(replacementTagName);
        // Set id attribute
        if (tagId != null) {
          e.setAttribute("id", tagId);
        }
        // Set other attributes
        for (String key : attributes.keySet()) {
          e.setAttribute(key, attributes.get(key));
        }

        // Add it as a child of the tag for the file
        doc.getElementsByTagName(parentTagName).item(0).appendChild(e);
      }

      // Write updated XML file
      TransformerFactory transformerFactory = TransformerFactory.newInstance();
      Transformer transformer = transformerFactory.newTransformer();
      DOMSource source = new DOMSource(doc);
      StreamResult result = new StreamResult(new File(XMLPath));
      transformer.transform(source, result);

      logger.info("Modified container XML file " + XMLPath);
    } catch (Exception e) {
      throw new RuntimeException("Unable to edit XML file", e);
    }
  }

  /**
   * Finds the node in the given document with the given name and attribute
   *
   * @param doc XML document to search for the node
   * @param nodeName The name of the node to search for
   * @param name The name of the attribute that the node should contain
   * @param value The value of the node's given attribute
   * @return Node with the given name, attribute, and attribute value
   */
  private static Node findNodeWithAttribute(Document doc, String nodeName, String name,
      String value) {
    // Get all nodes with given name
    NodeList nodes = doc.getElementsByTagName(nodeName);
    if (nodes == null) {
      return null;
    }

    // Find and return the first node that has the given attribute
    for (int i = 0; i < nodes.getLength(); i++) {
      Node node = nodes.item(i);
      Node nodeAttr = node.getAttributes().getNamedItem(name);

      if (nodeAttr != null && nodeAttr.getTextContent().equals(value)) {
        return node;
      }
    }

    return null;
  }

  /**
   * Replaces the node's attributes with the attributes in the given hashmap
   *
   * @param node XML node that should be edited
   * @param attributes HashMap of strings representing the attributes of a node (key = value)
   * @return The given node with ONLY the given attributes
   */
  private static Node rewriteNodeAttributes(Node node, HashMap<String, String> attributes) {
    NamedNodeMap nodeAttrs = node.getAttributes();

    // Remove all previous attributes
    while (nodeAttrs.getLength() > 0) {
      nodeAttrs.removeNamedItem(nodeAttrs.item(0).getNodeName());
    }

    // Set to new attributes
    for (String key : attributes.keySet()) {
      ((Element) node).setAttribute(key, attributes.get(key));
    }

    return node;
  }

  /**
   * Checks to see whether the given XML node has the exact attributes given in the attributes
   * hashmap
   *
   * @param checkSimilarValues If true, will also check to make sure that the given node's
   *        attributes also have the exact same values as the ones given in the attributes HashMap.
   * @return True if the node has only the attributes the are given by the HashMap (no more and no
   *         less attributes). If {@param checkSimilarValues} is true then only returns true if the
   *         node shares attributes with the given attribute list exactly.
   */
  private static boolean nodeHasExactAttributes(Node node, HashMap<String, String> attributes,
      boolean checkSimilarValues) {
    NamedNodeMap nodeAttrs = node.getAttributes();

    // Check to make sure the node has all attribute fields
    for (String key : attributes.keySet()) {
      Node attr = nodeAttrs.getNamedItem(key);
      if (attr == null
          || checkSimilarValues && !attr.getTextContent().equals(attributes.get(key))) {
        return false;
      }
    }

    // Check to make sure the node does not have more than the attribute fields
    for (int i = 0; i < nodeAttrs.getLength(); i++) {
      String attr = nodeAttrs.item(i).getNodeName();
      if (attributes.get(attr) == null || checkSimilarValues
          && !attributes.get(attr).equals(nodeAttrs.item(i).getTextContent())) {
        return false;
      }
    }

    return true;
  }

  private static String createTempDir() {
    try {
      return Files.createTempDirectory("geode_container_install")
          .toAbsolutePath()
          .toString();
    } catch (IOException e) {
      throw new RuntimeException(e);
    }
  }
}
