// 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.git;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;

import com.google.common.base.Throwables;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.ListMultimap;
import com.google.common.util.concurrent.CheckedFuture;
import com.google.gerrit.extensions.restapi.RestApiException;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.GerritPersonIdent;
import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
import com.google.gerrit.server.index.ChangeIndexer;
import com.google.gerrit.server.notedb.ChangeNotes;
import com.google.gerrit.server.notedb.ChangeUpdate;
import com.google.gerrit.server.project.ChangeControl;
import com.google.inject.assistedinject.Assisted;
import com.google.inject.assistedinject.AssistedInject;

import org.eclipse.jgit.lib.BatchRefUpdate;
import org.eclipse.jgit.lib.NullProgressMonitor;
import org.eclipse.jgit.lib.ObjectInserter;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.transport.ReceiveCommand;

import java.io.IOException;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TimeZone;

/**
 * Context for a set of updates that should be applied for a site.
 * <p>
 * An update operation can be divided into three phases:
 * <ol>
 * <li>Git reference updates</li>
 * <li>Database updates</li>
 * <li>Post-update steps<li>
 * </ol>
 * A single conceptual operation, such as a REST API call or a merge operation,
 * may make multiple changes at each step, which all need to be serialized
 * relative to each other. Moreover, for consistency, <em>all</em> git ref
 * updates must be performed before <em>any</em> database updates, since
 * database updates might refer to newly-created patch set refs. And all
 * post-update steps, such as hooks, should run only after all storage
 * mutations have completed.
 * <p>
 * Depending on the backend used, each step might support batching, for example
 * in a {@code BatchRefUpdate} or one or more database transactions. All
 * operations in one phase must complete successfully before proceeding to the
 * next phase.
 */
public class BatchUpdate implements AutoCloseable {
  public interface Factory {
    public BatchUpdate create(ReviewDb db, Project.NameKey project,
        CurrentUser user, Timestamp when);
  }

  public class Context {
    public Project.NameKey getProject() {
      return project;
    }

    public Timestamp getWhen() {
      return when;
    }

    public ReviewDb getDb() {
      return db;
    }

    public CurrentUser getUser() {
      return user;
    }
  }

  public class RepoContext extends Context {
    public Repository getRepository() throws IOException {
      initRepository();
      return repo;
    }

    public RevWalk getRevWalk() throws IOException {
      initRepository();
      return revWalk;
    }

    public ObjectInserter getInserter() throws IOException {
      initRepository();
      return inserter;
    }

    public BatchRefUpdate getBatchRefUpdate() throws IOException {
      initRepository();
      if (batchRefUpdate == null) {
        batchRefUpdate = repo.getRefDatabase().newBatchUpdate();
      }
      return batchRefUpdate;
    }

    public void addRefUpdate(ReceiveCommand cmd) throws IOException {
      getBatchRefUpdate().addCommand(cmd);
    }

    public TimeZone getTimeZone() {
      return tz;
    }
  }

  public class ChangeContext extends Context {
    private final ChangeControl ctl;
    private final ChangeUpdate update;

    private ChangeContext(ChangeControl ctl) {
      this.ctl = ctl;
      this.update = changeUpdateFactory.create(ctl, when);
    }

    public ChangeUpdate getChangeUpdate() {
      return update;
    }

    public ChangeNotes getChangeNotes() {
      return update.getChangeNotes();
    }

    public ChangeControl getChangeControl() {
      return ctl;
    }

    public Change getChange() {
      return update.getChange();
    }
  }

  public static class Op {
    @SuppressWarnings("unused")
    public void updateRepo(RepoContext ctx) throws Exception {
    }

    @SuppressWarnings("unused")
    public void updateChange(ChangeContext ctx) throws Exception {
    }

    // TODO(dborowitz): Support async operations?
    @SuppressWarnings("unused")
    public void postUpdate(Context ctx) throws Exception {
    }
  }

  public abstract static class InsertChangeOp extends Op {
    public abstract Change getChange();
  }

  private final ReviewDb db;
  private final GitRepositoryManager repoManager;
  private final ChangeIndexer indexer;
  private final ChangeControl.GenericFactory changeControlFactory;
  private final ChangeUpdate.Factory changeUpdateFactory;
  private final GitReferenceUpdated gitRefUpdated;

  private final Project.NameKey project;
  private final CurrentUser user;
  private final Timestamp when;
  private final TimeZone tz;

  private final ListMultimap<Change.Id, Op> ops = ArrayListMultimap.create();
  private final Map<Change.Id, Change> newChanges = new HashMap<>();
  private final List<CheckedFuture<?, IOException>> indexFutures =
      new ArrayList<>();

  private Repository repo;
  private ObjectInserter inserter;
  private RevWalk revWalk;
  private BatchRefUpdate batchRefUpdate;
  private boolean closeRepo;

