// Copyright (C) 2020 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.codeowners.backend.findowners;

import static com.google.common.base.Preconditions.checkState;
import static com.google.common.collect.ImmutableSet.toImmutableSet;
import static java.util.Objects.requireNonNull;
import static java.util.stream.Collectors.joining;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Joiner;
import com.google.common.base.Splitter;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.gerrit.entities.Project;
import com.google.gerrit.plugins.codeowners.backend.CodeOwnerConfig;
import com.google.gerrit.plugins.codeowners.backend.CodeOwnerConfigImportMode;
import com.google.gerrit.plugins.codeowners.backend.CodeOwnerConfigParseException;
import com.google.gerrit.plugins.codeowners.backend.CodeOwnerConfigParser;
import com.google.gerrit.plugins.codeowners.backend.CodeOwnerConfigReference;
import com.google.gerrit.plugins.codeowners.backend.CodeOwnerReference;
import com.google.gerrit.plugins.codeowners.backend.CodeOwnerSet;
import com.google.gerrit.server.git.ValidationError;
import com.google.inject.Singleton;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Stream;
import org.eclipse.jgit.lib.ObjectId;

/**
 * Parser and formatter for the syntax that is used to store {@link CodeOwnerConfig}s in {@code
 * OWNERS} files as they are used by the {@code find-owners} plugin.
 *
 * <p>The syntax is described at in the {@code find-owners} plugin documentation at:
 * https://gerrit.googlesource.com/plugins/find-owners/+/master/src/main/resources/Documentation/syntax.md
 *
 * <p>Comment lines are silently ignored.
 *
 * <p>Invalid lines cause the parsing to fail and trigger a {@link CodeOwnerConfigParseException}.
 *
 * <p>Comments can appear as separate lines and as appendix for email lines (e.g. using
 * 'foo.bar@example.com # Foo Bar' would be a valid email line).
 *
 * <p>Most of the code in this class was copied from the {@code
 * com.googlesource.gerrit.plugins.findowners.Parser} class from the {@code find-owners} plugin. The
 * original parsing code is used to be as backwards-compatible as possible and to avoid spending
 * time on reimplementing a parser for a deprecated syntax. We have only done a minimal amount of
 * adaption so that the parser produces a {@link CodeOwnerConfig} as result, instead of the
 * abstraction that is used in the {@code find-owners} plugin.
 */
@Singleton
@VisibleForTesting
public class FindOwnersCodeOwnerConfigParser implements CodeOwnerConfigParser {
  // Artifical owner token for "set noparent" when used in per-file.
  private static final String TOK_SET_NOPARENT = "set noparent";

  /**
   * Any Unicode linebreak sequence, is equivalent to {@code
   * \u000D\u000A|[\u000A\u000B\u000C\u000D\u0085\u2028\u2029]}.
   */
  private static final String LINEBREAK_MATCHER = "\\R";

  @Override
  public CodeOwnerConfig parse(
      ObjectId revision, CodeOwnerConfig.Key codeOwnerConfigKey, String codeOwnerConfigAsString)
      throws CodeOwnerConfigParseException {
    requireNonNull(revision, "revision");
    requireNonNull(codeOwnerConfigKey, "codeOwnerConfigKey");

    Parser parser = new Parser();
    CodeOwnerConfig codeOwnerConfig =
        parser.parse(revision, codeOwnerConfigKey, Strings.nullToEmpty(codeOwnerConfigAsString));
    if (!parser.getValidationErrors().isEmpty()) {
      throw new CodeOwnerConfigParseException(codeOwnerConfigKey, parser.getValidationErrors());
    }
    return codeOwnerConfig;
  }

  @Override
  public String formatAsString(CodeOwnerConfig codeOwnerConfig) {
    return Formatter.formatAsString(requireNonNull(codeOwnerConfig, "codeOwnerConfig"));
  }

