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