// 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.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 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 {
    // 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.isEmpty());
          } 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;
  }
}
