// Copyright (C) 2019 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.plugins.checks.acceptance.testsuite;

import static com.google.common.base.Preconditions.checkState;
import static com.google.common.collect.ImmutableSet.toImmutableSet;
import static com.google.gerrit.testing.TestActionRefUpdateContext.testRefAction;
import static java.nio.charset.StandardCharsets.UTF_8;
import static java.util.stream.Collectors.toList;
import static org.eclipse.jgit.lib.Constants.OBJ_BLOB;

import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Streams;
import com.google.gerrit.entities.Project;
import com.google.gerrit.exceptions.DuplicateKeyException;
import com.google.gerrit.plugins.checks.Checker;
import com.google.gerrit.plugins.checks.CheckerCreation;
import com.google.gerrit.plugins.checks.CheckerJson;
import com.google.gerrit.plugins.checks.CheckerRef;
import com.google.gerrit.plugins.checks.CheckerUpdate;
import com.google.gerrit.plugins.checks.CheckerUuid;
import com.google.gerrit.plugins.checks.Checkers;
import com.google.gerrit.plugins.checks.CheckersUpdate;
import com.google.gerrit.plugins.checks.api.CheckerInfo;
import com.google.gerrit.plugins.checks.db.CheckerConfig;
import com.google.gerrit.plugins.checks.db.CheckersByRepositoryNotes;
import com.google.gerrit.server.ServerInitiated;
import com.google.gerrit.server.config.AllProjectsName;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
import java.io.IOException;
import java.util.Arrays;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;
import java.util.stream.Stream;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.junit.TestRepository;
import org.eclipse.jgit.lib.BlobBasedConfig;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectReader;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.RefUpdate;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.notes.NoteMap;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.treewalk.TreeWalk;

/**
 * The implementation of {@code CheckerOperations}.
 *
 * <p>There is only one implementation of {@code CheckerOperations}. Nevertheless, we keep the
 * separation between interface and implementation to enhance clarity.
 */
@Singleton
public class CheckerOperationsImpl implements CheckerOperations {
  private final Checkers checkers;
  private final Provider<CheckersUpdate> checkersUpdate;
  private final GitRepositoryManager repoManager;
  private final AllProjectsName allProjectsName;
  private final CheckerJson checkerJson;
  private final AtomicInteger checkerCounter;

  @Inject
  public CheckerOperationsImpl(
      Checkers checkers,
      @ServerInitiated Provider<CheckersUpdate> checkersUpdate,
      GitRepositoryManager repoManager,
      AllProjectsName allProjectsName,
      CheckerJson checkerJson) {
    this.checkers = checkers;
    this.checkersUpdate = checkersUpdate;
    this.repoManager = repoManager;
    this.allProjectsName = allProjectsName;
    this.checkerJson = checkerJson;
    this.checkerCounter = new AtomicInteger();
  }

  @Override
  public PerCheckerOperations checker(CheckerUuid checkerUuid) {
    return new PerCheckerOperationsImpl(checkerUuid);
  }

  @Override
  public TestCheckerCreation.Builder newChecker() {
    return TestCheckerCreation.builder(this::createNewChecker);
  }

  private CheckerUuid createNewChecker(TestCheckerCreation testCheckerCreation)
      throws DuplicateKeyException, ConfigInvalidException, IOException {
    CheckerCreation checkerCreation = toCheckerCreation(testCheckerCreation);
    CheckerUpdate checkerUpdate = toCheckerUpdate(testCheckerCreation);
    Checker checker = checkersUpdate.get().createChecker(checkerCreation, checkerUpdate);
    return checker.getUuid();
  }

  private CheckerCreation toCheckerCreation(TestCheckerCreation checkerCreation) {
    CheckerUuid checkerUuid =
        checkerCreation
            .uuid()
            .orElseGet(() -> CheckerUuid.parse("test:checker-" + checkerCounter.incrementAndGet()));
    String checkerName = checkerCreation.name().orElse("Test Checker");
    Project.NameKey repository = checkerCreation.repository().orElse(allProjectsName);
    return CheckerCreation.builder()
        .setCheckerUuid(checkerUuid)
        .setName(checkerName)
        .setRepository(repository)
        .build();
  }