  public static String replaceEmail(
      String codeOwnerConfigFileContent, String oldEmail, String newEmail) {
    requireNonNull(codeOwnerConfigFileContent, "codeOwnerConfigFileContent");
    requireNonNull(oldEmail, "oldEmail");
    requireNonNull(newEmail, "newEmail");

    String charsThatCanAppearBeforeOrAfterEmail = "[\\s=,#]";
    Pattern pattern =
        Pattern.compile(
            "(^|.*"
                + charsThatCanAppearBeforeOrAfterEmail
                + "+)"
                + "("
                + Pattern.quote(oldEmail)
                + ")"
                + "($|"
                + charsThatCanAppearBeforeOrAfterEmail
                + "+.*)");

    List<String> updatedLines = new ArrayList<>();
    for (String line : Splitter.onPattern(LINEBREAK_MATCHER).split(codeOwnerConfigFileContent)) {
      while (pattern.matcher(line).matches()) {
        line = pattern.matcher(line).replaceFirst("$1" + newEmail + "$3");
      }
      updatedLines.add(line);
    }
    return Joiner.on("\n").join(updatedLines);
  }

  private static class Parser implements ValidationError.Sink {
    private static final String COMMA = "[\\s]*,[\\s]*";

    // Separator for project and file paths in an include line.
    private static final String COLON = "[\\s]*:[\\s]*"; // project:file

    private static final String BOL = "^[\\s]*"; // begin-of-line
    private static final String EOL = "[\\s]*(#.*)?$"; // end-of-line
    private static final String GLOB = "[^\\s,=]+"; // a file glob

    private static final String EMAIL_OR_STAR = "([^\\s<>@,]+@[^\\s<>@#,]+|\\*)";
    private static final String EMAIL_LIST =
        "(" + EMAIL_OR_STAR + "(" + COMMA + EMAIL_OR_STAR + ")*)";

    // Optional name of a Gerrit project followed by a colon and optional spaces.
    private static final String PROJECT_NAME = "([^\\s:]+" + COLON + ")?";

    // Optional name of a branch followed by a colon and optional spaces.
    private static final String BRANCH_NAME = "([^\\s:]+" + COLON + ")?";

    // A relative or absolute file path name without any colon or space character.
    private static final String FILE_PATH = "([^\\s:#]+)";

    private static final String PROJECT_BRANCH_AND_FILE = PROJECT_NAME + BRANCH_NAME + FILE_PATH;

    private static final String SET_NOPARENT = "set[\\s]+noparent";

    private static final String FILE_DIRECTIVE = "file:[\\s]*" + PROJECT_BRANCH_AND_FILE;
    private static final String INCLUDE_DIRECTIVE = "include[\\s]+" + PROJECT_BRANCH_AND_FILE;
    private static final String INCLUDE_OR_FILE = "(file:[\\s]*|include[\\s]+)";

    // Simple input lines with 0 or 1 sub-pattern.
    private static final Pattern PAT_COMMENT = Pattern.compile(BOL + EOL);
    private static final Pattern PAT_EMAIL = Pattern.compile(BOL + EMAIL_OR_STAR + EOL);
    private static final Pattern PAT_INCLUDE =
        Pattern.compile(BOL + INCLUDE_OR_FILE + PROJECT_BRANCH_AND_FILE + EOL);
    private static final Pattern PAT_NO_PARENT = Pattern.compile(BOL + SET_NOPARENT + EOL);

    private static final Pattern PAT_PER_FILE_OWNERS =
        Pattern.compile("^(" + EMAIL_LIST + "|" + SET_NOPARENT + "|" + FILE_DIRECTIVE + ")$");
    private static final Pattern PAT_PER_FILE_INCLUDE =
        Pattern.compile("^(" + INCLUDE_DIRECTIVE + ")$");
    private static final Pattern PAT_GLOBS =
        Pattern.compile("^(" + GLOB + "(" + COMMA + GLOB + ")*)$");

