// 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 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);
          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);
    }
  }
}
