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

import com.google.gerrit.reviewdb.client.Branch;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.client.SubmoduleSubscription;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.GerritPersonIdent;
import com.google.gerrit.server.config.CanonicalWebUrl;
import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
import com.google.gerrit.server.util.SubmoduleSectionParser;
import com.google.gwtorm.server.OrmException;
import com.google.gwtorm.server.SchemaFactory;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.assistedinject.Assisted;

import org.eclipse.jgit.dircache.DirCache;
import org.eclipse.jgit.dircache.DirCacheBuilder;
import org.eclipse.jgit.dircache.DirCacheEditor;
import org.eclipse.jgit.dircache.DirCacheEditor.PathEdit;
import org.eclipse.jgit.dircache.DirCacheEntry;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.errors.IncorrectObjectTypeException;
import org.eclipse.jgit.errors.MissingObjectException;
import org.eclipse.jgit.lib.BlobBasedConfig;
import org.eclipse.jgit.lib.CommitBuilder;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.FileMode;
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.RefUpdate;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.treewalk.TreeWalk;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.annotation.Nullable;

public class SubmoduleOp {
  public interface Factory {
    SubmoduleOp create(Branch.NameKey destBranch, RevCommit mergeTip,
        RevWalk rw, Repository db, Project destProject, List<Change> submitted,
        Map<Change.Id, CodeReviewCommit> commits);
  }

  private static final Logger log = LoggerFactory.getLogger(SubmoduleOp.class);
  private static final String GIT_MODULES = ".gitmodules";

  private final Branch.NameKey destBranch;
  private RevCommit mergeTip;
  private RevWalk rw;
  private final Provider<String> urlProvider;
  private ReviewDb schema;
  private Repository db;
  private Project destProject;
  private List<Change> submitted;
  private final Map<Change.Id, CodeReviewCommit> commits;
  private final PersonIdent myIdent;
  private final GitRepositoryManager repoManager;
  private final GitReferenceUpdated gitRefUpdated;
  private final SchemaFactory<ReviewDb> schemaFactory;
  private final Set<Branch.NameKey> updatedSubscribers;

  @Inject
  public SubmoduleOp(@Assisted final Branch.NameKey destBranch,
      @Assisted RevCommit mergeTip, @Assisted RevWalk rw,
      @CanonicalWebUrl @Nullable final Provider<String> urlProvider,
      final SchemaFactory<ReviewDb> sf, @Assisted Repository db,
      @Assisted Project destProject, @Assisted List<Change> submitted,
      @Assisted final Map<Change.Id, CodeReviewCommit> commits,
      @GerritPersonIdent final PersonIdent myIdent,
      GitRepositoryManager repoManager, GitReferenceUpdated gitRefUpdated) {
    this.destBranch = destBranch;
    this.mergeTip = mergeTip;
    this.rw = rw;
    this.urlProvider = urlProvider;
    this.schemaFactory = sf;
    this.db = db;
    this.destProject = destProject;
    this.submitted = submitted;
    this.commits = commits;
    this.myIdent = myIdent;
    this.repoManager = repoManager;
    this.gitRefUpdated = gitRefUpdated;

    updatedSubscribers = new HashSet<Branch.NameKey>();
  }

  public void update() throws SubmoduleException {
    try {
      schema = schemaFactory.open();

      updateSubmoduleSubscriptions();
      updateSuperProjects(destBranch, rw, mergeTip.getId().toObjectId(), null);
    } catch (OrmException e) {
      throw new SubmoduleException("Cannot open database", e);
    } finally {
      if (schema != null) {
        schema.close();
        schema = null;
      }
    }
  }