    // PAT_PER_FILE matches a line to two groups: (1) globs, (2) emails
    // Trimmed 1st group should match PAT_GLOBS;
    // trimmed 2nd group should match PAT_PER_FILE_OWNERS.
    private static final Pattern PAT_PER_FILE =
        Pattern.compile(BOL + "per-file[\\s]+([^=#]+)=[\\s]*([^#]+)" + EOL);

    private List<ValidationError> validationErrors;

    CodeOwnerConfig parse(
        ObjectId revision, CodeOwnerConfig.Key codeOwnerConfigKey, String codeOwnerConfigAsString) {
      CodeOwnerConfig.Builder codeOwnerConfigBuilder =
          CodeOwnerConfig.builder(codeOwnerConfigKey, revision);
      CodeOwnerSet.Builder globalCodeOwnerSetBuilder = CodeOwnerSet.builder();
      List<CodeOwnerSet> perFileCodeOwnerSet = new ArrayList<>();

      for (String line : Splitter.onPattern(LINEBREAK_MATCHER).split(codeOwnerConfigAsString)) {
        parseLine(codeOwnerConfigBuilder, globalCodeOwnerSetBuilder, perFileCodeOwnerSet, line);
      }

      // Make the code owners sets with the global code owners the first one in the list.
      CodeOwnerSet globalCodeOwnersSet = globalCodeOwnerSetBuilder.build();
      if (!globalCodeOwnersSet.codeOwners().isEmpty()) {
        codeOwnerConfigBuilder.addCodeOwnerSet(globalCodeOwnersSet);
      }
      perFileCodeOwnerSet.forEach(codeOwnerConfigBuilder::addCodeOwnerSet);

      return codeOwnerConfigBuilder.build();
    }

    private void parseLine(
        CodeOwnerConfig.Builder codeOwnerConfigBuilder,
        CodeOwnerSet.Builder globalCodeOwnerSetBuilder,
        List<CodeOwnerSet> perFileCodeOwnerSets,
        String line) {
      String email;
      CodeOwnerSet codeOwnerSet;
      CodeOwnerConfigReference codeOwnerConfigReference;
      if (isNoParent(line)) {
        codeOwnerConfigBuilder.setIgnoreParentCodeOwners();
      } else if (isComment(line)) {
        // ignore comment lines and empty lines
      } else if ((email = parseEmail(line)) != null) {
        globalCodeOwnerSetBuilder.addCodeOwner(CodeOwnerReference.create(email));
      } else if ((codeOwnerSet = parsePerFile(line)) != null) {
        perFileCodeOwnerSets.add(codeOwnerSet);
      } else if ((codeOwnerConfigReference = parseInclude(line)) != null) {
        codeOwnerConfigBuilder.addImport(codeOwnerConfigReference);
      } else {
        error(ValidationError.create(String.format("invalid line: %s", line)));
      }
    }

    private static CodeOwnerSet parsePerFile(String line) {
      Matcher m = PAT_PER_FILE.matcher(line);
      if (!m.matches() || !isGlobs(m.group(1).trim())) {
        return null;
      }

      String matchedGroup2 = m.group(2).trim();
      if (!PAT_PER_FILE_OWNERS.matcher(matchedGroup2).matches()) {
        checkState(
            !PAT_PER_FILE_INCLUDE.matcher(matchedGroup2).matches(),
            "import mode %s is unsupported for per file import: %s",
            CodeOwnerConfigImportMode.ALL.name(),
            line);
        return null;
      }

      String[] globsAndOwners =
          new String[] {removeExtraSpaces(m.group(1)), removeExtraSpaces(m.group(2))};
      String[] dirGlobs = globsAndOwners[0].split(COMMA, -1);
      String directive = globsAndOwners[1];
      if (directive.equals(TOK_SET_NOPARENT)) {
        return CodeOwnerSet.builder()
            .setIgnoreGlobalAndParentCodeOwners()
            .setPathExpressions(ImmutableSet.copyOf(dirGlobs))
            .build();
      }

      CodeOwnerConfigReference codeOwnerConfigReference;
      if ((codeOwnerConfigReference = parseInclude(directive)) != null) {
        return CodeOwnerSet.builder()
            .addImport(codeOwnerConfigReference)
            .setPathExpressions(ImmutableSet.copyOf(dirGlobs))
            .build();
      }

      List<String> ownerEmails = Arrays.asList(directive.split(COMMA, -1));
      return CodeOwnerSet.builder()
          .setPathExpressions(ImmutableSet.copyOf(dirGlobs))
          .setCodeOwners(
              ownerEmails.stream().map(CodeOwnerReference::create).collect(toImmutableSet()))
          .build();
    }

