// Copyright (C) 2016 The Android Open Source Project
//
// 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 com.google.gerrit.elasticsearch;

import static com.google.common.truth.Truth.assertThat;
import static com.google.gerrit.elasticsearch.ElasticAccountIndex.ACCOUNTS_PREFIX;
import static com.google.gerrit.elasticsearch.ElasticChangeIndex.CHANGES_PREFIX;
import static com.google.gerrit.elasticsearch.ElasticChangeIndex.CLOSED_CHANGES;
import static com.google.gerrit.elasticsearch.ElasticChangeIndex.OPEN_CHANGES;
import static com.google.gerrit.elasticsearch.ElasticGroupIndex.GROUPS_PREFIX;

import com.google.common.base.Strings;
import com.google.common.io.Files;
import com.google.gerrit.elasticsearch.ElasticAccountIndex.AccountMapping;
import com.google.gerrit.elasticsearch.ElasticChangeIndex.ChangeMapping;
import com.google.gerrit.elasticsearch.ElasticGroupIndex.GroupMapping;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.server.account.AccountState;
import com.google.gerrit.server.index.IndexModule.IndexType;
import com.google.gerrit.server.index.Schema;
import com.google.gerrit.server.index.account.AccountSchemaDefinitions;
import com.google.gerrit.server.index.change.ChangeSchemaDefinitions;
import com.google.gerrit.server.index.group.GroupSchemaDefinitions;
import com.google.gerrit.server.query.change.ChangeData;
import com.google.gson.FieldNamingPolicy;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import java.io.File;
import java.nio.file.Path;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import org.eclipse.jgit.lib.Config;
import org.elasticsearch.action.admin.cluster.node.info.NodesInfoRequest;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.node.Node;
import org.elasticsearch.node.NodeBuilder;

final class ElasticTestUtils {
  static final Gson gson =
      new GsonBuilder()
          .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
          .create();

  static class ElasticNodeInfo {
    final Node node;
    final String port;
    final File elasticDir;

    private ElasticNodeInfo(Node node, File rootDir, String port) {
      this.node = node;
      this.port = port;
      this.elasticDir = rootDir;
    }
  }

  static void configure(Config config, String port) {
    config.setEnum("index", null, "type", IndexType.ELASTICSEARCH);
    config.setString("elasticsearch", "test", "protocol", "http");
    config.setString("elasticsearch", "test", "hostname", "localhost");
    config.setString("elasticsearch", "test", "port", port);
  }

  static ElasticNodeInfo startElasticsearchNode() throws InterruptedException, ExecutionException {
    File elasticDir = Files.createTempDir();
    Path elasticDirPath = elasticDir.toPath();
    Settings settings =
        Settings.settingsBuilder()
            .put("cluster.name", "gerrit")
            .put("node.name", "Gerrit Elasticsearch Test Node")
            .put("node.local", true)
            .put("discovery.zen.ping.multicast.enabled", false)
            .put("index.store.fs.memory.enabled", true)
            .put("index.gateway.type", "none")
            .put("index.max_result_window", Integer.MAX_VALUE)
            .put("gateway.type", "default")
            .put("http.port", 0)
            .put("discovery.zen.ping.unicast.hosts", "[\"localhost\"]")
            .put("path.home", elasticDirPath.toAbsolutePath())
            .put("path.data", elasticDirPath.resolve("data").toAbsolutePath())
            .put("path.work", elasticDirPath.resolve("work").toAbsolutePath())
            .put("path.logs", elasticDirPath.resolve("logs").toAbsolutePath())
            .put("transport.tcp.connect_timeout", "60s")
            .build();

    // Start the node
    Node node = NodeBuilder.nodeBuilder().settings(settings).node();

    // Wait for it to be ready
    node.client().admin().cluster().prepareHealth().setWaitForYellowStatus().execute().actionGet();

    assertThat(node.isClosed()).isFalse();
    return new ElasticNodeInfo(node, elasticDir, getHttpPort(node));
  }

  static void deleteAllIndexes(ElasticNodeInfo nodeInfo) {
    nodeInfo.node.client().admin().indices().prepareDelete("_all").execute();
  }

  static class NodeInfo {
    String httpAddress;
  }

  static class Info {
    Map<String, NodeInfo> nodes;
  }

  static void createAllIndexes(ElasticNodeInfo nodeInfo) {
    Schema<ChangeData> changeSchema = ChangeSchemaDefinitions.INSTANCE.getLatest();
    ChangeMapping openChangesMapping = new ChangeMapping(changeSchema);
    ChangeMapping closedChangesMapping = new ChangeMapping(changeSchema);
    openChangesMapping.closedChanges = null;
    closedChangesMapping.openChanges = null;
    nodeInfo
        .node
        .client()
        .admin()
        .indices()
        .prepareCreate(String.format("%s%04d", CHANGES_PREFIX, changeSchema.getVersion()))
        .addMapping(OPEN_CHANGES, gson.toJson(openChangesMapping))
        .addMapping(CLOSED_CHANGES, gson.toJson(closedChangesMapping))
        .execute()
        .actionGet();

    Schema<AccountState> accountSchema = AccountSchemaDefinitions.INSTANCE.getLatest();
    AccountMapping accountMapping = new AccountMapping(accountSchema);
    nodeInfo
        .node
        .client()
        .admin()
        .indices()
        .prepareCreate(String.format("%s%04d", ACCOUNTS_PREFIX, accountSchema.getVersion()))
        .addMapping(ElasticAccountIndex.ACCOUNTS, gson.toJson(accountMapping))
        .execute()
        .actionGet();

    Schema<AccountGroup> groupSchema = GroupSchemaDefinitions.INSTANCE.getLatest();
    GroupMapping groupMapping = new GroupMapping(groupSchema);
    nodeInfo
        .node
        .client()
        .admin()
        .indices()
        .prepareCreate(String.format("%s%04d", GROUPS_PREFIX, groupSchema.getVersion()))
        .addMapping(ElasticGroupIndex.GROUPS, gson.toJson(groupMapping))
        .execute()
        .actionGet();
  }

  private static String getHttpPort(Node node) throws InterruptedException, ExecutionException {
    String nodes =
        node.client().admin().cluster().nodesInfo(new NodesInfoRequest("*")).get().toString();
    Gson gson =
        new GsonBuilder()
            .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
            .create();
    Info info = gson.fromJson(nodes, Info.class);
    if (info.nodes == null || info.nodes.size() != 1) {
      throw new RuntimeException("Cannot extract local Elasticsearch http port");
    }
    Iterator<NodeInfo> values = info.nodes.values().iterator();
    String httpAddress = values.next().httpAddress;
    if (Strings.isNullOrEmpty(httpAddress)) {
      throw new RuntimeException("Cannot extract local Elasticsearch http port");
    }
    if (httpAddress.indexOf(':') < 0) {
      throw new RuntimeException("Seems that port is not included in Elasticsearch http_address");
    }
    return httpAddress.substring(httpAddress.indexOf(':') + 1, httpAddress.length());
  }

  private ElasticTestUtils() {
    // hide default constructor
  }
}
