// Copyright (C) 2009 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.common.ChangeHookRunner;
import com.google.gerrit.common.data.ApprovalType;
import com.google.gerrit.common.data.ApprovalTypes;
import com.google.gerrit.reviewdb.ApprovalCategory;
import com.google.gerrit.reviewdb.ApprovalCategoryValue;
import com.google.gerrit.reviewdb.Change;
import com.google.gerrit.reviewdb.ChangeMessage;
import com.google.gerrit.reviewdb.PatchLineComment;
import com.google.gerrit.reviewdb.PatchSet;
import com.google.gerrit.reviewdb.PatchSetApproval;
import com.google.gerrit.reviewdb.ReviewDb;
import com.google.gerrit.server.ChangeUtil;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.mail.CommentSender;
import com.google.gerrit.server.mail.EmailException;
import com.google.gerrit.server.project.ChangeControl;
import com.google.gerrit.server.project.InvalidChangeOperationException;
import com.google.gerrit.server.project.NoSuchChangeException;
import com.google.gerrit.server.workflow.FunctionState;
import com.google.gwtjsonrpc.client.VoidResult;
import com.google.gwtorm.client.OrmException;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;

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

import java.util.ArrayList;
import java.util.Collection;
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 java.util.concurrent.Callable;

public class PublishComments implements Callable<VoidResult> {
  private static final Logger log =
      LoggerFactory.getLogger(PublishComments.class);

  public interface Factory {
    PublishComments create(PatchSet.Id patchSetId, String messageText,
        Set<ApprovalCategoryValue.Id> approvals);
  }

  private final ReviewDb db;
  private final IdentifiedUser user;
  private final ApprovalTypes types;
  private final CommentSender.Factory commentSenderFactory;
  private final PatchSetInfoFactory patchSetInfoFactory;
  private final ChangeControl.Factory changeControlFactory;
  private final FunctionState.Factory functionStateFactory;
  private final ChangeHookRunner hooks;

  private final PatchSet.Id patchSetId;
  private final String messageText;
  private final Set<ApprovalCategoryValue.Id> approvals;

  private Change change;
  private PatchSet patchSet;
  private ChangeMessage message;
  private List<PatchLineComment> drafts;

  @Inject
  PublishComments(final ReviewDb db, final IdentifiedUser user,
      final ApprovalTypes approvalTypes,
      final CommentSender.Factory commentSenderFactory,
      final PatchSetInfoFactory patchSetInfoFactory,
      final ChangeControl.Factory changeControlFactory,
      final FunctionState.Factory functionStateFactory,
      final ChangeHookRunner hooks,

      @Assisted final PatchSet.Id patchSetId,
      @Assisted final String messageText,
      @Assisted final Set<ApprovalCategoryValue.Id> approvals) {
    this.db = db;
    this.user = user;
    this.types = approvalTypes;
    this.patchSetInfoFactory = patchSetInfoFactory;
    this.commentSenderFactory = commentSenderFactory;
    this.changeControlFactory = changeControlFactory;
    this.functionStateFactory = functionStateFactory;
    this.hooks = hooks;

    this.patchSetId = patchSetId;
    this.messageText = messageText;
    this.approvals = approvals;
  }

  @Override
  public VoidResult call() throws NoSuchChangeException,
      InvalidChangeOperationException, OrmException {
    final Change.Id changeId = patchSetId.getParentKey();
    final ChangeControl ctl = changeControlFactory.validateFor(changeId);
    change = ctl.getChange();
    patchSet = db.patchSets().get(patchSetId);
    if (patchSet == null) {
      throw new NoSuchChangeException(changeId);
    }
    drafts = drafts();

    publishDrafts();

    final boolean isCurrent = patchSetId.equals(change.currentPatchSetId());
    if (isCurrent && change.getStatus().isOpen()) {
      publishApprovals(ctl);
    } else if (! approvals.isEmpty()) {
      throw new InvalidChangeOperationException("Change is closed");
    } else {
      publishMessageOnly();
    }

    touchChange();
    email();
    fireHook();
    return VoidResult.INSTANCE;
  }

  private void publishDrafts() throws OrmException {
    for (final PatchLineComment c : drafts) {
      c.setStatus(PatchLineComment.Status.PUBLISHED);
      c.updated();
    }
    db.patchComments().update(drafts);
  }

