// 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.server.patch;

import com.google.gerrit.client.data.ApprovalType;
import com.google.gerrit.client.data.ProjectCache;
import com.google.gerrit.client.data.SideBySidePatchDetail;
import com.google.gerrit.client.data.UnifiedPatchDetail;
import com.google.gerrit.client.patches.PatchDetailService;
import com.google.gerrit.client.reviewdb.Account;
import com.google.gerrit.client.reviewdb.ApprovalCategory;
import com.google.gerrit.client.reviewdb.ApprovalCategoryValue;
import com.google.gerrit.client.reviewdb.Change;
import com.google.gerrit.client.reviewdb.ChangeApproval;
import com.google.gerrit.client.reviewdb.ChangeMessage;
import com.google.gerrit.client.reviewdb.Patch;
import com.google.gerrit.client.reviewdb.PatchLineComment;
import com.google.gerrit.client.reviewdb.PatchSet;
import com.google.gerrit.client.reviewdb.PatchSetInfo;
import com.google.gerrit.client.reviewdb.Project;
import com.google.gerrit.client.reviewdb.ReviewDb;
import com.google.gerrit.client.reviewdb.Account.Id;
import com.google.gerrit.client.rpc.BaseServiceImplementation;
import com.google.gerrit.client.rpc.Common;
import com.google.gerrit.client.rpc.NoSuchEntityException;
import com.google.gerrit.git.RepositoryCache;
import com.google.gerrit.server.ChangeMail;
import com.google.gerrit.server.ChangeUtil;
import com.google.gerrit.server.GerritJsonServlet;
import com.google.gerrit.server.GerritServer;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwtjsonrpc.client.VoidResult;
import com.google.gwtorm.client.OrmException;
import com.google.gwtorm.client.OrmRunnable;
import com.google.gwtorm.client.Transaction;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.mail.MessagingException;

