/*
 * Copyright 2017 The Mifos Initiative.
 *
 * Licensed 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 io.mifos.core.test.servicestarter;

import io.mifos.anubis.test.v1.SystemSecurityEnvironment;
import io.mifos.core.api.context.AutoUserContext;
import io.mifos.core.lang.security.RsaKeyPairFactory;
import io.mifos.core.test.fixture.DataStoreTenantInitializer;
import io.mifos.core.test.fixture.TenantDataStoreTestContext;
import org.junit.rules.ExternalResource;

import java.io.File;
import java.io.IOException;
import java.net.Socket;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.util.*;

import static io.mifos.core.test.env.TestEnvironment.*;

/**
 * @author Myrle Krantz
 */
@SuppressWarnings("WeakerAccess")
public class IntegrationTestEnvironment extends ExternalResource {


  static String getJava()
  {
    final String javaHome = System.getProperty("java.home");
    return javaHome + File.separator + "bin" + File.separator + "java";
  }

  static String getArtifactoryDirectory()
  {
    final String homeDirectory = System.getProperty("user.home");
    return homeDirectory + File.separator + ".m2" + File.separator + "repository";
  }

  private int nextPort;
  private final Set<Integer> ports;
  private final RsaKeyPairFactory.KeyPairHolder keyPairHolder;
  private final SystemSecurityEnvironment systemSecurityEnvironment;
  private final DataStoreTenantInitializer[] dataStoreTenantInitializers;
  private final List<String> applicationNames;
  private TenantDataStoreTestContext tenantDataStoreTestContext;

  public IntegrationTestEnvironment(final DataStoreTenantInitializer... dataStoreTenantInitializers) {
    final Properties properties = System.getProperties();
    properties.setProperty(CASSANDRA_CLUSTER_NAME_PROPERTY, CASSANDRA_CLUSTER_NAME_DEFAULT);
    properties.setProperty(CASSANDRA_CONTACT_POINTS_PROPERTY, CASSANDRA_CONTACT_POINTS_DEFAULT);
    properties.setProperty(CASSANDRA_META_KEYSPACE_PROPERTY, CASSANDRA_META_KEYSPACE_DEFAULT);
    properties.setProperty(CASSANDRA_CONSISTENCY_LEVEL_READ_PROPERTY, CASSANDRA_CONSISTENCY_LEVEL_DEFAULT);
    properties.setProperty(CASSANDRA_CONSISTENCY_LEVEL_WRITE_PROPERTY, CASSANDRA_CONSISTENCY_LEVEL_DEFAULT);
    properties.setProperty(CASSANDRA_CONSISTENCY_LEVEL_DELETE_PROPERTY, CASSANDRA_CONSISTENCY_LEVEL_DEFAULT);
    properties.setProperty(MARIADB_DRIVER_CLASS_PROPERTY, MARIADB_DRIVER_CLASS_DEFAULT);
    properties.setProperty(MARIADB_DATABASE_NAME_PROPERTY, MARIADB_DATABASE_NAME_DEFAULT);
    properties.setProperty(MARIADB_HOST_PROPERTY, MARIADB_HOST_DEFAULT);
    properties.setProperty(MARIADB_PORT_PROPERTY, MARIADB_PORT_DEFAULT);
    properties.setProperty(MARIADB_USER_PROPERTY, MARIADB_USER_DEFAULT);
    properties.setProperty(MARIADB_PASSWORD_PROPERTY, MARIADB_PASSWORD_DEFAULT);
    properties.setProperty(HYSTRIX_ENABLED_PROPERTY, HYSTRIX_ENABLED_DEFAULT);
    properties.setProperty(RIBBON_USES_EUREKA_PROPERTY, RIBBON_USES_EUREKA_DEFAULT);
    this.keyPairHolder = RsaKeyPairFactory.createKeyPair();
    properties.setProperty(SYSTEM_PUBLIC_KEY_MODULUS_PROPERTY, this.keyPairHolder.publicKey().getModulus().toString());
    properties.setProperty(SYSTEM_PUBLIC_KEY_EXPONENT_PROPERTY, this.keyPairHolder.publicKey().getPublicExponent().toString());

    this.systemSecurityEnvironment = new SystemSecurityEnvironment(keyPairHolder.publicKey(), keyPairHolder.privateKey());
    this.dataStoreTenantInitializers = dataStoreTenantInitializers;

    nextPort = 2020;
    this.ports = new HashSet<>();
    //Prevent the following ports from being allocated to Microservices.
    this.ports.add(0);
    this.ports.add(3306); //MySQL
    this.ports.add(9142); //Cassandra
    this.ports.add(ActiveMQForTest.PORT);
    this.ports.add(EurekaForTest.PORT);

    this.applicationNames = new ArrayList<>();
  }

  @Override
  protected void before() {
    tenantDataStoreTestContext = TenantDataStoreTestContext.forRandomTenantName(dataStoreTenantInitializers);
  }

  @Override
  protected void after() {
    tenantDataStoreTestContext.close();
  }

  Integer getFreshPort() {
    while (ports.contains(nextPort) || !available(nextPort))
    {
      nextPort += 1;
    }

    ports.add(nextPort);
    return nextPort;
  }

  private static boolean available(int port) {
    try (final Socket ignored = new Socket("localhost", port)) {
      return false;
    } catch (final IOException ignored) {
      return true;
    }
  }

  public RSAPublicKey getSeshatPublicKey() {
    return this.keyPairHolder.publicKey();
  }

  public RSAPrivateKey getSeshatPrivateKey() {
    return this.keyPairHolder.privateKey();
  }

  public SystemSecurityEnvironment getSystemSecurityEnvironment() {
    return systemSecurityEnvironment;
  }

  void addApplication(final String applicationName) {
    applicationNames.add(applicationName);
  }

  @SuppressWarnings("unused")
  public AutoUserContext createAutoUserContext(final String userName) {
    return systemSecurityEnvironment.createAutoUserContext(userName, applicationNames);
  }
}
