// Copyright (C) 2014 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.notedb;

import static com.google.common.base.Preconditions.checkState;
import static com.google.gerrit.server.PatchLineCommentsUtil.setCommentRevId;

import com.google.common.base.MoreObjects;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.ComparisonChain;
import com.google.common.collect.Lists;
import com.google.common.collect.Multimap;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.PatchLineComment;
import com.google.gerrit.reviewdb.client.PatchLineComment.Status;
import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gerrit.reviewdb.client.PatchSetApproval;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.PatchLineCommentsUtil;
import com.google.gerrit.server.git.VersionedMetaData.BatchMetaDataUpdate;
import com.google.gerrit.server.patch.PatchListCache;
import com.google.gerrit.server.project.ChangeControl;
import com.google.gerrit.server.project.NoSuchChangeException;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Provider;

import org.eclipse.jgit.lib.BatchRefUpdate;
import org.eclipse.jgit.lib.ObjectInserter;
import org.eclipse.jgit.lib.RefUpdate;
import org.eclipse.jgit.lib.Repository;

import java.io.IOException;
import java.sql.Timestamp;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;

public class ChangeRebuilder {
  private static final long TS_WINDOW_MS =
      TimeUnit.MILLISECONDS.convert(1, TimeUnit.SECONDS);

  private final Provider<ReviewDb> dbProvider;
  private final ChangeControl.GenericFactory controlFactory;
  private final IdentifiedUser.GenericFactory userFactory;
  private final PatchListCache patchListCache;
  private final ChangeUpdate.Factory updateFactory;
  private final ChangeDraftUpdate.Factory draftUpdateFactory;

  @Inject
  ChangeRebuilder(Provider<ReviewDb> dbProvider,
      ChangeControl.GenericFactory controlFactory,
      IdentifiedUser.GenericFactory userFactory,
      PatchListCache patchListCache,
      ChangeUpdate.Factory updateFactory,
      ChangeDraftUpdate.Factory draftUpdateFactory) {
    this.dbProvider = dbProvider;
    this.controlFactory = controlFactory;
    this.userFactory = userFactory;
    this.patchListCache = patchListCache;
    this.updateFactory = updateFactory;
    this.draftUpdateFactory = draftUpdateFactory;
  }

  public ListenableFuture<?> rebuildAsync(final Change change,
      ListeningExecutorService executor, final BatchRefUpdate bru,
      final BatchRefUpdate bruForDrafts, final Repository changeRepo,
      final Repository allUsersRepo) {
    return executor.submit(new Callable<Void>() {
        @Override
      public Void call() throws Exception {
        rebuild(change, bru, bruForDrafts, changeRepo, allUsersRepo);
        return null;
      }
    });
  }

  public void rebuild(Change change, BatchRefUpdate bru,
      BatchRefUpdate bruForDrafts, Repository changeRepo,
      Repository allUsersRepo) throws NoSuchChangeException, IOException,
      OrmException {
    deleteRef(change, changeRepo);
    ReviewDb db = dbProvider.get();
    Change.Id changeId = change.getId();

    // We will rebuild all events, except for draft comments, in buckets based
    // on author and timestamp. However, all draft comments for a given change
    // and author will be written as one commit in the notedb.
    List<Event> events = Lists.newArrayList();
    Multimap<Account.Id, PatchLineCommentEvent> draftCommentEvents =
        ArrayListMultimap.create();

    for (PatchSet ps : db.patchSets().byChange(changeId)) {
      events.add(new PatchSetEvent(ps));
      for (PatchLineComment c : db.patchComments().byPatchSet(ps.getId())) {
        PatchLineCommentEvent e =
            new PatchLineCommentEvent(c, change, ps, patchListCache);
        if (c.getStatus() == Status.PUBLISHED) {
          events.add(e);
        } else {
          draftCommentEvents.put(c.getAuthor(), e);
        }
      }
    }

    for (PatchSetApproval psa : db.patchSetApprovals().byChange(changeId)) {
      events.add(new ApprovalEvent(psa));
    }


    Collections.sort(events);
    BatchMetaDataUpdate batch = null;
    ChangeUpdate update = null;
    for (Event e : events) {
      if (!sameUpdate(e, update)) {
        if (update != null) {
          writeToBatch(batch, update, changeRepo);
        }
        IdentifiedUser user = userFactory.create(dbProvider, e.who);
        update = updateFactory.create(
            controlFactory.controlFor(change, user), e.when);
        update.setPatchSetId(e.psId);
        if (batch == null) {
          batch = update.openUpdateInBatch(bru);
        }
      }
      e.apply(update);
    }
    if (batch != null) {
      if (update != null) {
        writeToBatch(batch, update, changeRepo);
      }

      // Since the BatchMetaDataUpdates generated by all ChangeRebuilders on a
      // given project are backed by the same BatchRefUpdate, we need to
      // synchronize on the BatchRefUpdate. Therefore, since commit on a
      // BatchMetaDataUpdate is the only method that modifies a BatchRefUpdate,
      // we can just synchronize this call.
      synchronized (bru) {
        batch.commit();
      }
    }

    for (Account.Id author : draftCommentEvents.keys()) {
      IdentifiedUser user = userFactory.create(dbProvider, author);
      ChangeDraftUpdate draftUpdate = null;
      BatchMetaDataUpdate batchForDrafts = null;
      for (PatchLineCommentEvent e : draftCommentEvents.get(author)) {
        if (draftUpdate == null) {
          draftUpdate = draftUpdateFactory.create(
              controlFactory.controlFor(change, user), e.when);
          draftUpdate.setPatchSetId(e.psId);
          batchForDrafts = draftUpdate.openUpdateInBatch(bruForDrafts);
        }
        e.applyDraft(draftUpdate);
      }
      writeToBatch(batchForDrafts, draftUpdate, allUsersRepo);
      synchronized(bruForDrafts) {
        batchForDrafts.commit();
      }
    }
  }

