// Copyright (C) 2015 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.google.gerrit.server.change;

import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.ListMultimap;
import com.google.gerrit.extensions.common.BlameInfo;
import com.google.gerrit.extensions.common.RangeInfo;
import com.google.gerrit.extensions.restapi.BadRequestException;
import com.google.gerrit.extensions.restapi.CacheControl;
import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
import com.google.gerrit.extensions.restapi.Response;
import com.google.gerrit.extensions.restapi.RestApiException;
import com.google.gerrit.extensions.restapi.RestReadView;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.git.MergeUtil;
import com.google.gerrit.server.patch.AutoMerger;
import com.google.gerrit.server.project.InvalidChangeOperationException;
import com.google.gitiles.blame.BlameCache;
import com.google.gitiles.blame.Region;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;

import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectInserter;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.merge.ThreeWayMergeStrategy;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;
import org.kohsuke.args4j.Option;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

public class GetBlame implements RestReadView<FileResource> {

  private final GitRepositoryManager repoManager;
  private final BlameCache blameCache;
  private final boolean allowBlame;
  private final ThreeWayMergeStrategy mergeStrategy;
  private final AutoMerger autoMerger;

  @Option(name = "--base", aliases = {"-b"},
    usage = "whether to load the blame of the base revision (the direct"
      + " parent of the change) instead of the change")
  private boolean base;

  @Inject
  GetBlame(GitRepositoryManager repoManager,
      BlameCache blameCache,
      @GerritServerConfig Config cfg,
      AutoMerger autoMerger) {
    this.repoManager = repoManager;
    this.blameCache = blameCache;
    this.mergeStrategy = MergeUtil.getMergeStrategy(cfg);
    this.autoMerger = autoMerger;
    allowBlame = cfg.getBoolean("change", "allowBlame", true);
  }

  @Override
  public Response<List<BlameInfo>> apply(FileResource resource)
      throws RestApiException, OrmException, IOException,
      InvalidChangeOperationException {
    if (!allowBlame) {
      throw new BadRequestException("blame is disabled");
    }

    Project.NameKey project = resource.getRevision().getChange().getProject();
    try (Repository repository = repoManager.openRepository(project);
        ObjectInserter ins = repository.newObjectInserter();
        RevWalk revWalk = new RevWalk(ins.newReader())) {
      String refName = resource.getRevision().getEdit().isPresent()
          ? resource.getRevision().getEdit().get().getRefName()
          : resource.getRevision().getPatchSet().getRefName();

      Ref ref = repository.findRef(refName);
      if (ref == null) {
        throw new ResourceNotFoundException("unknown ref " + refName);
      }
      ObjectId objectId = ref.getObjectId();
      RevCommit revCommit = revWalk.parseCommit(objectId);
      RevCommit[] parents = revCommit.getParents();

      String path = resource.getPatchKey().getFileName();

      List<BlameInfo> result;
      if (!base) {
        result = blame(revCommit, path, repository, revWalk);

      } else if (parents.length == 0) {
        throw new ResourceNotFoundException("Initial commit doesn't have base");

      } else if (parents.length == 1) {
        result = blame(parents[0], path, repository, revWalk);

      } else if (parents.length == 2) {
        ObjectId automerge = autoMerger.merge(repository, revWalk, ins,
            revCommit, mergeStrategy);
        result = blame(automerge, path, repository, revWalk);

      } else {
        throw new ResourceNotFoundException(
            "Cannot generate blame for merge commit with more than 2 parents");
      }

      Response<List<BlameInfo>> r = Response.ok(result);
      if (resource.isCacheable()) {
        r.caching(CacheControl.PRIVATE(7, TimeUnit.DAYS));
      }
      return r;
    }
  }

  private List<BlameInfo> blame(ObjectId id, String path,
      Repository repository, RevWalk revWalk) throws IOException {
    ListMultimap<BlameInfo, RangeInfo> ranges = ArrayListMultimap.create();
    List<BlameInfo> result = new ArrayList<>();
    if (blameCache.findLastCommit(repository, id, path) == null) {
      return result;
    }

    List<Region> blameRegions = blameCache.get(repository, id, path);
    int from = 1;
    for (Region region : blameRegions) {
      RevCommit commit = revWalk.parseCommit(region.getSourceCommit());
      BlameInfo blameInfo = toBlameInfo(commit, region.getSourceAuthor());
      ranges.put(blameInfo, new RangeInfo(from, from + region.getCount() - 1));
      from += region.getCount();
    }

    for (BlameInfo key : ranges.keySet()) {
      key.ranges = ranges.get(key);
      result.add(key);
    }
    return result;
  }

  private static BlameInfo toBlameInfo(RevCommit commit,
      PersonIdent sourceAuthor) {
    BlameInfo blameInfo = new BlameInfo();
    blameInfo.author = sourceAuthor.getName();
    blameInfo.id = commit.getName();
    blameInfo.commitMsg = commit.getFullMessage();
    blameInfo.time = commit.getCommitTime();
    return blameInfo;
  }
}