  private static CheckerUpdate toCheckerUpdate(TestCheckerCreation checkerCreation) {
    CheckerUpdate.Builder builder = CheckerUpdate.builder();
    checkerCreation.name().ifPresent(builder::setName);
    checkerCreation.description().ifPresent(builder::setDescription);
    checkerCreation.url().ifPresent(builder::setUrl);
    checkerCreation.repository().ifPresent(builder::setRepository);
    checkerCreation.status().ifPresent(builder::setStatus);
    checkerCreation.blockingConditions().ifPresent(builder::setBlockingConditions);
    checkerCreation.query().ifPresent(builder::setQuery);
    return builder.build();
  }

  @Override
  public ImmutableSet<CheckerUuid> checkersOf(Project.NameKey repositoryName) throws IOException {
    try (Repository repo = repoManager.openRepository(allProjectsName);
        RevWalk rw = new RevWalk(repo);
        ObjectReader or = repo.newObjectReader()) {
      Ref ref = repo.exactRef(CheckerRef.REFS_META_CHECKERS);
      if (ref == null) {
        return ImmutableSet.of();
      }

      RevCommit c = rw.parseCommit(ref.getObjectId());
      try (TreeWalk tw =
          TreeWalk.forPath(
              or,
              CheckersByRepositoryNotes.computeRepositorySha1(repositoryName).getName(),
              c.getTree())) {
        if (tw == null) {
          return ImmutableSet.of();
        }

        return Streams.stream(
                Splitter.on('\n')
                    .split(new String(or.open(tw.getObjectId(0), OBJ_BLOB).getBytes(), UTF_8)))
            .map(CheckerUuid::parse)
            .collect(toImmutableSet());
      }
    }
  }

  @Override
  public ImmutableSet<ObjectId> sha1sOfRepositoriesWithCheckers() throws IOException {
    try (Repository repo = repoManager.openRepository(allProjectsName);
        RevWalk rw = new RevWalk(repo)) {
      Ref ref = repo.exactRef(CheckerRef.REFS_META_CHECKERS);
      if (ref == null) {
        return ImmutableSet.of();
      }

      return Streams.stream(NoteMap.read(rw.getObjectReader(), rw.parseCommit(ref.getObjectId())))
          .map(ObjectId::copy)
          .collect(toImmutableSet());
    }
  }

  private class PerCheckerOperationsImpl implements PerCheckerOperations {
    private final CheckerUuid checkerUuid;

    PerCheckerOperationsImpl(CheckerUuid checkerUuid) {
      this.checkerUuid = checkerUuid;
    }

    @Override
    public boolean exists() {
      return getChecker(checkerUuid).isPresent();
    }

    @Override
    public Checker get() {
      return getChecker(checkerUuid)
          .orElseThrow(() -> new IllegalStateException("Tried to get non-existing test checker"));
    }

    private Optional<Checker> getChecker(CheckerUuid checkerUuid) {
      try {
        return checkers.getChecker(checkerUuid);
      } catch (IOException | ConfigInvalidException e) {
        throw new IllegalStateException(e);
      }
    }

    @Override
    public RevCommit commit() throws IOException {
      Optional<Checker> checker = getChecker(checkerUuid);
      checkState(checker.isPresent(), "Tried to get commit for a non-existing test checker");

      try (Repository repo = repoManager.openRepository(allProjectsName);
          RevWalk rw = new RevWalk(repo)) {
        return rw.parseCommit(checker.get().getRefState());
      }
    }

    @Override
    public String configText() throws IOException, ConfigInvalidException {
      Optional<Checker> checker = getChecker(checkerUuid);
      checkState(checker.isPresent(), "Tried to get config text for a non-existing test checker");

      try (Repository repo = repoManager.openRepository(allProjectsName)) {
        // Parse as Config to ensure it's a valid config file.
        return new BlobBasedConfig(
                null, repo, checker.get().getRefState(), CheckerConfig.CHECKER_CONFIG_FILE)
            .toText();
      }
    }

    @Override
    public CheckerInfo asInfo() {
      Optional<Checker> checker = getChecker(checkerUuid);
      checkState(checker.isPresent(), "Tried to get a non-existing test checker as CheckerInfo");
      return checkerJson.format(checker.get());
    }

    @Override
    public TestCheckerUpdate.Builder forUpdate() {
      return TestCheckerUpdate.builder(this::updateChecker);
    }

    private void updateChecker(TestCheckerUpdate testCheckerUpdate) throws Exception {
      CheckerUpdate checkerUpdate = toCheckerUpdate(testCheckerUpdate);
      checkersUpdate.get().updateChecker(checkerUuid, checkerUpdate);
    }