    private static boolean isComment(String line) {
      return PAT_COMMENT.matcher(line).matches();
    }

    private static boolean isNoParent(String line) {
      return PAT_NO_PARENT.matcher(line).matches();
    }

    private static String parseEmail(String line) {
      Matcher m = PAT_EMAIL.matcher(line);
      return m.matches() ? m.group(1).trim() : null;
    }

    private static CodeOwnerConfigReference parseInclude(String line) {
      Matcher m = Parser.PAT_INCLUDE.matcher(line);
      if (!m.matches()) {
        return null;
      }

      String keyword = m.group(1).trim();
      CodeOwnerConfigImportMode importMode =
          keyword.equals("include")
              ? CodeOwnerConfigImportMode.ALL
              : CodeOwnerConfigImportMode.GLOBAL_CODE_OWNER_SETS_ONLY;

      CodeOwnerConfigReference.Builder builder =
          CodeOwnerConfigReference.builder(importMode, m.group(4).trim());

      String projectName = m.group(2);
      if (projectName != null && projectName.length() > 1) {
        // PROJECT_NAME ends with ':'
        projectName = projectName.split(COLON, -1)[0].trim();
        builder.setProject(Project.nameKey(projectName));

        String branchName = m.group(3);
        if (branchName != null && branchName.length() > 1) {
          // BRANCH_NAME ends with ':'
          branchName = branchName.split(COLON, -1)[0].trim();
          builder.setBranch(branchName);
        }
      }

      return builder.build();
    }

    private static boolean isGlobs(String line) {
      return PAT_GLOBS.matcher(line).matches();
    }

    private static String removeExtraSpaces(String s) {
      return s.trim().replaceAll("[\\s]+", " ").replaceAll("[\\s]*:[\\s]*", ":");
    }

    /**
     * Get the validation errors, if any were discovered during parsing the code owner config file.
     *
     * @return list of errors; empty list if there are no errors.
     */
    public ImmutableList<ValidationError> getValidationErrors() {
      if (validationErrors != null) {
        return ImmutableList.copyOf(validationErrors);
      }
      return ImmutableList.of();
    }

    @Override
    public void error(ValidationError error) {
      if (validationErrors == null) {
        validationErrors = new ArrayList<>(4);
      }
      validationErrors.add(error);
    }
  }

  private static class Formatter {
    private static final String SET_NOPARENT_LINE = "set noparent\n";

    // String format for a "per-file" line. The first placeholder is for the comma-separated list of
    // path expressions, the second placeholder is for the comma-separated list of emails.
    private static final String PER_FILE_LINE_FORMAT = "per-file %s=%s\n";

    static String formatAsString(CodeOwnerConfig codeOwnerConfig) {
      return formatIgnoreParentCodeOwners(codeOwnerConfig)
          + formatImports(codeOwnerConfig)
          + formatGlobalCodeOwners(codeOwnerConfig)
          + formatPerFileCodeOwners(codeOwnerConfig);
    }

    private static String formatIgnoreParentCodeOwners(CodeOwnerConfig codeOwnerConfig) {
      return codeOwnerConfig.ignoreParentCodeOwners() ? SET_NOPARENT_LINE : "";
    }

