// Copyright (C) 2009 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.patch;

import static com.google.gerrit.client.data.PatchScriptSettings.Whitespace.IGNORE_NONE;

import com.google.gerrit.client.data.PatchScriptSettings.Whitespace;
import com.google.gerrit.client.reviewdb.Change;
import com.google.gerrit.client.reviewdb.PatchSet;
import com.google.gerrit.client.reviewdb.Project;
import com.google.gerrit.git.GitRepositoryManager;
import com.google.gerrit.server.cache.Cache;
import com.google.gerrit.server.cache.CacheModule;
import com.google.gerrit.server.cache.EvictionPolicy;
import com.google.gerrit.server.cache.SelfPopulatingCache;
import com.google.inject.Inject;
import com.google.inject.Module;
import com.google.inject.Singleton;
import com.google.inject.TypeLiteral;
import com.google.inject.name.Named;

import org.spearce.jgit.errors.IncorrectObjectTypeException;
import org.spearce.jgit.errors.MissingObjectException;
import org.spearce.jgit.lib.AnyObjectId;
import org.spearce.jgit.lib.ObjectId;
import org.spearce.jgit.lib.ObjectWriter;
import org.spearce.jgit.lib.Repository;
import org.spearce.jgit.revwalk.RevCommit;
import org.spearce.jgit.revwalk.RevWalk;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

/** Provides a cached list of {@link PatchListEntry}. */
@Singleton
public class PatchListCacheImpl implements PatchListCache {
  private static final String CACHE_NAME = "diff";

  public static Module module() {
    return new CacheModule() {
      @Override
      protected void configure() {
        final TypeLiteral<Cache<PatchListKey, PatchList>> type =
            new TypeLiteral<Cache<PatchListKey, PatchList>>() {};
        disk(type, CACHE_NAME) //
            .memoryLimit(128) // very large items, cache only a few
            .evictionPolicy(EvictionPolicy.LRU) // prefer most recent
        ;
        bind(PatchListCacheImpl.class);
        bind(PatchListCache.class).to(PatchListCacheImpl.class);
      }
    };
  }

  private final GitRepositoryManager repoManager;
  private final SelfPopulatingCache<PatchListKey, PatchList> self;

  @Inject
  PatchListCacheImpl(final GitRepositoryManager grm,
      @Named(CACHE_NAME) final Cache<PatchListKey, PatchList> raw) {
    repoManager = grm;
    self = new SelfPopulatingCache<PatchListKey, PatchList>(raw) {
      @Override
      protected PatchList createEntry(final PatchListKey key) throws Exception {
        return compute(key);
      }
    };
  }

  public PatchList get(final PatchListKey key) {
    return self.get(key);
  }

  public PatchList get(final Change change, final PatchSet patchSet) {
    return get(change, patchSet, IGNORE_NONE);
  }

  public PatchList get(final Change change, final PatchSet patchSet,
      final Whitespace whitespace) {
    final Project.NameKey projectKey = change.getProject();
    final ObjectId a = null;
    final ObjectId b = ObjectId.fromString(patchSet.getRevision().get());
    return get(new PatchListKey(projectKey, a, b, whitespace));
  }

  private PatchList compute(final PatchListKey key)
      throws MissingObjectException, IncorrectObjectTypeException, IOException {
    final Repository repo = repoManager.openRepository(key.projectKey.get());
    try {
      return readPatchList(key, repo);
    } finally {
      repo.close();
    }
  }

  private PatchList readPatchList(final PatchListKey key, final Repository repo)
      throws IOException {
    final RevCommit b = new RevWalk(repo).parseCommit(key.getNewId());
    final AnyObjectId a = aFor(key, repo, b);

    final List<String> args = new ArrayList<String>();
    args.add("git");
    args.add("--git-dir=.");
    args.add("diff-tree");
    args.add("-M");
    switch (key.getWhitespace()) {
      case IGNORE_NONE:
        break;
      case IGNORE_SPACE_AT_EOL:
        args.add("--ignore-space-at-eol");
        break;
      case IGNORE_SPACE_CHANGE:
        args.add("--ignore-space-change");
        break;
      case IGNORE_ALL_SPACE:
        args.add("--ignore-all-space");
        break;
      default:
        throw new IOException("Unsupported whitespace " + key.getWhitespace());
    }
    if (a == null /* want combined diff */) {
      args.add("--cc");
      args.add(b.name());
    } else {
      args.add("--unified=1");
      args.add(a.name());
      args.add(b.name());
    }

    final org.spearce.jgit.patch.Patch p = new org.spearce.jgit.patch.Patch();
    final Process diffProcess = exec(repo, args);
    try {
      diffProcess.getOutputStream().close();
      diffProcess.getErrorStream().close();

      final InputStream in = diffProcess.getInputStream();
      try {
        p.parse(in);
      } finally {
        in.close();
      }
    } finally {
      try {
        final int rc = diffProcess.waitFor();
        if (rc != 0) {
          throw new IOException("git diff-tree exited abnormally: " + rc);
        }
      } catch (InterruptedException ie) {
      }
    }

    final int cnt = p.getFiles().size();
    final PatchListEntry[] entries = new PatchListEntry[cnt];
    for (int i = 0; i < cnt; i++) {
      entries[i] = new PatchListEntry(p.getFiles().get(i));
    }
    return new PatchList(a, b, entries);
  }

  private static AnyObjectId aFor(final PatchListKey key,
      final Repository repo, final RevCommit b) throws IOException {
    if (key.getOldId() != null) {
      return key.getOldId();
    }

    switch (b.getParentCount()) {
      case 0:
        return emptyTree(repo);
      case 1:
        return b.getParent(0);
      default:
        // merge commit, return null to force combined diff behavior
        return null;
    }
  }

  private static Process exec(final Repository repo, final List<String> args)
      throws IOException {
    final String[] argv = args.toArray(new String[args.size()]);
    return Runtime.getRuntime().exec(argv, null, repo.getDirectory());
  }

  private static ObjectId emptyTree(final Repository repo) throws IOException {
    return new ObjectWriter(repo).writeCanonicalTree(new byte[0]);
  }
}