  private void updateSubmoduleSubscriptions() throws SubmoduleException {
    if (urlProvider.get() == null) {
      logAndThrowSubmoduleException("Cannot establish canonical web url used to access gerrit."
              + " It should be provided in gerrit.config file.");
    }

    try {
      final TreeWalk tw = TreeWalk.forPath(db, GIT_MODULES, mergeTip.getTree());
      if (tw != null
          && (FileMode.REGULAR_FILE.equals(tw.getRawMode(0)) || FileMode.EXECUTABLE_FILE
              .equals(tw.getRawMode(0)))) {

        BlobBasedConfig bbc =
            new BlobBasedConfig(null, db, mergeTip, GIT_MODULES);

        final String thisServer = new URI(urlProvider.get()).getHost();

        final Branch.NameKey target =
            new Branch.NameKey(new Project.NameKey(destProject.getName()),
                destBranch.get());

        final Set<SubmoduleSubscription> oldSubscriptions =
            new HashSet<SubmoduleSubscription>(schema.submoduleSubscriptions()
                .bySuperProject(destBranch).toList());
        final List<SubmoduleSubscription> newSubscriptions =
            new SubmoduleSectionParser(bbc, thisServer, target, repoManager)
                .parseAllSections();

        final Set<SubmoduleSubscription> alreadySubscribeds =
            new HashSet<SubmoduleSubscription>();
        for (SubmoduleSubscription s : newSubscriptions) {
          if (oldSubscriptions.contains(s)) {
            alreadySubscribeds.add(s);
          }
        }

        oldSubscriptions.removeAll(newSubscriptions);
        newSubscriptions.removeAll(alreadySubscribeds);

        if (!oldSubscriptions.isEmpty()) {
          schema.submoduleSubscriptions().delete(oldSubscriptions);
        }
        schema.submoduleSubscriptions().insert(newSubscriptions);
      }
    } catch (OrmException e) {
      logAndThrowSubmoduleException(
          "Database problem at update of subscriptions table from "
              + GIT_MODULES + " file.", e);
    } catch (ConfigInvalidException e) {
      logAndThrowSubmoduleException(
          "Problem at update of subscriptions table: " + GIT_MODULES
              + " config file is invalid.", e);
    } catch (IOException e) {
      logAndThrowSubmoduleException(
          "Problem at update of subscriptions table from " + GIT_MODULES + ".",
          e);
    } catch (URISyntaxException e) {
      logAndThrowSubmoduleException(
          "Incorrect gerrit canonical web url provided in gerrit.config file.",
          e);
    }
  }

  private void updateSuperProjects(final Branch.NameKey updatedBranch, RevWalk myRw,
      final ObjectId mergedCommit, final String msg) throws SubmoduleException {
    try {
      final List<SubmoduleSubscription> subscribers =
          schema.submoduleSubscriptions().bySubmodule(updatedBranch).toList();

      if (!subscribers.isEmpty()) {
        String msgbuf = msg;
        if (msgbuf == null) {
          // Initialize the message buffer
          msgbuf = "";

          // The first updatedBranch on a cascade event of automatic
          // updates of repos is added to updatedSubscribers set so
          // if we face a situation having
          // submodule-a(master)-->super(master)-->submodule-a(master),
          // it will be detected we have a circular subscription
          // when updateSuperProjects is called having as updatedBranch
          // the super(master) value.
          updatedSubscribers.add(updatedBranch);

          for (final Change chg : submitted) {
            final CodeReviewCommit c = commits.get(chg.getId());
            if (c != null
                && (c.statusCode == CommitMergeStatus.CLEAN_MERGE
                    || c.statusCode == CommitMergeStatus.CLEAN_PICK || c.statusCode == CommitMergeStatus.CLEAN_REBASE)) {
              msgbuf += "\n";
              msgbuf += c.getFullMessage();
            }
          }
        }

        // update subscribers of this module
        for (final SubmoduleSubscription s : subscribers) {
          if (!updatedSubscribers.add(s.getSuperProject())) {
            log.error("Possible circular subscription involving "
                + s.toString());
          } else {

            Map<Branch.NameKey, ObjectId> modules =
                new HashMap<Branch.NameKey, ObjectId>(1);
            modules.put(updatedBranch, mergedCommit);

            Map<Branch.NameKey, String> paths =
                new HashMap<Branch.NameKey, String>(1);
            paths.put(updatedBranch, s.getPath());

            try {
              updateGitlinks(s.getSuperProject(), myRw, modules, paths, msgbuf);
            } catch (SubmoduleException e) {
              throw e;
            }
          }
        }
      }
    } catch (OrmException e) {
      logAndThrowSubmoduleException("Cannot read subscription records", e);
    }
  }