  private void publishApprovals(ChangeControl ctl) throws OrmException {
    ChangeUtil.updated(change);

    final Set<ApprovalCategory.Id> dirty = new HashSet<ApprovalCategory.Id>();
    final List<PatchSetApproval> ins = new ArrayList<PatchSetApproval>();
    final List<PatchSetApproval> upd = new ArrayList<PatchSetApproval>();
    final Collection<PatchSetApproval> all =
        db.patchSetApprovals().byPatchSet(patchSetId).toList();
    final Map<ApprovalCategory.Id, PatchSetApproval> mine = mine(all);

    // Ensure any new approvals are stored properly.
    //
    for (final ApprovalCategoryValue.Id want : approvals) {
      PatchSetApproval a = mine.get(want.getParentKey());
      if (a == null) {
        a = new PatchSetApproval(new PatchSetApproval.Key(//
            patchSetId, user.getAccountId(), want.getParentKey()), want.get());
        a.cache(change);
        ins.add(a);
        all.add(a);
        mine.put(a.getCategoryId(), a);
        dirty.add(a.getCategoryId());
      }
    }

    // Normalize all of the items the user is changing.
    //
    final FunctionState functionState =
        functionStateFactory.create(ctl, patchSetId, all);
    for (final ApprovalCategoryValue.Id want : approvals) {
      final PatchSetApproval a = mine.get(want.getParentKey());
      final short o = a.getValue();
      a.setValue(want.get());
      a.cache(change);
      if (!ApprovalCategory.SUBMIT.equals(a.getCategoryId())) {
        functionState.normalize(types.byId(a.getCategoryId()), a);
      }
      if (o != a.getValue()) {
        // Value changed, ensure we update the database.
        //
        a.setGranted();
        dirty.add(a.getCategoryId());
      }
      if (!ins.contains(a)) {
        upd.add(a);
      }
    }

    // Format a message explaining the actions taken.
    //
    final StringBuilder msgbuf = new StringBuilder();
    for (final ApprovalType at : types.getApprovalTypes()) {
      if (dirty.contains(at.getCategory().getId())) {
        final PatchSetApproval a = mine.get(at.getCategory().getId());
        if (a.getValue() == 0 && ins.contains(a)) {
          // Don't say "no score" for an initial entry.
          continue;
        }

        final ApprovalCategoryValue val = at.getValue(a);
        if (msgbuf.length() > 0) {
          msgbuf.append("; ");
        }
        if (val != null && val.getName() != null && !val.getName().isEmpty()) {
          msgbuf.append(val.getName());
        } else {
          msgbuf.append(at.getCategory().getName());
          msgbuf.append(" ");
          if (a.getValue() > 0) msgbuf.append('+');
          msgbuf.append(a.getValue());
        }
      }
    }

    // Update dashboards for everyone else.
    //
    for (PatchSetApproval a : all) {
      if (!user.getAccountId().equals(a.getAccountId())) {
        a.cache(change);
        upd.add(a);
      }
    }

    db.patchSetApprovals().update(upd);
    db.patchSetApprovals().insert(ins);

    summarizeInlineComments(msgbuf);
    message(msgbuf.toString());
  }

  private void publishMessageOnly() throws OrmException {
    StringBuilder msgbuf = new StringBuilder();
    summarizeInlineComments(msgbuf);
    message(msgbuf.toString());
  }

  private void message(String actions) throws OrmException {
    if ((actions == null || actions.isEmpty())
        && (messageText == null || messageText.isEmpty())) {
      // They had nothing to say?
      //
      return;
    }

    final StringBuilder msgbuf = new StringBuilder();
    msgbuf.append("Patch Set " + patchSetId.get() + ":");
    if (actions != null && !actions.isEmpty()) {
      msgbuf.append(" ");
      msgbuf.append(actions);
    }
    msgbuf.append("\n\n");
    msgbuf.append(messageText != null ? messageText : "");

    message = new ChangeMessage(new ChangeMessage.Key(change.getId(),//
        ChangeUtil.messageUUID(db)), user.getAccountId());
    message.setMessage(msgbuf.toString());
    db.changeMessages().insert(Collections.singleton(message));
  }

  private Map<ApprovalCategory.Id, PatchSetApproval> mine(
      Collection<PatchSetApproval> all) {
    Map<ApprovalCategory.Id, PatchSetApproval> r =
        new HashMap<ApprovalCategory.Id, PatchSetApproval>();
    for (PatchSetApproval a : all) {
      if (user.getAccountId().equals(a.getAccountId())) {
        r.put(a.getCategoryId(), a);
      }
    }
    return r;
  }

  private void touchChange() {
    try {
      ChangeUtil.touch(change, db);
    } catch (OrmException e) {
    }
  }

  private List<PatchLineComment> drafts() throws OrmException {
    return db.patchComments().draft(patchSetId, user.getAccountId()).toList();
  }

  private void email() {
    try {
      if (message != null) {
        final CommentSender cm = commentSenderFactory.create(change);
        cm.setFrom(user.getAccountId());
        cm.setPatchSet(patchSet, patchSetInfoFactory.get(patchSetId));
        cm.setChangeMessage(message);
        cm.setPatchLineComments(drafts);
        cm.send();
      }
    } catch (EmailException e) {
      log.error("Cannot send comments by email for patch set " + patchSetId, e);
    } catch (PatchSetInfoNotAvailableException e) {
      log.error("Failed to obtain PatchSetInfo for patch set " + patchSetId, e);
    }
  }

  private void fireHook() {
    final Map<ApprovalCategory.Id, ApprovalCategoryValue.Id> changed =
        new HashMap<ApprovalCategory.Id, ApprovalCategoryValue.Id>();
    for (ApprovalCategoryValue.Id v : approvals) {
      changed.put(v.getParentKey(), v);
    }

    hooks.doCommentAddedHook(change, user.getAccount(), patchSet, messageText, changed);
  }

  private void summarizeInlineComments(StringBuilder in) {
    if (!drafts.isEmpty()) {
      if (in.length() != 0) {
        in.append("\n\n");
      }
      if (drafts.size() == 1) {
        in.append("(1 inline comment)");
      } else {
        in.append("(" + drafts.size() + " inline comments)");
      }
    }
  }
}
