// 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.server.account.AccountState;
import com.google.gerrit.server.group.InternalGroup;
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<InternalGroup> 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
  }
}
