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

import static com.googlesource.gerrit.plugins.findowners.Config.OWNERS;
import static com.googlesource.gerrit.plugins.findowners.Config.OWNERS_FILE_NAME;
import static com.googlesource.gerrit.plugins.findowners.Config.REJECT_ERROR_IN_OWNERS;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.Multimap;
import com.google.gerrit.extensions.annotations.Exports;
import com.google.gerrit.extensions.annotations.PluginName;
import com.google.gerrit.extensions.api.projects.ProjectConfigEntryType;
import com.google.gerrit.extensions.registration.DynamicSet;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.server.account.Emails;
import com.google.gerrit.server.config.PluginConfig;
import com.google.gerrit.server.config.PluginConfigFactory;
import com.google.gerrit.server.config.ProjectConfigEntry;
import com.google.gerrit.server.events.CommitReceivedEvent;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.git.validators.CommitValidationException;
import com.google.gerrit.server.git.validators.CommitValidationListener;
import com.google.gerrit.server.git.validators.CommitValidationMessage;
import com.google.gerrit.server.project.NoSuchProjectException;
import com.google.inject.AbstractModule;
import com.google.inject.Inject;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.eclipse.jgit.diff.RawText;
import org.eclipse.jgit.lib.FileMode;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectLoader;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.treewalk.TreeWalk;
import org.eclipse.jgit.treewalk.filter.TreeFilter;

/** Check syntax of changed OWNERS files. */
public class OwnersValidator implements CommitValidationListener {
  private interface TreeWalkVisitor {
    void onVisit(TreeWalk tw);
  }

  public static AbstractModule module() {
    return new AbstractModule() {
      @Override
      protected void configure() {
        DynamicSet.bind(binder(), CommitValidationListener.class).to(OwnersValidator.class);
        bind(ProjectConfigEntry.class)
            .annotatedWith(Exports.named(REJECT_ERROR_IN_OWNERS))
            .toInstance(
                new ProjectConfigEntry(
                    "Reject OWNERS Files With Errors",
                    null,
                    ProjectConfigEntryType.BOOLEAN,
                    null,
                    false,
                    "Pushes of commits with errors in OWNERS files will be rejected."));
      }
    };
  }

  private final String pluginName;
  private final PluginConfigFactory cfgFactory;
  private final GitRepositoryManager repoManager;
  private final Emails emails;

  @Inject
  OwnersValidator(
      @PluginName String pluginName,
      PluginConfigFactory cfgFactory,
      GitRepositoryManager repoManager,
      Emails emails) {
    this.pluginName = pluginName;
    this.cfgFactory = cfgFactory;
    this.repoManager = repoManager;
    this.emails = emails;
  }

  public static String getOwnersFileName(PluginConfig cfg) {
    return getOwnersFileName(cfg, OWNERS);
  }

  public static String getOwnersFileName(PluginConfig cfg, String defaultName) {
    return cfg.getString(OWNERS_FILE_NAME, defaultName);
  }

  public String getOwnersFileName(Project.NameKey project) {
    String name = getOwnersFileName(cfgFactory.getFromGerritConfig(pluginName, true));
    try {
      return getOwnersFileName(
          cfgFactory.getFromProjectConfigWithInheritance(project, pluginName), name);
    } catch (NoSuchProjectException e) {
      return name;
    }
  }

  @VisibleForTesting
  static boolean isActive(PluginConfig cfg) {
    return cfg.getBoolean(REJECT_ERROR_IN_OWNERS, false);
  }