  @AssistedInject
  BatchUpdate(GitRepositoryManager repoManager,
      ChangeIndexer indexer,
      ChangeControl.GenericFactory changeControlFactory,
      ChangeUpdate.Factory changeUpdateFactory,
      GitReferenceUpdated gitRefUpdated,
      @GerritPersonIdent PersonIdent serverIdent,
      @Assisted ReviewDb db,
      @Assisted Project.NameKey project,
      @Assisted CurrentUser user,
      @Assisted Timestamp when) {
    this.db = db;
    this.repoManager = repoManager;
    this.indexer = indexer;
    this.changeControlFactory = changeControlFactory;
    this.changeUpdateFactory = changeUpdateFactory;
    this.gitRefUpdated = gitRefUpdated;
    this.project = project;
    this.user = user;
    this.when = when;
    tz = serverIdent.getTimeZone();
  }

  @Override
  public void close() {
    if (closeRepo) {
      revWalk.close();
      inserter.close();
      repo.close();
    }
  }

  public BatchUpdate setRepository(Repository repo, RevWalk revWalk,
      ObjectInserter inserter) {
    checkState(this.repo == null, "repo already set");
    closeRepo = false;
    this.repo = checkNotNull(repo, "repo");
    this.revWalk = checkNotNull(revWalk, "revWalk");
    this.inserter = checkNotNull(inserter, "inserter");
    return this;
  }

  private void initRepository() throws IOException {
    if (repo == null) {
      this.repo = repoManager.openRepository(project);
      closeRepo = true;
      inserter = repo.newObjectInserter();
      revWalk = new RevWalk(inserter.newReader());
    }
  }

  public CurrentUser getUser() {
    return user;
  }

  public Repository getRepository() throws IOException {
    initRepository();
    return repo;
  }

  public RevWalk getRevWalk() throws IOException {
    initRepository();
    return revWalk;
  }

  public ObjectInserter getObjectInserter() throws IOException {
    initRepository();
    return inserter;
  }

  public BatchUpdate addOp(Change.Id id, Op op) {
    checkArgument(!(op instanceof InsertChangeOp), "use insertChange");
    ops.put(id, op);
    return this;
  }

  public BatchUpdate insertChange(InsertChangeOp op) {
    Change c = op.getChange();
    checkArgument(!newChanges.containsKey(c.getId()),
        "only one op allowed to create change %s", c.getId());
    newChanges.put(c.getId(), c);
    ops.get(c.getId()).add(0, op);
    return this;
  }

  public void execute() throws UpdateException, RestApiException {
    try {
      executeRefUpdates();
      executeChangeOps();
      reindexChanges();

      if (batchRefUpdate != null) {
        // Fire ref update events only after all mutations are finished, since
        // callers may assume a patch set ref being created means the change was
        // created, or a branch advancing meaning some changes were closed.
        gitRefUpdated.fire(project, batchRefUpdate);
      }

      executePostOps();
    } catch (UpdateException | RestApiException e) {
      // Propagate REST API exceptions thrown by operations; they commonly throw
      // exceptions like ResourceConflictException to indicate an atomic update
      // failure.
      throw e;
    } catch (Exception e) {
      Throwables.propagateIfPossible(e);
      throw new UpdateException(e);
    }
  }

  private void executeRefUpdates()
      throws IOException, UpdateException, RestApiException {
    try {
      RepoContext ctx = new RepoContext();
      for (Op op : ops.values()) {
        op.updateRepo(ctx);
      }
    } catch (Exception e) {
      Throwables.propagateIfPossible(e, RestApiException.class);
      throw new UpdateException(e);
    }

    if (repo == null || batchRefUpdate == null
        || batchRefUpdate.getCommands().isEmpty()) {
      return;
    }
    inserter.flush();
    batchRefUpdate.execute(revWalk, NullProgressMonitor.INSTANCE);
    boolean ok = true;
    for (ReceiveCommand cmd : batchRefUpdate.getCommands()) {
      if (cmd.getResult() != ReceiveCommand.Result.OK) {
        ok = false;
        break;
      }
    }
    if (!ok) {
      throw new UpdateException("BatchRefUpdate failed: " + batchRefUpdate);
    }
  }

  private void executeChangeOps() throws UpdateException, RestApiException {
    try {
      for (Map.Entry<Change.Id, Collection<Op>> e : ops.asMap().entrySet()) {
        Change.Id id = e.getKey();
        db.changes().beginTransaction(id);
        ChangeContext ctx;
        try {
          ctx = newChangeContext(id);
          for (Op op : e.getValue()) {
            op.updateChange(ctx);
          }
          db.commit();
        } finally {
          db.rollback();
        }
        ctx.getChangeUpdate().commit();
        indexFutures.add(indexer.indexAsync(id));
      }
    } catch (Exception e) {
      Throwables.propagateIfPossible(e, RestApiException.class);
      throw new UpdateException(e);
    }
  }

  private ChangeContext newChangeContext(Change.Id id) throws Exception {
    Change c = newChanges.get(id);
    if (c == null) {
      c = db.changes().get(id);
    }
    // Pass in preloaded change to controlFor, to avoid:
    //  - reading from a db that does not belong to this update
    //  - attempting to read a change that doesn't exist yet
    return new ChangeContext(
      changeControlFactory.controlFor(c, user));
  }

  private void reindexChanges() throws IOException {
    ChangeIndexer.allAsList(indexFutures).checkedGet();
  }

  private void executePostOps() throws Exception {
    Context ctx = new Context();
    for (Op op : ops.values()) {
      op.postUpdate(ctx);
    }
  }
}