  private void updateGitlinks(final Branch.NameKey subscriber, RevWalk myRw,
      final Map<Branch.NameKey, ObjectId> modules,
      final Map<Branch.NameKey, String> paths, final String msg)
      throws SubmoduleException {
    PersonIdent author = null;

    final StringBuilder msgbuf = new StringBuilder();
    msgbuf.append("Updated " + subscriber.getParentKey().get());
    Repository pdb = null;
    RevWalk recRw = null;

    try {
      boolean sameAuthorForAll = true;

      for (final Map.Entry<Branch.NameKey, ObjectId> me : modules.entrySet()) {
        RevCommit c = myRw.parseCommit(me.getValue());

        msgbuf.append("\nProject: ");
        msgbuf.append(me.getKey().getParentKey().get());
        msgbuf.append("  " + me.getValue().getName());
        msgbuf.append("\n");
        if (modules.size() == 1 && msg != null) {
          msgbuf.append(msg);
        } else {
          msgbuf.append(c.getShortMessage());
        }
        msgbuf.append("\n");

        if (author == null) {
          author = c.getAuthorIdent();
        } else if (!author.equals(c.getAuthorIdent())) {
          sameAuthorForAll = false;
        }
      }

      if (!sameAuthorForAll || author == null) {
        author = myIdent;
      }

      pdb = repoManager.openRepository(subscriber.getParentKey());
      if (pdb.getRef(subscriber.get()) == null) {
        throw new SubmoduleException(
            "The branch was probably deleted from the subscriber repository");
      }

      final ObjectId currentCommitId =
          pdb.getRef(subscriber.get()).getObjectId();

      DirCache dc = readTree(pdb, pdb.getRef(subscriber.get()));
      DirCacheEditor ed = dc.editor();
      for (final Map.Entry<Branch.NameKey, ObjectId> me : modules.entrySet()) {
        ed.add(new PathEdit(paths.get(me.getKey())) {
          public void apply(DirCacheEntry ent) {
            ent.setFileMode(FileMode.GITLINK);
            ent.setObjectId(me.getValue().copy());
          }
        });
      }
      ed.finish();

      ObjectInserter oi = pdb.newObjectInserter();
      ObjectId tree = dc.writeTree(oi);

      final CommitBuilder commit = new CommitBuilder();
      commit.setTreeId(tree);
      commit.setParentIds(new ObjectId[] {currentCommitId});
      commit.setAuthor(author);
      commit.setCommitter(myIdent);
      commit.setMessage(msgbuf.toString());
      oi.insert(commit);

      ObjectId commitId = oi.idFor(Constants.OBJ_COMMIT, commit.build());

      final RefUpdate rfu = pdb.updateRef(subscriber.get());
      rfu.setForceUpdate(false);
      rfu.setNewObjectId(commitId);
      rfu.setExpectedOldObjectId(currentCommitId);
      rfu
          .setRefLogMessage("Submit to " + subscriber.getParentKey().get(),
              true);

      switch (rfu.update()) {
        case NEW:
        case FAST_FORWARD:
          gitRefUpdated.fire(subscriber.getParentKey(), rfu);
          // TODO since this is performed "in the background" no mail will be
          // sent to inform users about the updated branch
          break;

        default:
          throw new IOException(rfu.getResult().name());
      }

      recRw = new RevWalk(pdb);

      // Recursive call: update subscribers of the subscriber
      updateSuperProjects(subscriber, recRw, commitId, msgbuf.toString());
    } catch (IOException e) {
      logAndThrowSubmoduleException("Cannot update gitlinks for "
          + subscriber.get(), e);
    } finally {
      if (recRw != null) {
        recRw.release();
      }
      if (pdb != null) {
        pdb.close();
      }
    }
  }

  private static DirCache readTree(final Repository pdb, final Ref branch)
      throws MissingObjectException, IncorrectObjectTypeException, IOException {
    final RevWalk rw = new RevWalk(pdb);
    try {
      final DirCache dc = DirCache.newInCore();
      final DirCacheBuilder b = dc.builder();
      b.addTree(new byte[0], // no prefix path
          DirCacheEntry.STAGE_0, // standard stage
          pdb.newObjectReader(), rw.parseTree(branch.getObjectId()));
      b.finish();
      return dc;
    } finally {
      rw.release();
    }
  }

  private static void logAndThrowSubmoduleException(final String errorMsg,
      final Exception e) throws SubmoduleException {
    log.error(errorMsg, e);
    throw new SubmoduleException(errorMsg, e);
  }

  private static void logAndThrowSubmoduleException(final String errorMsg)
      throws SubmoduleException {
    log.error(errorMsg);
    throw new SubmoduleException(errorMsg);
  }
}