    @Override
    public TestCheckerInvalidation.Builder forInvalidation() {
      return TestCheckerInvalidation.builder(this::invalidateChecker);
    }

    private void invalidateChecker(TestCheckerInvalidation testCheckerInvalidation)
        throws Exception {
      Optional<Checker> checker = getChecker(checkerUuid);
      checkState(checker.isPresent(), "Tried to invalidate a non-existing test checker");

      if (testCheckerInvalidation.invalidUuid()) {
        setValueInCheckerConfig("uuid", "invalid");
      }

      if (testCheckerInvalidation.invalidBlockingCondition()) {
        addValueInCheckerConfig("blocking", "invalid");
      }

      if (testCheckerInvalidation.invalidStatus()) {
        setValueInCheckerConfig("status", "invalid");
      }

      if (testCheckerInvalidation.unsetUuid()) {
        unsetValueInCheckerConfig("uuid");
      }

      if (testCheckerInvalidation.unsetName()) {
        unsetValueInCheckerConfig("name");
      }

      if (testCheckerInvalidation.unsetRepository()) {
        unsetValueInCheckerConfig("repository");
      }

      if (testCheckerInvalidation.unsetStatus()) {
        unsetValueInCheckerConfig("status");
      }

      if (testCheckerInvalidation.nonParseableConfig()) {
        try (Repository repo = repoManager.openRepository(allProjectsName);
            TestRepository<Repository> testRepo = new TestRepository<>(repo)) {
          testRepo
              .branch(checkerUuid.toRefName())
              .commit()
              .add(CheckerConfig.CHECKER_CONFIG_FILE, "non-parseable-config")
              .create();
        }
      }

      if (testCheckerInvalidation.deleteRef()) {
        try (Repository repo = repoManager.openRepository(allProjectsName);
            TestRepository<Repository> testRepo = new TestRepository<>(repo)) {
          RefUpdate ru = testRepo.getRepository().updateRef(checkerUuid.toRefName(), true);
          ru.setForceUpdate(true);
          testRefAction(() -> ru.delete());
        }
      }
    }

    private void setValueInCheckerConfig(String key, String value) throws Exception {
      updateCheckerConfig(cfg -> cfg.setString("checker", null, key, value));
    }

    private void addValueInCheckerConfig(String key, String value) throws Exception {
      updateCheckerConfig(
          cfg ->
              cfg.setStringList(
                  "checker",
                  null,
                  key,
                  Streams.concat(
                          Arrays.stream(cfg.getStringList("checker", null, key)), Stream.of(value))
                      .collect(toList())));
    }

    private void unsetValueInCheckerConfig(String key) throws Exception {
      updateCheckerConfig(cfg -> cfg.unset("checker", null, key));
    }

    private void updateCheckerConfig(Consumer<Config> configUpdater) throws Exception {
      try (Repository repo = repoManager.openRepository(allProjectsName)) {
        TestRepository<Repository> testRepo = new TestRepository<>(repo);
        Config checkerConfig =
            readConfig(testRepo, checkerUuid.toRefName(), CheckerConfig.CHECKER_CONFIG_FILE);
        configUpdater.accept(checkerConfig);
        testRepo
            .branch(checkerUuid.toRefName())
            .commit()
            .add(CheckerConfig.CHECKER_CONFIG_FILE, checkerConfig.toText())
            .create();
      }
    }

    private CheckerUpdate toCheckerUpdate(TestCheckerUpdate checkerUpdate) {
      CheckerUpdate.Builder builder = CheckerUpdate.builder();
      checkerUpdate.name().ifPresent(builder::setName);
      checkerUpdate.description().ifPresent(builder::setDescription);
      checkerUpdate.url().ifPresent(builder::setUrl);
      checkerUpdate.repository().ifPresent(builder::setRepository);
      checkerUpdate.status().ifPresent(builder::setStatus);
      checkerUpdate.blockingConditions().ifPresent(builder::setBlockingConditions);
      checkerUpdate.query().ifPresent(builder::setQuery);
      return builder.build();
    }

    private Config readConfig(TestRepository<?> testRepo, String ref, String fileName)
        throws Exception {
      Repository repo = testRepo.getRepository();
      return new BlobBasedConfig(null, repo, repo.resolve(ref), fileName);
    }
  }
}