  @Override
  public List<CommitValidationMessage> onCommitReceived(CommitReceivedEvent receiveEvent)
      throws CommitValidationException {
    List<CommitValidationMessage> messages = new LinkedList<>();
    try {
      Project.NameKey project = receiveEvent.project.getNameKey();
      PluginConfig cfg = cfgFactory.getFromProjectConfigWithInheritance(project, pluginName);
      if (isActive(cfg)) {
        try (Repository repo = repoManager.openRepository(project)) {
          String name = getOwnersFileName(project);
          messages = performValidation(receiveEvent.commit, receiveEvent.revWalk, name, false);
        }
      }
    } catch (NoSuchProjectException | IOException | ExecutionException e) {
      throw new CommitValidationException("failed to check owners files", e);
    }
    if (hasError(messages)) {
      throw new CommitValidationException("found invalid owners file", messages);
    }
    return messages;
  }

  @VisibleForTesting
  List<CommitValidationMessage> performValidation(
      RevCommit c, RevWalk revWalk, String ownersFileName, boolean verbose)
      throws IOException, ExecutionException {
    // Collect all messages from all files.
    List<CommitValidationMessage> messages = new LinkedList<>();
    // Collect all email addresses from all files and check each address only once.
    Map<String, Set<String>> email2lines = new HashMap<>();
    Map<String, ObjectId> content = getChangedOwners(c, revWalk, ownersFileName);
    for (String path : content.keySet()) {
      ObjectLoader ol = revWalk.getObjectReader().open(content.get(path));
      try (InputStream in = ol.openStream()) {
        if (RawText.isBinary(in)) {
          add(messages, path + " is a binary file", true); // OWNERS files cannot be binary
          continue;
        }
      }
      checkFile(messages, email2lines, path, ol, verbose);
    }
    checkEmails(messages, emails, email2lines, verbose);
    return messages;
  }

  private static void checkEmails(
      List<CommitValidationMessage> messages,
      Emails emails,
      Map<String, Set<String>> email2lines,
      boolean verbose) {
    List<String> owners = new ArrayList<>(email2lines.keySet());
    if (verbose) {
      for (String owner : owners) {
        add(messages, "owner: " + owner, false);
      }
    }
    if (emails == null || owners.isEmpty()) {
      return;
    }
    String[] ownerEmailsAsArray = new String[owners.size()];
    owners.toArray(ownerEmailsAsArray);
    try {
      Multimap<String, Account.Id> email2ids = emails.getAccountsFor(ownerEmailsAsArray);
      for (String owner : ownerEmailsAsArray) {
        boolean wrongEmail = (email2ids == null);
        if (!wrongEmail) {
          try {
            Collection<Account.Id> ids = email2ids.get(owner);
            wrongEmail = (ids == null || ids.size() != 1);
          } catch (Exception e) {
            wrongEmail = true;
          }
        }
        if (wrongEmail) {
          String locations = String.join(" ", email2lines.get(owner));
          add(messages, "unknown: " + owner + " at " + locations, true);
        }
      }
    } catch (Exception e) {
      add(messages, "checkEmails failed.", true);
    }
  }

  private static void checkFile(
      List<CommitValidationMessage> messages,
      Map<String, Set<String>> email2lines,
      String path,
      ObjectLoader ol,
      boolean verbose)
      throws IOException {
    if (verbose) {
      add(messages, "validate: " + path, false);
    }
    try (BufferedReader br =
        new BufferedReader(new InputStreamReader(ol.openStream(), StandardCharsets.UTF_8))) {
      int line = 0;
      for (String l = br.readLine(); l != null; l = br.readLine()) {
        line++;
        checkLine(messages, email2lines, path, line, l);
      }
    }
  }

  // Line patterns accepted by Parser.java in the find-owners plugin.
  static final Pattern patComment = Pattern.compile("^ *(#.*)?$");
  static final Pattern patEmail = // email address or a "*"
      Pattern.compile("^ *([^ <>@]+@[^ <>@#]+|\\*) *(#.*)?$");
  static final Pattern patFile = Pattern.compile("^ *file:.*$");
  static final Pattern patNoParent = Pattern.compile("^ *set +noparent *(#.*)?$");
  static final Pattern patPerFileNoParent =
      Pattern.compile("^ *per-file +([^= ]+) *= *set +noparent *(#.*)?$");
  static final Pattern patPerFileEmail =
      Pattern.compile("^ *per-file +([^= ]+) *= *([^ <>@]+@[^ <>@#]+|\\*) *(#.*)?$");