public class PatchDetailServiceImpl extends BaseServiceImplementation implements
    PatchDetailService {
  private final Logger log = LoggerFactory.getLogger(getClass());
  private final GerritServer server;

  public PatchDetailServiceImpl(final GerritServer gs) {
    server = gs;
  }

  public void sideBySidePatchDetail(final Patch.Key key,
      final List<PatchSet.Id> versions,
      final AsyncCallback<SideBySidePatchDetail> callback) {
    final RepositoryCache rc = server.getRepositoryCache();
    if (rc == null) {
      callback.onFailure(new Exception("No Repository Cache configured"));
      return;
    }
    run(callback, new SideBySidePatchDetailAction(rc, key, versions));
  }

  public void unifiedPatchDetail(final Patch.Key key,
      final AsyncCallback<UnifiedPatchDetail> callback) {
    run(callback, new UnifiedPatchDetailAction(key));
  }

  public void myDrafts(final Patch.Key key,
      final AsyncCallback<List<PatchLineComment>> callback) {
    run(callback, new Action<List<PatchLineComment>>() {
      public List<PatchLineComment> run(ReviewDb db) throws OrmException {
        return db.patchComments().draft(key, Common.getAccountId()).toList();
      }
    });
  }

  public void saveDraft(final PatchLineComment comment,
      final AsyncCallback<PatchLineComment> callback) {
    run(callback, new Action<PatchLineComment>() {
      public PatchLineComment run(ReviewDb db) throws OrmException, Failure {
        if (comment.getStatus() != PatchLineComment.Status.DRAFT) {
          throw new Failure(new IllegalStateException("Comment published"));
        }

        final Patch patch = db.patches().get(comment.getKey().getParentKey());
        final Change change;
        if (patch == null) {
          throw new Failure(new NoSuchEntityException());
        }
        change = db.changes().get(patch.getKey().getParentKey().getParentKey());
        assertCanRead(change);

        final Account.Id me = Common.getAccountId();
        if (comment.getKey().get() == null) {
          final PatchLineComment nc =
              new PatchLineComment(new PatchLineComment.Key(patch.getKey(),
                  ChangeUtil.messageUUID(db)), comment.getLine(), me);
          nc.setSide(comment.getSide());
          nc.setMessage(comment.getMessage());
          db.patchComments().insert(Collections.singleton(nc));
          return nc;

        } else {
          if (!me.equals(comment.getAuthor())) {
            throw new Failure(new NoSuchEntityException());
          }
          comment.updated();
          db.patchComments().update(Collections.singleton(comment));
          return comment;
        }
      }
    });
  }

  public void deleteDraft(final PatchLineComment.Key commentKey,
      final AsyncCallback<VoidResult> callback) {
    run(callback, new Action<VoidResult>() {
      public VoidResult run(ReviewDb db) throws OrmException, Failure {
        final PatchLineComment comment = db.patchComments().get(commentKey);
        if (comment == null) {
          throw new Failure(new NoSuchEntityException());
        }
        if (!Common.getAccountId().equals(comment.getAuthor())) {
          throw new Failure(new NoSuchEntityException());
        }
        if (comment.getStatus() != PatchLineComment.Status.DRAFT) {
          throw new Failure(new IllegalStateException("Comment published"));
        }
        db.patchComments().delete(Collections.singleton(comment));
        return VoidResult.INSTANCE;
      }
    });
  }

  public void publishComments(final PatchSet.Id psid, final String message,
      final Set<ApprovalCategoryValue.Id> approvals,
      final AsyncCallback<VoidResult> callback) {
    run(callback, new Action<VoidResult>() {
      public VoidResult run(ReviewDb db) throws OrmException, Failure {
        final PublishResult r;

        r = db.run(new OrmRunnable<PublishResult, ReviewDb>() {
          public PublishResult run(ReviewDb db, Transaction txn, boolean retry)
              throws OrmException {
            return doPublishComments(psid, message, approvals, db, txn);
          }
        });

        try {
          final ChangeMail cm = new ChangeMail(server, r.change);
          cm.setFrom(Common.getAccountId());
          cm.setPatchSet(r.patchSet, r.info);
          cm.setChangeMessage(r.message);
          cm.setPatchLineComments(r.comments);
          cm.setReviewDb(db);
          cm.setHttpServletRequest(GerritJsonServlet.getCurrentCall()
              .getHttpServletRequest());
          cm.sendComment();
        } catch (MessagingException e) {
          log.error("Cannot send comments by email for patch set " + psid, e);
          throw new Failure(e);
        }
        return VoidResult.INSTANCE;
      }
    });
  }

  private static class PublishResult {
    Change change;
    PatchSet patchSet;
    PatchSetInfo info;
    ChangeMessage message;
    List<PatchLineComment> comments;
  }

  private PublishResult doPublishComments(final PatchSet.Id psid,
      final String messageText, final Set<ApprovalCategoryValue.Id> approvals,
      final ReviewDb db, final Transaction txn) throws OrmException {
    final PublishResult r = new PublishResult();
    final Account.Id me = Common.getAccountId();
    r.change = db.changes().get(psid.getParentKey());
    r.patchSet = db.patchSets().get(psid);
    r.info = db.patchSetInfo().get(psid);
    if (r.change == null || r.patchSet == null || r.info == null) {
      throw new OrmException(new NoSuchEntityException());
    }

    r.comments = db.patchComments().draft(psid, me).toList();
    final Set<Patch.Key> patchKeys = new HashSet<Patch.Key>();
    for (final PatchLineComment c : r.comments) {
      patchKeys.add(c.getKey().getParentKey());
    }
    final Map<Patch.Key, Patch> patches =
        db.patches().toMap(db.patches().get(patchKeys));
    for (final PatchLineComment c : r.comments) {
      final Patch p = patches.get(c.getKey().getParentKey());
      if (p != null) {
        p.setCommentCount(p.getCommentCount() + 1);
      }
      c.setStatus(PatchLineComment.Status.PUBLISHED);
      c.updated();
    }
    db.patches().update(patches.values(), txn);
    db.patchComments().update(r.comments, txn);

    final StringBuilder msgbuf = new StringBuilder();
    final Map<ApprovalCategory.Id, ApprovalCategoryValue.Id> values =
        new HashMap<ApprovalCategory.Id, ApprovalCategoryValue.Id>();
    for (final ApprovalCategoryValue.Id v : approvals) {
      values.put(v.getParentKey(), v);
    }

    final boolean open = r.change.getStatus().isOpen();
    final Map<ApprovalCategory.Id, ChangeApproval> have =
        new HashMap<ApprovalCategory.Id, ChangeApproval>();
    for (final ChangeApproval a : db.changeApprovals().byChangeUser(
        r.change.getId(), me)) {
      have.put(a.getCategoryId(), a);
    }
    for (final ApprovalType at : Common.getGerritConfig().getApprovalTypes()) {
      final ApprovalCategoryValue.Id v = values.get(at.getCategory().getId());
      if (v == null) {
        continue;
      }

      final ApprovalCategoryValue val = at.getValue(v.get());
      if (val == null) {
        continue;
      }

      ChangeApproval mycatpp = have.remove(v.getParentKey());
      if (mycatpp == null) {
        if (msgbuf.length() > 0) {
          msgbuf.append("; ");
        }
        msgbuf.append(val.getName());
        if (open) {
          mycatpp =
              new ChangeApproval(new ChangeApproval.Key(r.change.getId(), me, v
                  .getParentKey()), v.get());
          db.changeApprovals().insert(Collections.singleton(mycatpp), txn);
        }

      } else if (mycatpp.getValue() != v.get()) {
        if (msgbuf.length() > 0) {
          msgbuf.append("; ");
        }
        msgbuf.append(val.getName());
        if (open) {
          mycatpp.setValue(v.get());
          mycatpp.setGranted();
          db.changeApprovals().update(Collections.singleton(mycatpp), txn);
        }
      }
    }
    if (open) {
      db.changeApprovals().delete(have.values(), txn);
    }

    if (msgbuf.length() > 0) {
      msgbuf.insert(0, "Patch Set " + psid.get() + ": ");
      msgbuf.append("\n\n");
    }
    if (messageText != null) {
      msgbuf.append(messageText);
    }
    if (msgbuf.length() > 0) {
      r.message =
          new ChangeMessage(new ChangeMessage.Key(r.change.getId(), ChangeUtil
              .messageUUID(db)), me);
      r.message.setMessage(msgbuf.toString());
      db.changeMessages().insert(Collections.singleton(r.message), txn);
    }

    ChangeUtil.updated(r.change);
    db.changes().update(Collections.singleton(r.change), txn);
    return r;
  }

  public void addReviewers(final Change.Id id, final List<String> reviewers,
      final AsyncCallback<VoidResult> callback) {
    run(callback, new Action<VoidResult>() {
      public VoidResult run(ReviewDb db) throws OrmException, Failure {
        final Set<Account.Id> reviewerIds = new HashSet<Account.Id>();
        final Change change = db.changes().get(id);
        if (change == null) {
          throw new Failure(new NoSuchEntityException());
        }

        for (final String email : reviewers) {
          final Account who = Account.find(db, email);
          if (who != null) {
            reviewerIds.add(who.getId());
          }
        }

        // Add the reviewer to the database
        db.run(new OrmRunnable<VoidResult, ReviewDb>() {
          public VoidResult run(ReviewDb db, Transaction txn, boolean retry)
              throws OrmException {
            return doAddReviewers(reviewerIds, id, db, txn);
          }
        });

        // Email the reviewer
        try {
          final ChangeMail cm = new ChangeMail(server, change);
          cm.setFrom(Common.getAccountId());
          cm.setReviewDb(db);
          cm.addReviewers(reviewerIds);
          cm.setHttpServletRequest(GerritJsonServlet.getCurrentCall()
              .getHttpServletRequest());
          cm.sendRequestReview();
        } catch (MessagingException e) {
          log.error("Cannot send review request by email for change " + id, e);
          throw new Failure(e);
        }
        return VoidResult.INSTANCE;
      }
    });
  }

  private VoidResult doAddReviewers(final Set<Id> reviewerIds,
      final Change.Id id, final ReviewDb db, final Transaction txn)
      throws OrmException {
    final List<ApprovalType> allTypes =
        Common.getGerritConfig().getApprovalTypes();
    final ApprovalCategory.Id ac =
        allTypes.get(allTypes.size() - 1).getCategory().getId();

    for (Account.Id reviewer : reviewerIds) {
      if (!db.changeApprovals().byChangeUser(id, reviewer).iterator().hasNext()) {
        // This reviewer has not entered an approval for this change yet.
        ChangeApproval myca =
            new ChangeApproval(new ChangeApproval.Key(id, reviewer, ac),
                (short) 0);
        db.changeApprovals().insert(Collections.singleton(myca), txn);
      }
    }
    return VoidResult.INSTANCE;
  }

  public void abandonChange(final PatchSet.Id patchSetId, final String message,
      final AsyncCallback<VoidResult> callback) {
    run(callback, new Action<VoidResult>() {
      public VoidResult run(final ReviewDb db) throws OrmException, Failure {
        final Account.Id me = Common.getAccountId();
        final Change change = db.changes().get(patchSetId.getParentKey());
        if (change == null) {
          throw new Failure(new NoSuchEntityException());
        }
        final PatchSet patch = db.patchSets().get(patchSetId);
        final ProjectCache.Entry projEnt =
            Common.getProjectCache().get(change.getDest().getParentKey());
        if (me == null || patch == null || projEnt == null) {
          throw new Failure(new NoSuchEntityException());
        }
        final Project proj = projEnt.getProject();

        if (!me.equals(change.getOwner()) && !me.equals(patch.getUploader())
            && !Common.getGroupCache().isAdministrator(me)
            && !Common.getGroupCache().isInGroup(me, proj.getOwnerGroupId())) {
          // The user doesn't have permission to abandon the change
          throw new Failure(new NoSuchEntityException());
        }

        final ChangeMessage cmsg =
            new ChangeMessage(new ChangeMessage.Key(change.getId(), ChangeUtil
                .messageUUID(db)), me);
        final StringBuilder msgBuf =
            new StringBuilder("Patch Set " + change.currentPatchSetId().get()
                + ": Abandoned");
        if (message != null && message.length() > 0) {
          msgBuf.append("\n\n");
          msgBuf.append(message);
        }
        cmsg.setMessage(msgBuf.toString());

        Boolean dbSuccess = db.run(new OrmRunnable<Boolean, ReviewDb>() {
          public Boolean run(ReviewDb db, Transaction txn, boolean retry)
              throws OrmException {
            return doAbandonChange(message, change, patchSetId, cmsg, db, txn);
          }
        });

        if (dbSuccess) {
          // Email the reviewers
          try {
            final ChangeMail cm = new ChangeMail(server, change);
            cm.setFrom(me);
            cm.setReviewDb(db);
            cm.setChangeMessage(cmsg);
            cm.setHttpServletRequest(GerritJsonServlet.getCurrentCall()
                .getHttpServletRequest());
            cm.sendAbandoned();
          } catch (MessagingException e) {
            log.error("Cannot send abandon change email for change "
                + change.getChangeId(), e);
            throw new Failure(e);
          }
        }

        return VoidResult.INSTANCE;
      }
    });
  }

  private Boolean doAbandonChange(final String message, final Change change,
      final PatchSet.Id psid, final ChangeMessage cm, final ReviewDb db,
      final Transaction txn) throws OrmException {

    // Check to make sure the change status and current patchset ID haven't
    // changed while the user was typing an abandon message
    if (change.getStatus() == Change.Status.NEW
        && change.currentPatchSetId().equals(psid)) {
      change.setStatus(Change.Status.ABANDONED);
      ChangeUtil.updated(change);

      final List<ChangeApproval> approvals =
          db.changeApprovals().byChange(change.getId()).toList();
      for (ChangeApproval a : approvals) {
        a.cache(change);
      }
      db.changeApprovals().update(approvals, txn);

      db.changeMessages().insert(Collections.singleton(cm), txn);
      db.changes().update(Collections.singleton(change), txn);
      return Boolean.TRUE;
    }

    return Boolean.FALSE;
  }
}
