// 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.Maps;
import com.google.common.collect.Multimaps;
import com.google.common.collect.SetMultimap;
import com.google.common.collect.Sets;
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.PatchList;
import com.google.gerrit.server.patch.PatchListEntry;
import java.io.IOException;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
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 final SetMultimap<String, Account.Id> owners;

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

  private final Repository repository;

  private final Optional<Project.NameKey> maybeParentRepo;

  private final PatchList patchList;

  private final ConfigurationParser parser;

  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;

  public PathOwners(
      Accounts accounts,
      GitRepositoryManager repositoryManager,
      Repository repository,
      Optional<Project.NameKey> maybeParentRepo,
      Optional<String> branchWhenEnabled,
      PatchList patchList,
      boolean expandGroups) {
    this.repositoryManager = repositoryManager;
    this.repository = repository;
    this.maybeParentRepo = maybeParentRepo;
    this.patchList = patchList;
    this.parser = new ConfigurationParser(accounts);
    this.accounts = accounts;
    this.expandGroups = expandGroups;

    OwnersMap map = branchWhenEnabled.map(branch -> fetchOwners(branch)).orElse(new OwnersMap());
    owners = Multimaps.unmodifiableSetMultimap(map.getPathOwners());
    reviewers = Multimaps.unmodifiableSetMultimap(map.getPathReviewers());
    matchers = map.getMatchers();
    fileOwners = map.getFileOwners();
    fileGroupOwners = map.getFileGroupOwners();
  }

  /**
   * 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;
  }

  /**
   * Fetched the owners for the associated patch list.
   *
   * @return A structure containing matchers paths to owners
   */
  private OwnersMap fetchOwners(String branch) {
    OwnersMap ownersMap = new OwnersMap();
    try {
      // Using a `map` would have needed a try/catch inside the lamba, resulting in more code
      Optional<PathOwnersEntry> maybeParentPathOwnersEntry =
          maybeParentRepo.isPresent()
              ? Optional.of(getPathOwnersEntry(maybeParentRepo.get(), RefNames.REFS_CONFIG))
              : Optional.empty();
      PathOwnersEntry projectEntry = getPathOwnersEntry(repository, RefNames.REFS_CONFIG);
      PathOwnersEntry rootEntry = getPathOwnersEntry(repository, branch);

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

        // 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);
        }
      }
      return ownersMap;
    } catch (IOException e) {
      log.warn("Invalid OWNERS file", e);
      return ownersMap;
    }
  }

  private PathOwnersEntry getPathOwnersEntry(Project.NameKey projectName, String branch)
      throws IOException {
    try (Repository repo = repositoryManager.openRepository(projectName)) {
      return getPathOwnersEntry(repo, branch);
    }
  }

  private PathOwnersEntry getPathOwnersEntry(Repository repo, String branch) throws IOException {
    String rootPath = "OWNERS";
    return getOwnersConfig(repo, rootPath, branch)
        .map(
            conf ->
                new PathOwnersEntry(
                    rootPath,
                    conf,
                    accounts,
                    Collections.emptySet(),
                    Collections.emptySet(),
                    Collections.emptySet(),
                    Collections.emptySet()))
        .orElse(new PathOwnersEntry());
  }

  private void processMatcherPerPath(
      Map<String, Matcher> fullMatchers,
      HashMap<String, Matcher> newMatchers,
      String path,
      OwnersMap ownersMap) {
    Iterator<Matcher> it = fullMatchers.values().iterator();
    while (it.hasNext()) {
      Matcher matcher = it.next();
      if (matcher.matches(path)) {
        newMatchers.put(matcher.getPath(), matcher);
        ownersMap.addFileOwners(path, matcher.getOwners());
        ownersMap.addFileReviewers(path, matcher.getReviewers());
      }
    }
  }

  private PathOwnersEntry resolvePathEntry(
      String path,
      String branch,
      PathOwnersEntry projectEntry,
      Optional<PathOwnersEntry> maybeParentPathOwnersEntry,
      PathOwnersEntry rootEntry,
      Map<String, PathOwnersEntry> entries)
      throws IOException {
    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
    if (maybeParentPathOwnersEntry.isPresent()) {
      calculateCurrentEntry(projectEntry, maybeParentPathOwnersEntry.get(), 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";
        Optional<OwnersConfig> conf = getOwnersConfig(repository, ownersPath, branch);
        final Set<Id> owners = currentEntry.getOwners();
        final Set<Id> reviewers = currentEntry.getReviewers();
        Collection<Matcher> inheritedMatchers = currentEntry.getMatchers().values();
        Set<String> groupOwners = currentEntry.getGroupOwners();
        currentEntry =
            conf.map(
                    c ->
                        new PathOwnersEntry(
                            ownersPath,
                            c,
                            accounts,
                            owners,
                            reviewers,
                            inheritedMatchers,
                            groupOwners))
                .orElse(currentEntry);
        entries.put(partial, currentEntry);
      }
    }
    return currentEntry;
  }

  private void calculateCurrentEntry(
      PathOwnersEntry rootEntry, PathOwnersEntry 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());
      }
    }
  }

  /**
   * Parses the patch list for any paths that were modified.
   *
   * @return set of modified paths.
   */
  private Set<String> getModifiedPaths() {
    Set<String> paths = Sets.newHashSet();
    for (PatchListEntry patch : patchList.getPatches()) {
      // Ignore commit message and Merge List
      String newName = patch.getNewName();
      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.getChangeType() == Patch.ChangeType.RENAMED) {
          paths.add(patch.getOldName());
        }
      }
    }
    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);
  }
}