  private void deleteRef(Change change, Repository changeRepo)
      throws IOException {
    String refName = ChangeNoteUtil.changeRefName(change.getId());
    RefUpdate ru = changeRepo.updateRef(refName, true);
    ru.setForceUpdate(true);
    RefUpdate.Result result = ru.delete();
    switch (result) {
      case FORCED:
      case NEW:
      case NO_CHANGE:
        break;
      default:
        throw new IOException(
            String.format("Failed to delete ref %s: %s", refName, result));
    }
  }

  private void writeToBatch(BatchMetaDataUpdate batch,
      AbstractChangeUpdate update, Repository repo) throws IOException,
      OrmException {
    try (ObjectInserter inserter = repo.newObjectInserter()) {
      update.setInserter(inserter);
      update.writeCommit(batch);
    }
  }

  private static long round(Date when) {
    return when.getTime() / TS_WINDOW_MS;
  }

  private static boolean sameUpdate(Event event, ChangeUpdate update) {
    return update != null
        && round(event.when) == round(update.getWhen())
        && event.who.equals(update.getUser().getAccountId())
        && event.psId.equals(update.getPatchSetId());
  }

  private abstract static class Event implements Comparable<Event> {
    final PatchSet.Id psId;
    final Account.Id who;
    final Timestamp when;

    protected Event(PatchSet.Id psId, Account.Id who, Timestamp when) {
      this.psId = psId;
      this.who = who;
      this.when = when;
    }

    protected void checkUpdate(AbstractChangeUpdate update) {
      checkState(Objects.equals(update.getPatchSetId(), psId),
          "cannot apply event for %s to update for %s",
          update.getPatchSetId(), psId);
      checkState(when.getTime() - update.getWhen().getTime() <= TS_WINDOW_MS,
          "event at %s outside update window starting at %s",
          when, update.getWhen());
      checkState(Objects.equals(update.getUser().getAccountId(), who),
          "cannot apply event by %s to update by %s",
          who, update.getUser().getAccountId());
    }

    abstract void apply(ChangeUpdate update) throws OrmException;

    @Override
    public int compareTo(Event other) {
      return ComparisonChain.start()
          // TODO(dborowitz): Smarter bucketing: pick a bucket start time T and
          // include all events up to T + TS_WINDOW_MS but no further.
          // Interleaving different authors complicates things.
          .compare(round(when), round(other.when))
          .compare(who.get(), other.who.get())
          .compare(psId.get(), other.psId.get())
          .result();
    }

    @Override
    public String toString() {
      return MoreObjects.toStringHelper(this)
          .add("psId", psId)
          .add("who", who)
          .add("when", when)
          .toString();
    }
  }

  private static class ApprovalEvent extends Event {
    private PatchSetApproval psa;

    ApprovalEvent(PatchSetApproval psa) {
      super(psa.getPatchSetId(), psa.getAccountId(), psa.getGranted());
      this.psa = psa;
    }

    @Override
    void apply(ChangeUpdate update) {
      checkUpdate(update);
      update.putApproval(psa.getLabel(), psa.getValue());
    }
  }

  private static class PatchSetEvent extends Event {
    private final PatchSet ps;

    PatchSetEvent(PatchSet ps) {
      super(ps.getId(), ps.getUploader(), ps.getCreatedOn());
      this.ps = ps;
    }

    @Override
    void apply(ChangeUpdate update) {
      checkUpdate(update);
      if (ps.getPatchSetId() == 1) {
        update.setSubject("Create change");
      } else {
        update.setSubject("Create patch set " + ps.getPatchSetId());
      }
    }
  }

  private static class PatchLineCommentEvent extends Event {
    public final PatchLineComment c;
    private final Change change;
    private final PatchSet ps;
    private final PatchListCache cache;

    PatchLineCommentEvent(PatchLineComment c, Change change, PatchSet ps,
        PatchListCache cache) {
      super(PatchLineCommentsUtil.getCommentPsId(c), c.getAuthor(), c.getWrittenOn());
      this.c = c;
      this.change = change;
      this.ps = ps;
      this.cache = cache;
    }

    @Override
    void apply(ChangeUpdate update) throws OrmException {
      checkUpdate(update);
      if (c.getRevId() == null) {
        setCommentRevId(c, cache, change, ps);
      }
      update.insertComment(c);
    }

    void applyDraft(ChangeDraftUpdate draftUpdate) throws OrmException {
      if (c.getRevId() == null) {
        setCommentRevId(c, cache, change, ps);
      }
      draftUpdate.insertComment(c);
    }
  }
}
