/*
 * 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.test.junit.rules;

import static org.apache.geode.distributed.ConfigurationProperties.START_DEV_REST_API;
import static org.apache.geode.test.awaitility.GeodeAwaitility.await;

import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import org.apache.geode.cache.CacheFactory;
import org.apache.geode.cache.RegionFactory;
import org.apache.geode.cache.RegionShortcut;
import org.apache.geode.cache.server.CacheServer;
import org.apache.geode.distributed.internal.DistributionConfig;
import org.apache.geode.distributed.internal.InternalDistributedSystem;
import org.apache.geode.internal.AvailablePortHelper;
import org.apache.geode.internal.cache.GemFireCacheImpl;
import org.apache.geode.internal.cache.InternalCache;
import org.apache.geode.internal.cache.tier.sockets.CacheServerHelper;
import org.apache.geode.pdx.PdxSerializer;

/**
 * This is a rule to start up a server in your current VM. It's useful for your Integration Tests.
 *
 * <p>
 * This rules allows you to create/start a server using any @ConfigurationProperties, you can chain
 * the configuration of the rule like this: ServerStarterRule server = new ServerStarterRule()
 * .withProperty(key, value) .withName(name) .withProperties(properties) .withSecurityManager(class)
 * .withJmxManager() .withRestService() .withEmbeddedLocator() .withRegion(type, name) etc, etc. If
 * your rule calls withAutoStart(), the cache and server will be started before your test code.
 *
 * <p>
 * In your test code, you can use the rule to access the server's attributes, like the port
 * information, working dir, name, and the cache and cacheServer it creates.
 *
 * <p>
 * If you need a rule to start a server/locator in different VMs for Distributed tests, You should
 * use {@code ClusterStartupRule}.
 */
public class ServerStarterRule extends MemberStarterRule<ServerStarterRule> implements Server {
  private final int availableLocatorPort;
  private transient InternalCache cache;
  private transient List<CacheServer> servers = new ArrayList<>();
  private int embeddedLocatorPort = -1;
  private boolean pdxPersistent = false;
  private boolean pdxPersistentUserSet = false;
  private PdxSerializer pdxSerializer = null;
  private boolean pdxReadSerialized = false;
  private boolean pdxReadSerializedUserSet = false;
  private int maxThreads = -1;
  // By default we start one server per jvm
  private int serverCount = 1;

  public ServerStarterRule() {
    String workerID = System.getProperty("org.gradle.test.worker");
    Path wd = Paths.get(".").toAbsolutePath();
    String className = getClass().getSimpleName();
    availableLocatorPort = AvailablePortHelper.getRandomAvailableTCPPort();
  }

  private final Map<String, RegionShortcut> regions = new HashMap<>();

  @Override
  public InternalCache getCache() {
    return cache;
  }

  @Override
  public CacheServer getServer() {
    return servers.get(0);
  }

  public List<CacheServer> getServers() {
    return servers;
  }

  @Override
  public void before() {
    super.before();
    if (autoStart) {
      startServer();
      regions.forEach((regionName, regionType) -> {
        RegionFactory rf = getCache().createRegionFactory(regionType);
        rf.create(regionName);
      });
    }
  }

  @Override
  public void stopMember() {
    for (CacheServer server : servers) {
      server.stop();
    }
    // make sure this cache is the one currently open. A server cache can be recreated due to
    // importing a new set of cluster configuration.
    cache = GemFireCacheImpl.getInstance();
    if (cache != null) {
      try {
        cache.close();
      } catch (Exception ignored) {
      } finally {
        cache = null;
      }
    }
    servers.clear();
  }

  public ServerStarterRule withMaxThreads(int maxThreads) {
    this.maxThreads = maxThreads;
    return this;
  }

  public ServerStarterRule withPDXPersistent() {
    pdxPersistent = true;
    pdxPersistentUserSet = true;
    return this;
  }

  public ServerStarterRule withPDXReadSerialized() {
    pdxReadSerialized = true;
    pdxReadSerializedUserSet = true;
    return this;
  }