  private static void collectEmail(
      Map<String, Set<String>> map, String email, String file, int lineNumber) {
    if (!email.equals("*")) {
      map.computeIfAbsent(email, (String k) -> new HashSet<>());
      map.get(email).add(file + ":" + lineNumber);
    }
  }

  private static boolean hasError(List<CommitValidationMessage> messages) {
    for (CommitValidationMessage m : messages) {
      if (m.isError()) {
        return true;
      }
    }
    return false;
  }

  private static void add(List<CommitValidationMessage> messages, String msg, boolean error) {
    messages.add(new CommitValidationMessage(msg, error));
  }

  private static void checkLine(
      List<CommitValidationMessage> messages,
      Map<String, Set<String>> email2lines,
      String path,
      int lineNumber,
      String line) {
    Matcher m;
    if (patComment.matcher(line).find()
        || patNoParent.matcher(line).find()
        || patPerFileNoParent.matcher(line).find()) {
      return;
    } else if ((m = patEmail.matcher(line)).find()) {
      collectEmail(email2lines, m.group(1), path, lineNumber);
    } else if ((m = patPerFileEmail.matcher(line)).find()) {
      collectEmail(email2lines, m.group(2).trim(), path, lineNumber);
    } else {
      String prefix = patFile.matcher(line).find() ? "ignored" : "syntax";
      add(messages, prefix + ": " + path + ":" + lineNumber + ": " + line, true);
    }
  }

  /**
   * Find all changed OWNERS files which differ between the commit and its parents. Return a map
   * from "Path to the changed file" to "ObjectId of the file".
   */
  private static Map<String, ObjectId> getChangedOwners(
      RevCommit c, RevWalk revWalk, String ownersFileName) throws IOException {
    final Map<String, ObjectId> content = new HashMap<>();
    visitChangedEntries(
        c,
        revWalk,
        new TreeWalkVisitor() {
          @Override
          public void onVisit(TreeWalk tw) {
            if (isFile(tw) && ownersFileName.equals(tw.getNameString())) {
              content.put(tw.getPathString(), tw.getObjectId(0));
            }
          }
        });
    return content;
  }

  private static boolean isFile(TreeWalk tw) {
    return FileMode.EXECUTABLE_FILE.equals(tw.getRawMode(0))
        || FileMode.REGULAR_FILE.equals(tw.getRawMode(0));
  }

  /**
   * Find all TreeWalk entries which differ between the commit and its parents. If a TreeWalk entry
   * is found this method calls the onVisit() method of the class TreeWalkVisitor.
   */
  private static void visitChangedEntries(RevCommit c, RevWalk revWalk, TreeWalkVisitor visitor)
      throws IOException {
    try (TreeWalk tw = new TreeWalk(revWalk.getObjectReader())) {
      tw.setRecursive(true);
      tw.setFilter(TreeFilter.ANY_DIFF);
      tw.addTree(c.getTree());
      if (c.getParentCount() > 0) {
        for (RevCommit p : c.getParents()) {
          if (p.getTree() == null) {
            revWalk.parseHeaders(p);
          }
          tw.addTree(p.getTree());
        }
        while (tw.next()) {
          if (isDifferentToAllParents(c, tw)) {
            visitor.onVisit(tw);
          }
        }
      } else {
        while (tw.next()) {
          visitor.onVisit(tw);
        }
      }
    }
  }

  private static boolean isDifferentToAllParents(RevCommit c, TreeWalk tw) {
    if (c.getParentCount() > 1) {
      for (int p = 1; p <= c.getParentCount(); p++) {
        if (tw.getObjectId(0).equals(tw.getObjectId(p))) {
          return false;
        }
      }
    }
    return true;
  }
}
