// Copyright (C) 2008 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.git;

import com.google.gerrit.client.reviewdb.Account;
import com.google.gerrit.client.reviewdb.AccountExternalId;
import com.google.gerrit.client.reviewdb.Patch;
import com.google.gerrit.client.reviewdb.PatchContent;
import com.google.gerrit.client.reviewdb.PatchSet;
import com.google.gerrit.client.reviewdb.PatchSetAncestor;
import com.google.gerrit.client.reviewdb.PatchSetInfo;
import com.google.gerrit.client.reviewdb.RevId;
import com.google.gerrit.client.reviewdb.ReviewDb;
import com.google.gerrit.client.reviewdb.UserIdentity;
import com.google.gwtorm.client.OrmDuplicateKeyException;
import com.google.gwtorm.client.OrmException;
import com.google.gwtorm.client.Transaction;

import org.spearce.jgit.lib.Commit;
import org.spearce.jgit.lib.Constants;
import org.spearce.jgit.lib.ObjectId;
import org.spearce.jgit.lib.ObjectWriter;
import org.spearce.jgit.lib.PersonIdent;
import org.spearce.jgit.lib.Repository;
import org.spearce.jgit.lib.Tree;
import org.spearce.jgit.patch.CombinedFileHeader;
import org.spearce.jgit.patch.FileHeader;
import org.spearce.jgit.revwalk.RevCommit;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

/** Imports a {@link PatchSet} from a {@link Commit}. */
public class PatchSetImporter {
  private final ReviewDb db;
  private final Repository repo;
  private final RevCommit src;
  private final PatchSet dst;
  private final boolean isNew;
  private Transaction txn;
  private org.spearce.jgit.patch.Patch gitpatch;

  private PatchSetInfo info;
  private boolean infoIsNew;

  private final MessageDigest contentmd = Constants.newMessageDigest();
  private final Map<String, Patch> patchExisting = new HashMap<String, Patch>();
  private final List<Patch> patchInsert = new ArrayList<Patch>();
  private final List<Patch> patchUpdate = new ArrayList<Patch>();
  private final Map<PatchContent.Key, String> content =
      new HashMap<PatchContent.Key, String>();

  private final Map<Integer, PatchSetAncestor> ancestorExisting =
      new HashMap<Integer, PatchSetAncestor>();
  private final List<PatchSetAncestor> ancestorInsert =
      new ArrayList<PatchSetAncestor>();
  private final List<PatchSetAncestor> ancestorUpdate =
      new ArrayList<PatchSetAncestor>();

  public PatchSetImporter(final ReviewDb dstDb, final Repository srcRepo,
      final RevCommit srcCommit, final PatchSet dstPatchSet,
      final boolean isNewPatchSet) {
    db = dstDb;
    repo = srcRepo;
    src = srcCommit;
    dst = dstPatchSet;
    isNew = isNewPatchSet;
  }

  public void setTransaction(final Transaction t) {
    txn = t;
  }

  public PatchSetInfo getPatchSetInfo() {
    return info;
  }

  public void run() throws IOException, OrmException {
    gitpatch = readGitPatch();

    dst.setRevision(toRevId(src));

    if (!isNew) {
      // If we aren't a new patch set then we need to load the existing
      // files so we can update or delete them if there are corrections.
      //
      info = db.patchSetInfo().get(dst.getId());
      for (final Patch p : db.patches().byPatchSet(dst.getId())) {
        patchExisting.put(p.getFileName(), p);
      }
      for (final PatchSetAncestor a : db.patchSetAncestors().ancestorsOf(
          dst.getId())) {
        ancestorExisting.put(a.getPosition(), a);
      }
    }

    importInfo();
    for (final FileHeader fh : gitpatch.getFiles()) {
      importFile(fh);
    }

    // Ensure all content entities exist
    //
    putPatchContent();

    final boolean auto = txn == null;
    if (auto) {
      txn = db.beginTransaction();
    }
    if (isNew) {
      db.patchSets().insert(Collections.singleton(dst), txn);
    }
    if (infoIsNew) {
      db.patchSetInfo().insert(Collections.singleton(info), txn);
    } else {
      db.patchSetInfo().update(Collections.singleton(info), txn);
    }
    db.patches().insert(patchInsert, txn);
    db.patchSetAncestors().insert(ancestorInsert, txn);
    if (!isNew) {
      db.patches().update(patchUpdate, txn);
      db.patches().delete(patchExisting.values(), txn);

      db.patchSetAncestors().update(ancestorUpdate, txn);
      db.patchSetAncestors().delete(ancestorExisting.values(), txn);
    }
    if (auto) {
      txn.commit();
      txn = null;
    }
  }

  private void importInfo() throws OrmException {
    if (info == null) {
      info = new PatchSetInfo(dst.getId());
      infoIsNew = true;
    }

    info.setSubject(src.getShortMessage());
    info.setMessage(src.getFullMessage());
    info.setAuthor(toUserIdentity(src.getAuthorIdent()));
    info.setCommitter(toUserIdentity(src.getCommitterIdent()));

    for (int p = 0; p < src.getParentCount(); p++) {
      PatchSetAncestor a = ancestorExisting.remove(p + 1);
      if (a == null) {
        a = new PatchSetAncestor(new PatchSetAncestor.Id(dst.getId(), p + 1));
        ancestorInsert.add(a);
      } else {
        ancestorUpdate.add(a);
      }
      a.setAncestorRevision(toRevId(src.getParent(p)));
    }
  }