    private static String formatGlobalCodeOwners(CodeOwnerConfig codeOwnerConfig) {
      String emails =
          codeOwnerConfig.codeOwnerSets().stream()
              // Filter out code owner sets with path expressions. If path expressions are present
              // the code owner set defines per-file code owners and is handled in
              // formatPerFileCodeOwners(CodeOwnerConfig).
              .filter(codeOwnerSet -> codeOwnerSet.pathExpressions().isEmpty())
              .flatMap(codeOwnerSet -> codeOwnerSet.codeOwners().stream())
              .map(CodeOwnerReference::email)
              .sorted()
              .distinct()
              .collect(joining("\n"));
      if (!emails.isEmpty()) {
        return emails + "\n";
      }
      return emails;
    }

    private static String formatPerFileCodeOwners(CodeOwnerConfig codeOwnerConfig) {
      StringBuilder b = new StringBuilder();
      codeOwnerConfig.codeOwnerSets().stream()
          // Filter out code owner sets without path expressions. If path expressions are absent the
          // code owner set defines global code owners and is handled in
          // formatGlobalCodeOwners(CodeOwnerConfig).
          .filter(codeOwnerSet -> !codeOwnerSet.pathExpressions().isEmpty())
          .map(Formatter::formatCodeOwnerSet)
          .forEach(b::append);
      return b.toString();
    }

    private static String formatCodeOwnerSet(CodeOwnerSet codeOwnerSet) {
      String formattedPathExpressions = formatValuesAsList(codeOwnerSet.pathExpressions());

      StringBuilder b = new StringBuilder();
      if (codeOwnerSet.ignoreGlobalAndParentCodeOwners()) {
        b.append(String.format(PER_FILE_LINE_FORMAT, formattedPathExpressions, TOK_SET_NOPARENT));
      }

      for (CodeOwnerConfigReference codeOwnerConfigReference : codeOwnerSet.imports()) {
        b.append(
            String.format(
                PER_FILE_LINE_FORMAT,
                formattedPathExpressions,
                formatImport(codeOwnerConfigReference)));
      }

      if (!codeOwnerSet.codeOwners().isEmpty()) {
        b.append(
            String.format(
                PER_FILE_LINE_FORMAT,
                formattedPathExpressions,
                formatCodeOwnerReferencesAsList(codeOwnerSet.codeOwners())));
      }
      return b.toString();
    }

    private static String formatCodeOwnerReferencesAsList(
        ImmutableSet<CodeOwnerReference> codeOwnerReferences) {
      return formatValuesAsList(codeOwnerReferences.stream().map(CodeOwnerReference::email));
    }

    private static String formatValuesAsList(ImmutableSet<String> values) {
      return formatValuesAsList(values.stream());
    }

    private static String formatValuesAsList(Stream<String> stream) {
      return stream.sorted().distinct().collect(joining(","));
    }

    private static String formatImports(CodeOwnerConfig codeOwnerConfig) {
      StringBuilder b = new StringBuilder();
      codeOwnerConfig
          .imports()
          .forEach(
              codeOwnerConfigReference ->
                  b.append(formatImport(codeOwnerConfigReference)).append('\n'));
      return b.toString();
    }

    private static String formatImport(CodeOwnerConfigReference codeOwnerConfigReference) {
      StringBuilder b = new StringBuilder();

      // write the keyword
      switch (codeOwnerConfigReference.importMode()) {
        case ALL:
          b.append("include ");
          break;
        case GLOBAL_CODE_OWNER_SETS_ONLY:
          b.append("file: ");
          break;
        default:
          throw new IllegalStateException(
              String.format("unknown import mode: %s", codeOwnerConfigReference.importMode()));
      }

      // write the project
      if (codeOwnerConfigReference.project().isPresent()) {
        b.append(codeOwnerConfigReference.project().get()).append(':');
      }

      // write the branch
      if (codeOwnerConfigReference.branch().isPresent()) {
        checkState(
            codeOwnerConfigReference.project().isPresent(),
            "project is required if branch is specified: %s",
            codeOwnerConfigReference);
        b.append(codeOwnerConfigReference.branch().get()).append(':');
      }

      // write the file path
      b.append(codeOwnerConfigReference.filePath());

      return b.toString();
    }
  }
}
