// Copyright (c) 2013 VMware, Inc. All Rights Reserved.
// 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.owners.common;

import static com.google.gerrit.entities.Patch.COMMIT_MSG;
import static com.google.gerrit.entities.Patch.MERGE_LIST;
import static com.googlesource.gerrit.owners.common.JgitWrapper.getBlobAsBytes;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimaps;
import com.google.common.collect.SetMultimap;
import com.google.common.collect.Sets;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.entities.Account;
import com.google.gerrit.entities.Account.Id;
import com.google.gerrit.entities.Patch;
import com.google.gerrit.entities.Project;
import com.google.gerrit.entities.RefNames;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.patch.DiffSummary;
import com.google.gerrit.server.patch.filediff.FileDiffOutput;
import com.google.gerrit.server.project.ProjectState;
import java.io.IOException;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.stream.Collectors;
import org.eclipse.jgit.lib.Repository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/** Calculates the owners of a patch list. */
// TODO(vspivak): provide assisted factory
public class PathOwners {

  private static final Logger log = LoggerFactory.getLogger(PathOwners.class);

  private enum MatcherLevel {
    Regular,
    Fallback,
    CatchAll;

    static MatcherLevel forMatcher(Matcher matcher) {
      return matcher instanceof GenericMatcher
          ? (matcher.path.equals(".*") ? CatchAll : Fallback)
          : Regular;
    }
  }

  private final SetMultimap<String, Account.Id> owners;

  private final SetMultimap<String, Account.Id> reviewers;

  private final Repository repository;

  private final List<Project.NameKey> parentProjectsNames;

  private final ConfigurationParser parser;

  private final Set<String> modifiedPaths;

  private final Accounts accounts;

  private final GitRepositoryManager repositoryManager;

  private Map<String, Matcher> matchers;

  private Map<String, Set<Id>> fileOwners;

  private Map<String, Set<String>> fileGroupOwners;

  private final boolean expandGroups;

  private final Optional<LabelDefinition> label;

  public PathOwners(
      Accounts accounts,
      GitRepositoryManager repositoryManager,
      Repository repository,
      List<Project.NameKey> parentProjectsNames,
      Optional<String> branchWhenEnabled,
      Map<String, FileDiffOutput> fileDiffMap,
      boolean expandGroups,
      String project,
      PathOwnersEntriesCache cache) {
    this(
        accounts,
        repositoryManager,
        repository,
        parentProjectsNames,
        branchWhenEnabled,
        getModifiedPaths(fileDiffMap),
        expandGroups,
        project,
        cache);
  }

  public PathOwners(
      Accounts accounts,
      GitRepositoryManager repositoryManager,
      Repository repository,
      List<Project.NameKey> parentProjectsNames,
      Optional<String> branchWhenEnabled,
      DiffSummary diffSummary,
      boolean expandGroups,
      String project,
      PathOwnersEntriesCache cache) {
    this(
        accounts,
        repositoryManager,
        repository,
        parentProjectsNames,
        branchWhenEnabled,
        ImmutableSet.copyOf(diffSummary.getPaths()),
        expandGroups,
        project,
        cache);
  }

  public PathOwners(
      Accounts accounts,
      GitRepositoryManager repositoryManager,
      Repository repository,
      List<Project.NameKey> parentProjectsNames,
      Optional<String> branchWhenEnabled,
      Set<String> modifiedPaths,
      boolean expandGroups,
      String project,
      PathOwnersEntriesCache cache) {
    this.repositoryManager = repositoryManager;
    this.repository = repository;
    this.parentProjectsNames = parentProjectsNames;
    this.modifiedPaths = modifiedPaths;
    this.parser = new ConfigurationParser(accounts);
    this.accounts = accounts;
    this.expandGroups = expandGroups;

    OwnersMap map =
        branchWhenEnabled
            .map(branch -> fetchOwners(project, branch, cache))
            .orElse(new OwnersMap());
    owners = Multimaps.unmodifiableSetMultimap(map.getPathOwners());
    reviewers = Multimaps.unmodifiableSetMultimap(map.getPathReviewers());
    matchers = map.getMatchers();
    fileOwners = map.getFileOwners();
    fileGroupOwners = map.getFileGroupOwners();
    label = map.getLabel();
  }
  /**
   * Returns a read only view of the paths to owners mapping.
   *
   * @return multimap of paths to owners
   */
  public SetMultimap<String, Account.Id> get() {
    return owners;
  }

