// 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.google.common.base.Strings.isNullOrEmpty;
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.common.flogger.FluentLogger;
import com.google.gerrit.extensions.annotations.Exports;
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.inject.AbstractModule;
import com.google.inject.Inject;
import java.io.BufferedReader;
import java.io.File;
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.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
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.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 static final FluentLogger logger = FluentLogger.forEnclosingClass();

  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 Config config;
  private final GitRepositoryManager repoManager;
  private final Emails emails;

  @Inject
  OwnersValidator(PluginConfigFactory cfgFactory, GitRepositoryManager repoManager, Emails emails) {
    this(new Config(cfgFactory), repoManager, emails);
  }

  @VisibleForTesting
  OwnersValidator(PluginConfig config, GitRepositoryManager repoManager, Emails emails) {
    this(new Config(config), repoManager, emails);
  }

  private OwnersValidator(Config config, GitRepositoryManager repoManager, Emails emails) {
    this.config = config;
    this.repoManager = repoManager;
    this.emails = emails;
  }

  @VisibleForTesting
  String getOwnersFileName() {
    return config.getOwnersFileName();
  }

  @VisibleForTesting
  public String getOwnersFileName(Project project) {
    return config.getOwnersFileName(project);
  }

  @VisibleForTesting
  boolean isActive(Project project) {
    return config.getRejectErrorInOwners(project);
  }

  @VisibleForTesting
  boolean isActive() {
    return config.getRejectErrorInOwners();
  }

  @Override
  public List<CommitValidationMessage> onCommitReceived(CommitReceivedEvent event)
      throws CommitValidationException {
    if (!isActive(event.project)) {
      return new ArrayList<>();
    }
    Checker checker = new Checker(event, false);
    try {
      checker.check(getOwnersFileName(event.project));
      if (checker.hasError()) {
        checker.addError(
            "See OWNERS file syntax document at "
                + "https://gerrit.googlesource.com/plugins/find-owners/+/"
                + "master/src/main/resources/Documentation/syntax.md");
        throw new CommitValidationException("found invalid owners file", checker.messages);
      }
      return checker.messages;
    } catch (IOException e) {
      logger.atSevere().withCause(e).log("Failed in onCommitReceived");
      return new ArrayList<>();
    }
  }

  class Checker {
    // An inner class to keep needed data specific to one commit event.
    CommitReceivedEvent event;
    boolean verbose;
    List<CommitValidationMessage> messages;
    Map<String, ObjectId> allFiles; // changedFilePath => ObjectId
    Map<String, String> readFiles; // project:file => content
    Set<String> checkedFiles; // project:file
    // Collect all email addresses from all files and check each address only once.
    Map<String, Set<String>> email2lines;

    Checker(CommitReceivedEvent event, boolean verbose) {
      this.event = event;
      this.verbose = verbose;
      messages = new ArrayList<>();
      readFiles = new HashMap<>();
      checkedFiles = new HashSet<>();
      email2lines = new HashMap<>();
      try {
        allFiles = getChangedFiles(event.commit, event.revWalk);
      } catch (Exception e) {
        allFiles = new HashMap<>();
        addError("getChangedFiles failed.");
      }
    }

    @VisibleForTesting
    void check(String ownersFileName) throws IOException {
      Map<String, ObjectId> ownerFiles =
          allFiles.entrySet().stream()
              .filter(e -> ownersFileName.equals(new File(e.getKey()).getName()))
              .collect(Collectors.toMap(e -> e.getKey(), e -> e.getValue()));
      String projectName = event.project.getName();
      for (String path : ownerFiles.keySet()) {
        String key = projectName + ":" + path;
        ObjectLoader ol = event.revWalk.getObjectReader().open(ownerFiles.get(path));
        try (InputStream in = ol.openStream()) {
          if (RawText.isBinary(in)) {
            addError(path + " is a binary file"); // OWNERS files cannot be binary
            continue;
          }
        }
        checkedFiles.add(key);
        checkFile(projectName, path, ol);
      }
      checkEmails(emails);
    }

    void checkEmails(Emails emails) {
      List<String> owners = new ArrayList<>(email2lines.keySet());
      if (owners.isEmpty()) {
        return;
      }
      if (verbose) {
        for (String owner : owners) {
          addMsg("owner: " + owner);
        }
      }
      if (emails == null) {
        addError("cannot check owner emails with null Emails cache.");
      }
      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));
            addError("unknown: " + owner + " at " + locations);
          }
        }
      } catch (Exception e) {
        addError("checkEmails failed.");
      }
    }

    void checkFile(String project, String path, String[] lines) {
      addVerboseMsg("checking " + path);
      int num = 0;
      for (String line : lines) {
        checkLine(project, path, ++num, line);
      }
    }

    void checkFile(String project, String path, String content) {
      checkFile(project, path, content.split("\\R"));
    }

    void checkFile(String project, String path, ObjectLoader ol) {
      try {
        BufferedReader reader =
            new BufferedReader(new InputStreamReader(ol.openStream(), StandardCharsets.UTF_8));
        checkFile(project, path, reader.lines().toArray(String[]::new));
      } catch (Exception e) {
        addError("cannot open file: " + path);
      }
    }

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

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

    void addError(String msg) {
      messages.add(new CommitValidationMessage(msg, true));
    }

    String qualifiedPath(String project, String path) {
      return event.project.getName().equals(project) ? path : (project + ":" + path);
    }

    void addSyntaxError(String path, int lineNumber, String line) {
      addError("syntax: " + path + ":" + lineNumber + ": " + line);
    }

    void addMsg(String msg) {
      messages.add(new CommitValidationMessage(msg, false));
    }

    void addVerboseMsg(String msg) {
      if (verbose) {
        addMsg(msg);
      }
    }

    String normalizeChangedFilePath(String dir, String file) {
      try {
        if (file.startsWith("/")) {
          file = new File(file).getCanonicalPath();
        } else {
          file = new File("/" + dir + "/" + file).getCanonicalPath();
        }
      } catch (IOException e) {
        addError("cannot build file path " + dir + ":" + file);
      }
      return file.startsWith("/") ? file.substring(1) : file;
    }

    /**
     * Check if an included file exists and with valid syntax. An included file could be (1) in the
     * current CL, (2) in the same repository, (3) in a different repository, (4) in another CL.
     * Case (4) is not checked yet.
     */
    void checkIncludeOrFile(String project, String path, int num, String line) {
      // project is the including file's project, not necessarily the same as CL event's.
      String directive = Parser.getIncludeOrFile(line);
      String[] KPF = Parser.parseInclude(project, directive);
      if (KPF == null || KPF[1] == null || KPF[2] == null) {
        addSyntaxError(qualifiedPath(project, path), num, line);
      }
      String file = KPF[2];
      String curDir = Util.getParentDir(path);
      String repoFile = normalizeChangedFilePath(curDir, file);
      // Check each file only once.
      String key = KPF[1] + ":" + repoFile;
      if (checkedFiles.contains(key)) {
        addVerboseMsg("skip repeated include of " + key);
        return;
      }
      checkedFiles.add(key);
      if (KPF[1].equals(event.project.getName())) {
        if (allFiles.get(repoFile) != null) {
          // Case (1): included file is in current CL.
          addVerboseMsg("check changed file " + key);
          try {
            ObjectLoader ol = event.revWalk.getObjectReader().open(allFiles.get(repoFile));
            try (InputStream in = ol.openStream()) {
              if (RawText.isBinary(in)) {
                addError(path + " is a binary file"); // OWNERS files cannot be binary
                return;
              }
            }
            checkFile(KPF[1], repoFile, ol);
          } catch (Exception e) {
            addError("cannot open changed file: " + path);
          }
          return;
        }
      }
      // Included file is in repository or other CL.
      addVerboseMsg("check repo file " + key);
      String content =
          OwnersDb.getRepoFile(
              null, /* permissionBackend */
              readFiles,
              repoManager,
              null,
              null,
              KPF[1],
              event.refName,
              repoFile,
              new ArrayList<>());
      if (isNullOrEmpty(content)) { // file not found or not readable.
        addVerboseMsg("cannot find file: " + key);
        // unchecked: including-file-path : line number : source line
        addMsg("unchecked: " + qualifiedPath(project, path) + ":" + num + ": " + directive);
      } else {
        checkFile(KPF[1], repoFile, content);
      }
    }

    void checkLine(String project, String path, int lineNumber, String line) {
      String email;
      String[] owners;
      if (Parser.isComment(line) || Parser.isNoParent(line)) {
        // no email address to check
      } else if ((email = Parser.parseEmail(line)) != null) {
        collectEmail(email, project, path, lineNumber);
      } else if ((owners = Parser.parsePerFileOwners(line)) != null) {
        for (String owner : owners) {
          if (owner.startsWith("file:")) {
            // Pass the whole line, not just owner, to report any syntax error.,
            checkIncludeOrFile(project, path, lineNumber, line);
          } else if (!owner.equals(Parser.TOK_SET_NOPARENT)) {
            collectEmail(owner, project, path, lineNumber);
          }
        }
      } else if (Parser.isInclude(line)) {
        checkIncludeOrFile(project, path, lineNumber, line);
      } else {
        addSyntaxError(qualifiedPath(project, path), lineNumber, line);
      }
    }
  } // end of inner class Checker

  /** Return a map from "Path to changed file" to "ObjectId of the file". */
  private static Map<String, ObjectId> getChangedFiles(RevCommit c, RevWalk revWalk)
      throws IOException {
    final Map<String, ObjectId> content = new HashMap<>();
    visitChangedEntries(
        c,
        revWalk,
        new TreeWalkVisitor() {
          @Override
          public void onVisit(TreeWalk tw) {
            // getPathString() returns path names without leading "/"
            if (isFile(tw)) {
              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;
  }
}
