// Copyright (C) 2018 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.acceptance.pgm;

import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.TruthJUnit.assume;

import com.google.common.collect.ImmutableSet;
import com.google.errorprone.annotations.MustBeClosed;
import com.google.gerrit.acceptance.NoHttpd;
import com.google.gerrit.acceptance.StandaloneSiteTest;
import com.google.gerrit.entities.Project;
import com.google.gerrit.index.IndexConfig;
import com.google.gerrit.index.QueryOptions;
import com.google.gerrit.index.project.ProjectData;
import com.google.gerrit.index.project.ProjectIndexCollection;
import com.google.gerrit.server.config.AllProjectsName;
import com.google.gerrit.server.config.AllUsersName;
import java.io.IOException;
import java.nio.file.FileVisitOption;
import java.nio.file.Files;
import java.nio.file.Path;
import java.time.Instant;
import java.util.Comparator;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.eclipse.jgit.util.FS;
import org.junit.Test;

@NoHttpd
public class InitIT extends StandaloneSiteTest {

  @Test
  public void indexesAllProjectsAndAllUsers() throws Exception {
    initSite();
    try (ServerContext ctx = startServer()) {
      ProjectIndexCollection projectIndex =
          ctx.getInjector().getInstance(ProjectIndexCollection.class);
      Project.NameKey allProjects = ctx.getInjector().getInstance(AllProjectsName.class);
      Project.NameKey allUsers = ctx.getInjector().getInstance(AllUsersName.class);
      QueryOptions opts =
          QueryOptions.create(IndexConfig.createDefault(), 0, 1, ImmutableSet.of("name"));
      Optional<ProjectData> allProjectsData = projectIndex.getSearchIndex().get(allProjects, opts);
      assertThat(allProjectsData).isPresent();
      Optional<ProjectData> allUsersData = projectIndex.getSearchIndex().get(allUsers, opts);
      assertThat(allUsersData).isPresent();
    }
  }

  @Test
  public void initDoesNotReindexProjectsOnExistingSites() throws Exception {
    // These tests expect the Lucene index to modify files on disk which the fake index doesn't do.
    String configuredIndexBackend = baseConfig.getString("index", null, "type");
    configuredIndexBackend = configuredIndexBackend == null ? "fake" : configuredIndexBackend;
    assume().that(configuredIndexBackend).isEqualTo("lucene");
    initSite();

    // Simulate a projects indexes files modified in the past by 3 seconds
    Optional<Instant> projectsLastModified =
        getProjectsIndexLastModified(sitePaths.index_dir).map(t -> t.minusSeconds(3));
    assertThat(projectsLastModified).isPresent();
    setProjectsIndexLastModifiedInThePast(sitePaths.index_dir, projectsLastModified.get());

    initSite();
    Optional<Instant> projectsLastModifiedAfterInit =
        getProjectsIndexLastModified(sitePaths.index_dir);

    // Verify that projects index files haven't been updated
    assertThat(projectsLastModified).isEqualTo(projectsLastModifiedAfterInit);
  }

  private void initSite() throws Exception {
    runGerrit("init", "-d", sitePaths.site_path.toString(), "--show-stack-trace");
  }

  private void setProjectsIndexLastModifiedInThePast(Path indexDir, Instant time)
      throws IOException {
    try (Stream<Path> allprojectsIndexFiles = getAllProjectsIndexFiles(indexDir)) {
      for (Path path : allprojectsIndexFiles.collect(Collectors.toList())) {
        FS.DETECTED.setLastModified(path, time);
      }
    }
  }

  private Optional<Instant> getProjectsIndexLastModified(Path indexDir) throws IOException {
    try (Stream<Path> allprojectsIndexFiles = getAllProjectsIndexFiles(indexDir)) {
      return allprojectsIndexFiles
          .map(FS.DETECTED::lastModifiedInstant)
          .max(Comparator.comparingLong(Instant::toEpochMilli));
    }
  }

  @MustBeClosed
  private Stream<Path> getAllProjectsIndexFiles(Path indexDir) throws IOException {
    try (Stream<Path> stream = Files.walk(indexDir, 1)) {
      Optional<Path> projectsPath =
          stream
              .filter(Files::isDirectory)
              .filter(p -> p.getFileName().toString().startsWith("projects_"))
              .findFirst();
      if (!projectsPath.isPresent()) {
        return Stream.empty();
      }
      return Files.walk(projectsPath.get(), 1, FileVisitOption.FOLLOW_LINKS);
    }
  }
}