  /**
   * Returns a read only view of the paths to reviewers mapping.
   *
   * @return multimap of paths to reviewers
   */
  public SetMultimap<String, Account.Id> getReviewers() {
    return reviewers;
  }

  public Map<String, Matcher> getMatchers() {
    return matchers;
  }

  public Map<String, Set<Account.Id>> getFileOwners() {
    return fileOwners;
  }

  public Map<String, Set<String>> getFileGroupOwners() {
    return fileGroupOwners;
  }

  public boolean expandGroups() {
    return expandGroups;
  }

  public Optional<LabelDefinition> getLabel() {
    return label;
  }

  public static List<Project.NameKey> getParents(ProjectState projectState) {
    return projectState.parents().stream()
        .map(ProjectState::getNameKey)
        .collect(Collectors.toList());
  }

  /**
   * Fetched the owners for the associated patch list.
   *
   * @return A structure containing matchers paths to owners
   */
  private OwnersMap fetchOwners(String project, String branch, PathOwnersEntriesCache cache) {
    OwnersMap ownersMap = new OwnersMap();
    try {
      // Using a `map` would have needed a try/catch inside the lamba, resulting in more code
      List<ReadOnlyPathOwnersEntry> parentsPathOwnersEntries =
          getPathOwnersEntries(parentProjectsNames, RefNames.REFS_CONFIG, cache);
      ReadOnlyPathOwnersEntry projectEntry =
          getPathOwnersEntryOrEmpty(project, repository, RefNames.REFS_CONFIG, cache);
      PathOwnersEntry rootEntry = getPathOwnersEntryOrNew(project, repository, branch, cache);

      Map<String, PathOwnersEntry> entries = new HashMap<>();
      PathOwnersEntry currentEntry = null;
      for (String path : modifiedPaths) {
        currentEntry =
            resolvePathEntry(
                project,
                path,
                branch,
                projectEntry,
                parentsPathOwnersEntries,
                rootEntry,
                entries,
                cache);

        // add owners and reviewers to file for matcher predicates
        ownersMap.addFileOwners(path, currentEntry.getOwners());
        ownersMap.addFileReviewers(path, currentEntry.getReviewers());
        ownersMap.addFileGroupOwners(path, currentEntry.getGroupOwners());

        // Only add the path to the OWNERS file to reduce the number of
        // entries in the result
        if (currentEntry.getOwnersPath() != null) {
          ownersMap.addPathOwners(currentEntry.getOwnersPath(), currentEntry.getOwners());
          ownersMap.addPathReviewers(currentEntry.getOwnersPath(), currentEntry.getReviewers());
        }
        ownersMap.addMatchers(currentEntry.getMatchers());
      }

      // We need to only keep matchers that match files in the patchset
      Map<String, Matcher> matchers = ownersMap.getMatchers();
      if (matchers.size() > 0) {
        HashMap<String, Matcher> newMatchers = Maps.newHashMap();
        // extra loop
        for (String path : modifiedPaths) {
          processMatcherPerPath(matchers, newMatchers, path, ownersMap);
        }
        if (matchers.size() != newMatchers.size()) {
          ownersMap.setMatchers(newMatchers);
        }
      }
      ownersMap.setLabel(Optional.ofNullable(currentEntry).flatMap(PathOwnersEntry::getLabel));
      return ownersMap;
    } catch (IOException | ExecutionException e) {
      log.warn("Invalid OWNERS file", e);
      return ownersMap;
    }
  }

