// 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.googlesource.gerrit.plugins.copyright;

import static com.google.common.truth.Truth.assertThat;
import static com.googlesource.gerrit.plugins.copyright.ScannerConfig.KEY_ENABLE;
import static com.googlesource.gerrit.plugins.copyright.ScannerConfig.KEY_EXCLUDE;
import static com.googlesource.gerrit.plugins.copyright.ScannerConfig.KEY_FIRST_PARTY;
import static com.googlesource.gerrit.plugins.copyright.ScannerConfig.KEY_FORBIDDEN;
import static com.googlesource.gerrit.plugins.copyright.ScannerConfig.KEY_FORBIDDEN_PATTERN;
import static com.googlesource.gerrit.plugins.copyright.ScannerConfig.KEY_REVIEW_LABEL;
import static com.googlesource.gerrit.plugins.copyright.ScannerConfig.KEY_THIRD_PARTY;
import static java.nio.charset.StandardCharsets.UTF_8;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.gerrit.acceptance.PushOneCommit;
import com.google.gerrit.acceptance.TestAccount;
import com.google.gerrit.common.data.GroupReference;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.client.RefNames;
import com.google.gerrit.server.config.PluginConfig;
import com.google.gerrit.server.group.InternalGroup;
import com.google.gerrit.server.project.GroupList;
import com.google.gerrit.server.project.ProjectConfig;
import java.util.Arrays;
import java.util.function.Consumer;
import org.eclipse.jgit.internal.storage.dfs.InMemoryRepository;
import org.eclipse.jgit.junit.TestRepository;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.ObjectLoader;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.revwalk.RevBlob;
import org.eclipse.jgit.revwalk.RevObject;
import org.eclipse.jgit.revwalk.RevWalk;

/** Test helper for copyright plugin All-Projects configurations. */
class TestConfig {
  static final String LOCAL_BRANCH = "config";

  private static final String ACCESS = "access";
  private static final String LABEL = "label";
  private static final String PLUGIN = "plugin";

  private Project.NameKey project;
  private String pluginName;
  private TestAccount owner;
  private TestRepository<InMemoryRepository> testRepo;
  private Config configProject;
  private Config configPlugin;
  private PluginConfig pluginConfig;
  private GroupList groupList;
  private String commitMsg;

  TestConfig(
      Project.NameKey project,
      String pluginName,
      TestAccount owner,
      TestRepository<InMemoryRepository> testRepo)
      throws Exception {
    this.project = project;
    this.pluginName = pluginName;
    this.owner = owner;
    this.testRepo = testRepo;
    readConfigProject();
    extractPlugin();
    this.commitMsg = "This is a commit.";
  }

  static final Consumer<PluginConfig> BASE_CONFIG =
      pCfg -> {
        pCfg.setString(KEY_REVIEW_LABEL, "Copyright-Review");
        pCfg.setStringList(KEY_EXCLUDE, ImmutableList.of("EXAMPLES"));
        pCfg.setStringList(
            KEY_FIRST_PARTY, ImmutableList.of("APACHE2", "ANDROID", "GOOGLE", "EXAMPLES"));
        pCfg.setStringList(
            KEY_THIRD_PARTY, ImmutableList.of("BSD", "MIT", "EPL", "GPL2", "GPL3", "PSFL"));
        pCfg.setStringList(
            KEY_FORBIDDEN,
            ImmutableList.of(
                "AGPL",
                "NOT_A_CONTRIBUTION",
                "WTFPL",
                "CC_BY_NC",
                "NON_COMMERCIAL",
                "COMMONS_CLAUSE"));
        pCfg.setStringList(
            KEY_FORBIDDEN_PATTERN,
            ImmutableList.of("license .*(?:Previously|formerly) licen[cs]ed under.*"));
      };

  static final Consumer<PluginConfig> ENABLE_CONFIG =
      pCfg -> {
        pCfg.setBoolean(KEY_ENABLE, true);
      };
  static final Consumer<PluginConfig> DISABLE_CONFIG =
      pCfg -> {
        pCfg.setBoolean(KEY_ENABLE, false);
      };

  /** Adds {@code groups} to the groups file. */
  void addGroups(InternalGroup... groups) throws Exception {
    if (groups == null) {
      return;
    }
    for (InternalGroup group : groups) {
      groupList.put(
          group.getGroupUUID(), new GroupReference(group.getGroupUUID(), group.getNameKey().get()));
    }
  }

  /**
   * Make a copy of an existing label configuration {@code fromLabel} under a different name, {@code
   * toLabel}.
   *
   * <p>Useful shortcut for configuring a Copyright-Review label based on the default Code-Review
   * label.
   */
  void copyLabel(String fromLabel, String toLabel) throws Exception {
    for (String name : configProject.getNames(LABEL, fromLabel)) {
      configProject.setStringList(
          LABEL, toLabel, name, Arrays.asList(configProject.getStringList(LABEL, fromLabel, name)));
    }
    for (String sub : configProject.getSubsections(ACCESS)) {
      for (String name : configProject.getNames(ACCESS, sub)) {
        if (!name.endsWith("-" + fromLabel)) {
          continue;
        }
        String[] values = configProject.getStringList(ACCESS, sub, name);
        if (values == null || values.length == 0) {
          continue;
        }
        configProject.setStringList(
            ACCESS,
            sub,
            name.substring(0, name.length() - fromLabel.length()) + toLabel,
            Arrays.asList(values));
      }
    }
  }

