// 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.index.Schema;
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.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
  }
}