  private List<ReadOnlyPathOwnersEntry> getPathOwnersEntries(
      List<Project.NameKey> projectNames, String branch, PathOwnersEntriesCache cache)
      throws IOException, ExecutionException {
    ImmutableList.Builder<ReadOnlyPathOwnersEntry> pathOwnersEntries = ImmutableList.builder();
    for (Project.NameKey projectName : projectNames) {
      try (Repository repo = repositoryManager.openRepository(projectName)) {
        pathOwnersEntries =
            pathOwnersEntries.add(
                getPathOwnersEntryOrEmpty(projectName.get(), repo, branch, cache));
      }
    }
    return pathOwnersEntries.build();
  }

  private ReadOnlyPathOwnersEntry getPathOwnersEntryOrEmpty(
      String project, Repository repo, String branch, PathOwnersEntriesCache cache)
      throws ExecutionException {
    return getPathOwnersEntry(project, repo, branch, cache)
        .map(v -> (ReadOnlyPathOwnersEntry) v)
        .orElse(PathOwnersEntry.EMPTY);
  }

  private PathOwnersEntry getPathOwnersEntryOrNew(
      String project, Repository repo, String branch, PathOwnersEntriesCache cache)
      throws ExecutionException {
    return getPathOwnersEntry(project, repo, branch, cache).orElseGet(PathOwnersEntry::new);
  }

  private Optional<PathOwnersEntry> getPathOwnersEntry(
      String project, Repository repo, String branch, PathOwnersEntriesCache cache)
      throws ExecutionException {
    String rootPath = "OWNERS";
    return cache
        .get(project, branch, rootPath, () -> getOwnersConfig(repo, rootPath, branch))
        .map(
            conf ->
                new PathOwnersEntry(
                    rootPath,
                    conf,
                    accounts,
                    Optional.empty(),
                    Collections.emptySet(),
                    Collections.emptySet(),
                    Collections.emptySet(),
                    Collections.emptySet()));
  }

  private void processMatcherPerPath(
      Map<String, Matcher> fullMatchers,
      HashMap<String, Matcher> newMatchers,
      String path,
      OwnersMap ownersMap) {

    Map<MatcherLevel, List<Matcher>> matchersByLevel =
        fullMatchers.values().stream().collect(Collectors.groupingBy(MatcherLevel::forMatcher));
    if (findAndAddMatchers(
        newMatchers, path, ownersMap, matchersByLevel.get(MatcherLevel.Regular))) {
      return;
    }

    if (findAndAddMatchers(
        newMatchers, path, ownersMap, matchersByLevel.get(MatcherLevel.Fallback))) {
      return;
    }

    findAndAddMatchers(newMatchers, path, ownersMap, matchersByLevel.get(MatcherLevel.CatchAll));
  }

  private boolean findAndAddMatchers(
      HashMap<String, Matcher> newMatchers,
      String path,
      OwnersMap ownersMap,
      @Nullable List<Matcher> matchers) {
    if (matchers == null) {
      return false;
    }

    boolean matchingFound = false;

    for (Matcher matcher : matchers) {
      if (matcher.matches(path)) {
        newMatchers.put(matcher.getPath(), matcher);
        ownersMap.addFileOwners(path, matcher.getOwners());
        ownersMap.addFileGroupOwners(path, matcher.getGroupOwners());
        ownersMap.addFileReviewers(path, matcher.getReviewers());
        matchingFound = true;
      }
    }
    return matchingFound;
  }

