// 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.restapi.change;

import com.google.common.collect.ListMultimap;
import com.google.common.collect.MultimapBuilder;
import com.google.gerrit.entities.Project;
import com.google.gerrit.extensions.common.BlameInfo;
import com.google.gerrit.extensions.common.RangeInfo;
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.server.change.FileResource;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.git.InMemoryInserter;
import com.google.gerrit.server.patch.AutoMerger;
import com.google.gerrit.server.project.InvalidChangeOperationException;
import com.google.gitiles.blame.cache.BlameCache;
import com.google.gitiles.blame.cache.Region;
import com.google.inject.Inject;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectReader;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;
import org.kohsuke.args4j.Option;

public class GetBlame implements RestReadView<FileResource> {

  private final GitRepositoryManager repoManager;
  private final BlameCache blameCache;
  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, AutoMerger autoMerger) {
    this.repoManager = repoManager;
    this.blameCache = blameCache;
    this.autoMerger = autoMerger;
  }

  public GetBlame setBase(boolean base) {
    this.base = base;
    return this;
  }

  @Override
  public Response<List<BlameInfo>> apply(FileResource resource)
      throws RestApiException, IOException, InvalidChangeOperationException {
    Project.NameKey project = resource.getRevision().getChange().getProject();
    try (Repository repository = repoManager.openRepository(project);
        InMemoryInserter ins = new InMemoryInserter(repository);
        ObjectReader reader = ins.newReader();
        RevWalk revWalk = new RevWalk(reader)) {
      String refName =
          resource.getRevision().getEdit().isPresent()
              ? resource.getRevision().getEdit().get().getRefName()
              : resource.getRevision().getPatchSet().refName();

      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().fileName();

      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.lookupFromGitOrMergeInMemory(repository, revWalk, ins, revCommit);
        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 =
        MultimapBuilder.hashKeys().arrayListValues().build();
    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;
  }
}