  public ServerStarterRule withPdxSerializer(PdxSerializer pdxSerializer) {
    this.pdxSerializer = pdxSerializer;
    return this;
  }

  /*
   * If your only needs a cache and does not need a server for clients to connect
   */
  public ServerStarterRule withNoCacheServer() {
    serverCount = 0;
    return this;
  }

  public ServerStarterRule withServerCount(int serverCount) {
    this.serverCount = serverCount;
    return this;
  }

  public ServerStarterRule withEmbeddedLocator() {
    embeddedLocatorPort = availableLocatorPort;
    properties.setProperty("start-locator", "localhost[" + embeddedLocatorPort + "]");
    return this;
  }

  public ServerStarterRule withRestService() {
    return withRestService(false);
  }

  public ServerStarterRule withRestService(boolean useDefaultPort) {
    withHttpService(useDefaultPort);
    properties.setProperty(START_DEV_REST_API, "true");
    return this;
  }

  @Override
  protected void normalizeProperties() {
    super.normalizeProperties();
    if (httpPort < 0 && "true".equalsIgnoreCase(properties.getProperty(START_DEV_REST_API))) {
      withRestService();
    }
  }

  public ServerStarterRule withRegion(RegionShortcut type, String name) {
    autoStart = true;
    regions.put(name, type);
    return this;
  }

  public void startServer(Properties properties, int locatorPort) {
    withProperties(properties).withConnectionToLocator(locatorPort).startServer();
  }

  public void startServer() {
    if (servers == null) {
      servers = new ArrayList<>();
    }
    CacheFactory cf = new CacheFactory(properties);
    if (pdxPersistentUserSet) {
      cf.setPdxPersistent(pdxPersistent);
    }
    if (pdxReadSerializedUserSet) {
      cf.setPdxReadSerialized(pdxReadSerialized);
    }
    if (pdxSerializer != null) {
      cf.setPdxSerializer(pdxSerializer);
    }
    cache = (InternalCache) cf.create();
    DistributionConfig config =
        ((InternalDistributedSystem) cache.getDistributedSystem()).getConfig();
    jmxPort = config.getJmxManagerPort();
    httpPort = config.getHttpServicePort();

    for (int i = 0; i < serverCount; i++) {
      CacheServer server = cache.addCacheServer();
      if (i == 0) {
        CacheServerHelper.setIsDefaultServer(server);
      }
      // memberPort is by default zero, which translates to "randomly select an available port,"
      // which is why it is updated after this try block
      if (serverCount == 1) {
        server.setPort(memberPort);
      } else {
        server.setPort(0);
      }
      if (maxThreads >= 0) {
        server.setMaxThreads(maxThreads);
      }
      try {
        server.start();
      } catch (IOException e) {
        throw new RuntimeException("unable to start server", e);
      }
      // if this member has multiple cache servers, the memberPort will be the last server's port
      // started.
      memberPort = server.getPort();
      servers.add(server);
    }
  }

  @Override
  public int getEmbeddedLocatorPort() {
    return embeddedLocatorPort;
  }

  @Override
  public void waitTilFullyReconnected() {
    try {
      await().until(() -> {
        InternalDistributedSystem internalDistributedSystem =
            InternalDistributedSystem.getConnectedInstance();
        return internalDistributedSystem != null
            && internalDistributedSystem.getCache() != null
            && !internalDistributedSystem.getCache().getCacheServers().isEmpty();
      });

    } catch (Exception e) {
      // provide more information when condition is not satisfied after awaitility timeout
      InternalDistributedSystem ids = InternalDistributedSystem.getConnectedInstance();
      System.out.println("ds is: " + (ids != null ? "not null" : "null"));
      System.out.println("cache is: " + (ids.getCache() != null ? "not null" : "null"));
      System.out.println("has cache server: "
          + (!ids.getCache().getCacheServers().isEmpty()));
      throw e;
    }
    InternalDistributedSystem dm = InternalDistributedSystem.getConnectedInstance();
    cache = dm.getCache();
  }
}