  private UserIdentity toUserIdentity(final PersonIdent who)
      throws OrmException {
    final UserIdentity u = new UserIdentity();
    u.setName(who.getName());
    u.setEmail(who.getEmailAddress());
    u.setDate(new Timestamp(who.getWhen().getTime()));
    u.setTimeZone(who.getTimeZoneOffset());

    if (u.getEmail() != null) {
      // If only one account has access to this email address, select it
      // as the identity of the user.
      //
      final Set<Account.Id> a = new HashSet<Account.Id>();
      for (final AccountExternalId e : db.accountExternalIds().byEmailAddress(
          u.getEmail())) {
        a.add(e.getAccountId());
      }
      if (a.size() == 1) {
        u.setAccount(a.iterator().next());
      }
    }

    return u;
  }

  private void importFile(final FileHeader fh)
      throws UnsupportedEncodingException {
    final String path;
    if (fh.getChangeType() == FileHeader.ChangeType.DELETE) {
      path = fh.getOldName();
    } else {
      path = fh.getNewName();
    }

    Patch p = patchExisting.remove(path);
    if (p == null) {
      p = new Patch(new Patch.Key(dst.getId(), path));
      patchInsert.add(p);
    } else {
      p.setSourceFileName(null);
      patchUpdate.add(p);
    }

    // Convert the ChangeType
    //
    if (fh.getChangeType() == FileHeader.ChangeType.ADD) {
      p.setChangeType(Patch.ChangeType.ADD);

    } else if (fh.getChangeType() == FileHeader.ChangeType.MODIFY) {
      p.setChangeType(Patch.ChangeType.MODIFIED);

    } else if (fh.getChangeType() == FileHeader.ChangeType.DELETE) {
      p.setChangeType(Patch.ChangeType.DELETED);

    } else if (fh.getChangeType() == FileHeader.ChangeType.RENAME) {
      p.setChangeType(Patch.ChangeType.RENAMED);
      p.setSourceFileName(fh.getOldName());

    } else if (fh.getChangeType() == FileHeader.ChangeType.COPY) {
      p.setChangeType(Patch.ChangeType.COPIED);
      p.setSourceFileName(fh.getOldName());
    }

    // Convert the PatchType
    //
    if (fh instanceof CombinedFileHeader) {
      p.setPatchType(Patch.PatchType.N_WAY);

    } else if (fh.getPatchType() == FileHeader.PatchType.GIT_BINARY) {
      p.setPatchType(Patch.PatchType.BINARY);

    } else if (fh.getPatchType() == FileHeader.PatchType.BINARY) {
      p.setPatchType(Patch.PatchType.BINARY);
    }

    String contentStr = fh.getScriptText();
    if (p.getPatchType() != Patch.PatchType.BINARY
        && contentStr.indexOf('\0') >= 0) {
      // Its really binary, but Git couldn't see the nul early enough
      // to realize its binary, and instead produced the diff. Some
      // databases (PostgreSQL) won't allow us to store a nul into a
      // text field. Force it to be a binary; it really should have
      // been that in the first place.
      //
      p.setPatchType(Patch.PatchType.BINARY);
      final int lfatat = contentStr.indexOf("\n@@");
      final StringBuilder b = new StringBuilder();
      b.append(contentStr.substring(0, lfatat + 1));
      b.append("Binary files ");
      b.append(path);
      b.append(" and ");
      b.append(path);
      b.append(" differ\n");
      contentStr = b.toString();
    }

    // Hash the content.
    //
    contentmd.reset();
    contentmd.update(contentStr.getBytes("UTF-8"));
    final PatchContent.Key contentKey =
        new PatchContent.Key(ObjectId.fromRaw(contentmd.digest()).name());
    content.put(contentKey, contentStr);
    p.setContent(contentKey);
  }

  private void putPatchContent() throws OrmException {
    for (final Iterator<Map.Entry<PatchContent.Key, String>> i =
        content.entrySet().iterator(); i.hasNext();) {
      final Map.Entry<PatchContent.Key, String> e = i.next();
      final PatchContent pc = new PatchContent(e.getKey(), e.getValue());
      try {
        db.patchContents().insert(Collections.singleton(pc));
      } catch (OrmDuplicateKeyException err) {
        // Should be fine; someone else beat us to the insertion.
      }
      i.remove();
    }
  }

  private static RevId toRevId(final RevCommit src) {
    return new RevId(src.getId().name());
  }

  private org.spearce.jgit.patch.Patch readGitPatch() throws IOException {
    final List<String> args = new ArrayList<String>();
    args.add("git");
    args.add("--git-dir=.");
    args.add("diff-tree");
    args.add("-M");
    args.add("--full-index");

    switch (src.getParentCount()) {
      case 0:
        args.add("--unified=5");
        args.add(new ObjectWriter(repo).writeTree(new Tree(repo)).name());
        args.add(src.getTree().getId().name());
        break;
      case 1:
        args.add("--unified=5");
        args.add(src.getParent(0).getId().name());
        args.add(src.getId().name());
        break;
      default:
        args.add("--cc");
        args.add(src.getId().name());
        break;
    }

    final Process proc =
        Runtime.getRuntime().exec(args.toArray(new String[args.size()]), null,
            repo.getDirectory());
    try {
      final org.spearce.jgit.patch.Patch p = new org.spearce.jgit.patch.Patch();
      proc.getOutputStream().close();
      proc.getErrorStream().close();
      p.parse(proc.getInputStream());
      proc.getInputStream().close();
      return p;
    } finally {
      try {
        if (proc.waitFor() != 0) {
          throw new IOException("git diff-tree exited abnormally");
        }
      } catch (InterruptedException ie) {
      }
    }
  }
}