  /** Creates a commit for the current configuration and pushes the commit to trigger validation. */
  PushOneCommit.Result push(PushOneCommit.Factory pushFactory) throws Exception {
    savePlugin();
    String subject = "Change All-Projects project.config\n\n" + commitMsg;
    PersonIdent author = owner.newIdent();
    PushOneCommit pushCommit =
        pushFactory.create(
            author,
            testRepo,
            subject,
            ImmutableMap.<String, String>of(
                ProjectConfig.PROJECT_CONFIG,
                configProject.toText(),
                GroupList.FILE_NAME,
                groupList.asText()));
    return pushCommit.to("refs/for/" + RefNames.REFS_CONFIG);
  }

  /** Adds {@code message} to the /COMMIT_MSG text for the push. */
  void commitMessage(String message) throws Exception {
    commitMsg = commitMsg + message;
  }

  /** Deletes the label section and voter configurations for {@code label}. */
  void removeLabel(String label) throws Exception {
    for (String sub : configProject.getSubsections(ACCESS)) {
      configProject.setStringList(ACCESS, sub, "label-" + label, ImmutableList.of());
      configProject.setStringList(ACCESS, sub, "labelAs-" + label, ImmutableList.of());
    }
    configProject.unsetSection(LABEL, label);
  }

  /** Deletes the voter configurations for {@code label} from the access section for {@code ref}. */
  void removeVoters(String ref, String label) throws Exception {
    configProject.setStringList(ACCESS, ref, "label-" + label, ImmutableList.of());
  }

  /**
   * Replaces the voter configuration for {@code label} in the access section for {@code ref} with
   * {@code voters}.
   */
  void setVoters(String ref, String label, Voter... voters) throws Exception {
    ImmutableList.Builder<String> builder = ImmutableList.builder();
    for (Voter v : voters) {
      builder.add(vString(v.minVote) + ".." + vString(v.maxVote) + " group " + v.groupName);
    }
    configProject.setStringList(ACCESS, ref, "label-" + label, builder.build());
  }

  /** Apply {@code updates} to {@code this.pluginConfig}. */
  void updatePlugin(Consumer<PluginConfig>... updates) throws Exception {
    for (Consumer<PluginConfig> update : updates) {
      update.accept(pluginConfig);
    }
  }

  /** Extracts the plugin section from the project config and creates a PluginConfig view of it. */
  private void extractPlugin() throws Exception {
    configPlugin = new Config();
    for (String name : configProject.getNames(PLUGIN, pluginName)) {
      configPlugin.setStringList(
          PLUGIN,
          pluginName,
          name,
          Arrays.asList(configProject.getStringList(PLUGIN, pluginName, name)));
    }
    pluginConfig = new PluginConfig(pluginName, configPlugin);
  }

  /** Reads the project.config and groups files from {@code this.testRepo}. */
  private void readConfigProject() throws Exception {
    Ref ref = testRepo.getRepository().exactRef(LOCAL_BRANCH);
    configProject = new Config();
    configProject.fromText(readFileContents(ref, ProjectConfig.PROJECT_CONFIG));
    groupList = GroupList.parse(project, readFileContents(ref, GroupList.FILE_NAME), e -> {});
  }

  /** Reads the contents of {@code ref}/{@code path} from {@code this.restRepo}. */
  private String readFileContents(Ref ref, String path) throws Exception {
    RevWalk rw = testRepo.getRevWalk();
    RevObject obj = testRepo.get(rw.parseTree(ref.getObjectId()), path);
    assertThat(obj).isInstanceOf(RevBlob.class);
    ObjectLoader loader = rw.getObjectReader().open(obj);
    return new String(loader.getCachedBytes(), UTF_8);
  }

  /**
   * Replaces the plugin section in {@code this.configProject} with the contents of {@code
   * this.configPlugin}.
   */
  private void savePlugin() throws Exception {
    configProject.unsetSection(PLUGIN, pluginName);
    for (String name : configPlugin.getNames(PLUGIN, pluginName)) {
      configProject.setStringList(
          PLUGIN,
          pluginName,
          name,
          Arrays.asList(configPlugin.getStringList(PLUGIN, pluginName, name)));
    }
  }

  /** Formats integers with an explicit sign for both positive and negative values. */
  private String vString(int vote) throws Exception {
    return (vote > 0 ? "+" : "") + Integer.toString(vote);
  }

  /** A group name and allowed vote range. */
  static class Voter {
    String groupName;
    int minVote;
    int maxVote;

    Voter(String groupName, int minVote, int maxVote) {
      this.groupName = groupName;
      this.minVote = minVote;
      this.maxVote = maxVote;
    }
  }
}