  private PathOwnersEntry resolvePathEntry(
      String project,
      String path,
      String branch,
      ReadOnlyPathOwnersEntry projectEntry,
      List<ReadOnlyPathOwnersEntry> parentsPathOwnersEntries,
      PathOwnersEntry rootEntry,
      Map<String, PathOwnersEntry> entries,
      PathOwnersEntriesCache cache)
      throws ExecutionException {
    String[] parts = path.split("/");
    PathOwnersEntry currentEntry = rootEntry;
    StringBuilder builder = new StringBuilder();

    // Inherit from Project if OWNER in root enables inheritance
    calculateCurrentEntry(rootEntry, projectEntry, currentEntry);

    // Inherit from Parent Project if OWNER in Project enables inheritance
    for (ReadOnlyPathOwnersEntry parentPathOwnersEntry : parentsPathOwnersEntries) {
      calculateCurrentEntry(projectEntry, parentPathOwnersEntry, currentEntry);
    }

    // Iterate through the parent paths, not including the file name
    // itself
    for (int i = 0; i < parts.length - 1; i++) {
      String part = parts[i];
      builder.append(part).append("/");
      String partial = builder.toString();

      // Skip if we already parsed this path
      if (entries.containsKey(partial)) {
        currentEntry = entries.get(partial);
      } else {
        String ownersPath = partial + "OWNERS";
        PathOwnersEntry pathFallbackEntry = currentEntry;
        currentEntry =
            cache
                .get(
                    project,
                    branch,
                    ownersPath,
                    () -> getOwnersConfig(repository, ownersPath, branch))
                .map(
                    c -> {
                      Optional<LabelDefinition> label = pathFallbackEntry.getLabel();
                      final Set<Id> owners = pathFallbackEntry.getOwners();
                      final Set<Id> reviewers = pathFallbackEntry.getReviewers();
                      Collection<Matcher> inheritedMatchers =
                          pathFallbackEntry.getMatchers().values();
                      Set<String> groupOwners = pathFallbackEntry.getGroupOwners();
                      return new PathOwnersEntry(
                          ownersPath,
                          c,
                          accounts,
                          label,
                          owners,
                          reviewers,
                          inheritedMatchers,
                          groupOwners);
                    })
                .orElse(pathFallbackEntry);
        entries.put(partial, currentEntry);
      }
    }
    return currentEntry;
  }

  private void calculateCurrentEntry(
      ReadOnlyPathOwnersEntry rootEntry,
      ReadOnlyPathOwnersEntry projectEntry,
      PathOwnersEntry currentEntry) {
    if (rootEntry.isInherited()) {
      for (Matcher matcher : projectEntry.getMatchers().values()) {
        if (!currentEntry.hasMatcher(matcher.getPath())) {
          currentEntry.addMatcher(matcher);
        }
      }
      if (currentEntry.getOwners().isEmpty()) {
        currentEntry.setOwners(projectEntry.getOwners());
      }
      if (currentEntry.getOwnersPath() == null) {
        currentEntry.setOwnersPath(projectEntry.getOwnersPath());
      }
      if (currentEntry.getLabel().isEmpty()) {
        currentEntry.setLabel(projectEntry.getLabel());
      }
    }
  }

  /**
   * Parses the diff list for any paths that were modified.
   *
   * @return set of modified paths.
   */
  private static Set<String> getModifiedPaths(Map<String, FileDiffOutput> patchList) {
    Set<String> paths = Sets.newHashSet();
    for (Map.Entry<String, FileDiffOutput> patch : patchList.entrySet()) {
      // Ignore commit message and Merge List
      String newName = patch.getKey();
      if (!COMMIT_MSG.equals(newName) && !MERGE_LIST.equals(newName)) {
        paths.add(newName);

        // If a file was moved then we need approvals for old and new
        // path
        if (patch.getValue().changeType() == Patch.ChangeType.RENAMED) {
          paths.add(patch.getValue().oldPath().get());
        }
      }
    }
    return paths;
  }

  /**
   * Returns the parsed FileOwnersConfig file for the given path if it exists.
   *
   * @param ownersPath path to OWNERS file in the git repo
   * @return config or null if it doesn't exist
   * @throws IOException
   */
  private Optional<OwnersConfig> getOwnersConfig(Repository repo, String ownersPath, String branch)
      throws IOException {
    return getBlobAsBytes(repo, branch, ownersPath).flatMap(parser::getOwnersConfig);
  }
}
