/*
 * 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.perftest.jvms;


import static java.util.concurrent.TimeUnit.DAYS;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PrivateKey;
import java.security.SignatureException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;

import org.apache.commons.io.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sun.security.tools.keytool.CertAndKeyGen;
import sun.security.x509.X500Name;

import org.apache.geode.perftest.infrastructure.Infrastructure;
import org.apache.geode.perftest.infrastructure.InfrastructureFactory;
import org.apache.geode.perftest.jvms.classpath.ClassPathCopier;
import org.apache.geode.perftest.jvms.rmi.Controller;
import org.apache.geode.perftest.jvms.rmi.ControllerFactory;
import org.apache.geode.perftest.runner.SharedContext;

/**
 * Factory for launching JVMs and a given infrastructure and setting up RMI
 * access to all JVMs.
 */
public class RemoteJVMFactory {
  private static final Logger logger = LoggerFactory.getLogger(RemoteJVMFactory.class);

  public static final String RMI_HOST = "RMI_HOST";
  public static final String RMI_PORT_PROPERTY = "RMI_PORT";
  public static final String CONTROLLER = "CONTROLLER";
  public static final String OUTPUT_DIR = "OUTPUT_DIR";
  public static final String ROLE = "ROLE";
  public static final String JVM_ID = "JVM_ID";
  public static final int RMI_PORT = 33333;
  private static final String CLASSPATH = System.getProperty("java.class.path");
  private static final String JAVA_HOME = System.getProperty("java.home");
  private final JVMLauncher jvmLauncher;
  private final ClassPathCopier classPathCopier;
  private final ControllerFactory controllerFactory;
  private final InfrastructureFactory infrastructureFactory;

  public RemoteJVMFactory(InfrastructureFactory infrastructureFactory,
      JVMLauncher jvmLauncher,
      ClassPathCopier classPathCopier,
      ControllerFactory controllerFactory) {
    this.infrastructureFactory = infrastructureFactory;
    this.jvmLauncher = jvmLauncher;
    this.classPathCopier = classPathCopier;
    this.controllerFactory = controllerFactory;
  }

  public RemoteJVMFactory(InfrastructureFactory infrastructureFactory) {
    this(infrastructureFactory, new JVMLauncher(), new ClassPathCopier(CLASSPATH, JAVA_HOME),
        new ControllerFactory());
  }

  /**
   * Start all requested JVMs on the infrastructure
   *
   * @param roles The JVMs to start. Keys a roles and values are the number
   *        of JVMs in that role.
   *
   * @return a {@link RemoteJVMs} object used to access the JVMs through RMI
   */
  public RemoteJVMs launch(Map<String, Integer> roles,
      Map<String, List<String>> jvmArgs) throws Exception {
    int numWorkers = roles.values().stream().mapToInt(Integer::intValue).sum();

    Infrastructure infra = infrastructureFactory.create(numWorkers);

    Set<Infrastructure.Node> nodes = infra.getNodes();

    if (nodes.size() < numWorkers) {
      throw new IllegalStateException(
          "Too few nodes for test. Need " + numWorkers + ", have " + nodes.size());
    }

    List<JVMMapping> mapping = mapRolesToNodes(roles, nodes, jvmArgs);

    Controller controller =
        controllerFactory.createController(new SharedContext(mapping), numWorkers);

    classPathCopier.copyToNodes(infra, node -> getLibDir(mapping, node));

    final List<File> files = new ArrayList<>();
    files.add(createKeystore());

    final File securityJsonFile = new File("security.json");
    FileUtils.copyURLToFile(getClass().getClassLoader().getResource("security.json"),
        securityJsonFile);
    files.add(securityJsonFile);

    if (JavaVersion.current().atLeast(JavaVersion.v17)) {
      final File javaArgsFile = new File("java.args");
      FileUtils.copyURLToFile(
          getClass().getClassLoader().getResource("open-all-jdk-packages-linux-openjdk-17"),
          javaArgsFile);
      files.add(javaArgsFile);
    }

    infra.copyToNodes(files, node -> getLibDir(mapping, node), false);

    CompletableFuture<Void> processesExited = jvmLauncher.launchProcesses(infra, RMI_PORT, mapping);

    if (!controller.waitForWorkers(5, TimeUnit.MINUTES)) {
      throw new IllegalStateException("Workers failed to start in 5 minute");
    }

    return new RemoteJVMs(infra, mapping, controller, processesExited);
  }

  private JVMMapping getJvmMapping(List<JVMMapping> mapping, Infrastructure.Node node) {
    return mapping.stream()
        .filter(entry -> entry.getNode().equals(node))
        .findFirst()
        .orElseThrow(() -> new IllegalStateException("Could not find node dir " + node));
  }

  private String getLibDir(List<JVMMapping> mapping, Infrastructure.Node node) {
    return getJvmMapping(mapping, node)
        .getLibDir();
  }

  private File createKeystore()
      throws KeyStoreException, IOException, CertificateException, NoSuchAlgorithmException,
      NoSuchProviderException, InvalidKeyException, SignatureException {

    CertAndKeyGen keyGen = new CertAndKeyGen("RSA", "SHA1WithRSA", null);
    keyGen.generate(1024);

    char[] password = "123456".toCharArray();
    PrivateKey privateKey = keyGen.getPrivateKey();

    // Generate self signed certificate
    X509Certificate[] chain = new X509Certificate[1];
    chain[0] = keyGen.getSelfCertificate(new X500Name("CN=ROOT"), DAYS.toSeconds(365));

    logger.debug("Certificate : {}", chain[0]);

    KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
    ks.load(null, null);
    ks.setKeyEntry("default", privateKey, password, chain);

    File jksFile = new File("temp-self-signed.jks");
    FileOutputStream fos = new FileOutputStream(jksFile);
    ks.store(fos, password);
    fos.close();

    return jksFile;
  }

  public InfrastructureFactory getInfrastructureFactory() {
    return infrastructureFactory;
  }

  private List<JVMMapping> mapRolesToNodes(Map<String, Integer> roles,
      Set<Infrastructure.Node> nodes,
      Map<String, List<String>> jvmArgs) {
    List<JVMMapping> mapping = new ArrayList<>();
    Iterator<Infrastructure.Node> nodeItr = nodes.iterator();

    int id = 0;
    for (Map.Entry<String, Integer> roleEntry : roles.entrySet()) {
      for (int i = 0; i < roleEntry.getValue(); i++) {
        Infrastructure.Node node = nodeItr.next();
        String role = roleEntry.getKey();
        List<String> roleArgs = jvmArgs.getOrDefault(role, Collections.emptyList());
        mapping.add(new JVMMapping(node, role, id++, roleArgs));
      }

    }
    return mapping;
  }
}
