// 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.client.changes;

import com.google.gerrit.client.ConfirmationCallback;
import com.google.gerrit.client.ConfirmationDialog;
import com.google.gerrit.client.ErrorDialog;
import com.google.gerrit.client.FormatUtil;
import com.google.gerrit.client.Gerrit;
import com.google.gerrit.client.patches.PatchUtil;
import com.google.gerrit.client.rpc.GerritCallback;
import com.google.gerrit.client.ui.AccountLink;
import com.google.gerrit.client.ui.AddMemberBox;
import com.google.gerrit.client.ui.ReviewerSuggestOracle;
import com.google.gerrit.common.data.AccountInfoCache;
import com.google.gerrit.common.data.ApprovalDetail;
import com.google.gerrit.common.data.ApprovalType;
import com.google.gerrit.common.data.ApprovalTypes;
import com.google.gerrit.common.data.ChangeDetail;
import com.google.gerrit.common.data.PatchSetPublishDetail;
import com.google.gerrit.common.data.ReviewerResult;
import com.google.gerrit.common.data.SubmitRecord;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.PatchSetApproval;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.Grid;
import com.google.gwt.user.client.ui.HTMLTable.CellFormatter;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.user.client.ui.PushButton;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwtexpui.safehtml.client.SafeHtmlBuilder;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;

/** Displays a table of {@link ApprovalDetail} objects for a change record. */
public class ApprovalTable extends Composite {
  private final ApprovalTypes types;
  private final Grid table;
  private final Widget missing;
  private final Panel addReviewer;
  private final ReviewerSuggestOracle reviewerSuggestOracle;
  private final AddMemberBox addMemberBox;
  private Change.Id changeId;
  private AccountInfoCache accountCache = AccountInfoCache.empty();

  public ApprovalTable() {
    types = Gerrit.getConfig().getApprovalTypes();
    table = new Grid(1, 3);
    table.addStyleName(Gerrit.RESOURCES.css().infoTable());

    missing = new Widget() {
      {
        setElement(DOM.createElement("ul"));
      }
    };
    missing.setStyleName(Gerrit.RESOURCES.css().missingApprovalList());

    addReviewer = new FlowPanel();
    addReviewer.setStyleName(Gerrit.RESOURCES.css().addReviewer());
    reviewerSuggestOracle = new ReviewerSuggestOracle();
    addMemberBox =
        new AddMemberBox(Util.C.approvalTableAddReviewer(),
            Util.C.approvalTableAddReviewerHint(), reviewerSuggestOracle);
    addMemberBox.addClickHandler(new ClickHandler() {
      @Override
      public void onClick(final ClickEvent event) {
        doAddReviewer();
      }
    });
    addReviewer.add(addMemberBox);
    addReviewer.setVisible(false);

    final FlowPanel fp = new FlowPanel();
    fp.add(table);
    fp.add(missing);
    fp.add(addReviewer);
    initWidget(fp);

    setStyleName(Gerrit.RESOURCES.css().approvalTable());
  }

  private void displayHeader(List<String> labels) {
    table.resizeColumns(2 + labels.size());

    final CellFormatter fmt = table.getCellFormatter();
    int col = 0;

    table.setText(0, col, Util.C.approvalTableReviewer());
    fmt.setStyleName(0, col, Gerrit.RESOURCES.css().header());
    col++;

    table.clearCell(0, col);
    fmt.setStyleName(0, col, Gerrit.RESOURCES.css().header());
    col++;

    for (String name : labels) {
      table.setText(0, col, name);
      fmt.setStyleName(0, col, Gerrit.RESOURCES.css().header());
      col++;
    }
    fmt.addStyleName(0, col - 1, Gerrit.RESOURCES.css().rightmost());
  }

  public void setAccountInfoCache(final AccountInfoCache aic) {
    assert aic != null;
    accountCache = aic;
  }

  private AccountLink link(final Account.Id id) {
    return AccountLink.link(accountCache, id);
  }

  void display(PatchSetPublishDetail detail) {
    doDisplay(detail.getChange(), detail.getApprovals(),
        detail.getSubmitRecords());
  }

  void display(ChangeDetail detail) {
    doDisplay(detail.getChange(), detail.getApprovals(),
        detail.getSubmitRecords());
  }

  private void doDisplay(Change change, List<ApprovalDetail> approvals,
      List<SubmitRecord> submitRecords) {
    changeId = change.getId();
    reviewerSuggestOracle.setChange(changeId);

    List<String> columns = new ArrayList<String>();

    final Element missingList = missing.getElement();
    while (DOM.getChildCount(missingList) > 0) {
      DOM.removeChild(missingList, DOM.getChild(missingList, 0));
    }
    missing.setVisible(false);

    if (submitRecords != null) {
      HashSet<String> reportedMissing = new HashSet<String>();

      HashMap<Account.Id, ApprovalDetail> byUser =
          new HashMap<Account.Id, ApprovalDetail>();
      for (ApprovalDetail ad : approvals) {
        byUser.put(ad.getAccount(), ad);
      }

      for (SubmitRecord rec : submitRecords) {
        if (rec.labels == null) {
          continue;
        }

        for (SubmitRecord.Label lbl : rec.labels) {
          if (!columns.contains(lbl.label)) {
            columns.add(lbl.label);
          }

          switch (lbl.status) {
            case OK: {
              ApprovalDetail ad = byUser.get(lbl.appliedBy);
              if (ad != null) {
                ad.approved(lbl.label);
              }
              break;
            }

            case REJECT: {
              ApprovalDetail ad = byUser.get(lbl.appliedBy);
              if (ad != null) {
                ad.rejected(lbl.label);
              }
              break;
            }

            case MAY:
              break;

            case NEED:
            case IMPOSSIBLE:
              if (reportedMissing.add(lbl.label)) {
                Element li = DOM.createElement("li");
                li.setClassName(Gerrit.RESOURCES.css().missingApproval());
                DOM.setInnerText(li, Util.M.needApproval(lbl.label));
                DOM.appendChild(missingList, li);
              }
              break;
          }
        }
      }
      missing.setVisible(!reportedMissing.isEmpty());

    } else {
      for (ApprovalDetail ad : approvals) {
        for (PatchSetApproval psa : ad.getPatchSetApprovals()) {
          ApprovalType legacyType = types.byId(psa.getCategoryId());
          if (legacyType == null) {
            continue;
          }
          String labelName = legacyType.getCategory().getLabelName();
          if (psa.getValue() != 0 ) {
            if (psa.getValue() == legacyType.getMax().getValue()) {
              ad.approved(labelName);
            } else if (psa.getValue() == legacyType.getMin().getValue()) {
              ad.rejected(labelName);
            }
          }
          if (!columns.contains(labelName)) {
            columns.add(labelName);
          }
        }
        Collections.sort(columns, new Comparator<String>() {
          @Override
          public int compare(String o1, String o2) {
            ApprovalType a = types.byLabel(o1);
            ApprovalType b = types.byLabel(o2);
            int cmp = 0;
            if (a != null && b != null) {
              cmp = a.getCategory().getPosition() - b.getCategory().getPosition();
            }
            if (cmp == 0) {
              cmp = o1.compareTo(o2);
            }
            return cmp;
          }
        });
      }
    }

    if (approvals.isEmpty()) {
      table.setVisible(false);
    } else {
      displayHeader(columns);
      table.resizeRows(1 + approvals.size());
      for (int i = 0; i < approvals.size(); i++) {
        displayRow(i + 1, approvals.get(i), change, columns);
      }
      table.setVisible(true);
    }

    addReviewer.setVisible(Gerrit.isSignedIn());

    if (Gerrit.getConfig().testChangeMerge()
        && !change.isMergeable()) {
      Element li = DOM.createElement("li");
      li.setClassName(Gerrit.RESOURCES.css().missingApproval());
      DOM.setInnerText(li, Util.C.messageNeedsRebaseOrHasDependency());
      DOM.appendChild(missingList, li);
      missing.setVisible(true);
    }
  }

  private void doAddReviewer() {
    final String reviewer = addMemberBox.getText();
    if (reviewer.length() == 0) {
      return;
    }

    addMemberBox.setEnabled(false);
    final List<String> reviewers = new ArrayList<String>();
    reviewers.add(reviewer);

    addReviewers(reviewers, false);
  }

  private void addReviewers(final List<String> reviewers,
      final boolean confirmed) {
    PatchUtil.DETAIL_SVC.addReviewers(changeId, reviewers, confirmed,
        new GerritCallback<ReviewerResult>() {
          public void onSuccess(final ReviewerResult result) {
            addMemberBox.setEnabled(true);
            addMemberBox.setText("");

            final ChangeDetail changeDetail = result.getChange();
            if (changeDetail != null) {
              setAccountInfoCache(changeDetail.getAccounts());
              display(changeDetail);
            }

            if (!result.getErrors().isEmpty()) {
              final SafeHtmlBuilder r = new SafeHtmlBuilder();
              for (final ReviewerResult.Error e : result.getErrors()) {
                switch (e.getType()) {
                  case REVIEWER_NOT_FOUND:
                    r.append(Util.M.reviewerNotFound(e.getName()));
                    break;

                  case ACCOUNT_INACTIVE:
                    r.append(Util.M.accountInactive(e.getName()));
                    break;

                  case CHANGE_NOT_VISIBLE:
                    r.append(Util.M.changeNotVisibleTo(e.getName()));
                    break;

                  case GROUP_EMPTY:
                    r.append(Util.M.groupIsEmpty(e.getName()));
                    break;

                  case GROUP_HAS_TOO_MANY_MEMBERS:
                    if (result.askForConfirmation() && !confirmed) {
                      askForConfirmation(e.getName(), result.getMemberCount());
                      return;
                    } else {
                      r.append(Util.M.groupHasTooManyMembers(e.getName()));
                    }
                    break;

                  case GROUP_NOT_ALLOWED:
                    r.append(Util.M.groupIsNotAllowed(e.getName()));
                    break;

                  default:
                    r.append(e.getName());
                    r.append(" - ");
                    r.append(e.getType());
                    r.br();
                    break;
                }
              }
              new ErrorDialog(r).center();
            }
          }

          private void askForConfirmation(final String groupName,
              final int memberCount) {
            final SafeHtmlBuilder b = new SafeHtmlBuilder();
            b.openElement("b");
            b.append(Util.M
                .groupManyMembersConfirmation(groupName, memberCount));
            b.closeElement("b");
            final ConfirmationDialog confirmationDialog =
                new ConfirmationDialog(Util.C
                    .approvalTableAddManyReviewersConfirmationDialogTitle(),
                    b.toSafeHtml(), new ConfirmationCallback() {
                      @Override
                      public void onOk() {
                        addReviewers(reviewers, true);
                      }
                    });
            confirmationDialog.center();
          }

          @Override
          public void onFailure(final Throwable caught) {
            addMemberBox.setEnabled(true);
            super.onFailure(caught);
          }
        });
  }

  private void displayRow(final int row, final ApprovalDetail ad,
      final Change change, List<String> columns) {
    final CellFormatter fmt = table.getCellFormatter();
    int col = 0;

    table.setWidget(row, col++, link(ad.getAccount()));

    if (ad.canRemove()) {
      final PushButton remove = new PushButton( //
          new Image(Util.R.removeReviewerNormal()), //
          new Image(Util.R.removeReviewerPressed()));
      remove.setTitle(Util.M.removeReviewer( //
          FormatUtil.name(accountCache.get(ad.getAccount()))));
      remove.setStyleName(Gerrit.RESOURCES.css().removeReviewer());
      remove.addClickHandler(new ClickHandler() {
        @Override
        public void onClick(ClickEvent event) {
          doRemove(ad, remove);
        }
      });
      table.setWidget(row, col, remove);
    } else {
      table.clearCell(row, col);
    }
    fmt.setStyleName(row, col++, Gerrit.RESOURCES.css().removeReviewerCell());

    for (String labelName : columns) {
      fmt.setStyleName(row, col, Gerrit.RESOURCES.css().approvalscore());

      if (ad.isRejected(labelName)) {
        table.setWidget(row, col, new Image(Gerrit.RESOURCES.redNot()));

      } else if (ad.isApproved(labelName)) {
        table.setWidget(row, col, new Image(Gerrit.RESOURCES.greenCheck()));

      } else {
        ApprovalType legacyType = types.byLabel(labelName);
        if (legacyType == null) {
          table.clearCell(row, col);
          col++;
          continue;
        }

        PatchSetApproval ca = ad.getPatchSetApproval(legacyType.getCategory().getId());
        if (ca == null || ca.getValue() == 0) {
          table.clearCell(row, col);
          col++;
          continue;
        }

        String vstr = String.valueOf(ca.getValue());
        if (ca.getValue() > 0) {
          vstr = "+" + vstr;
          fmt.addStyleName(row, col, Gerrit.RESOURCES.css().posscore());
        } else {
          fmt.addStyleName(row, col, Gerrit.RESOURCES.css().negscore());
        }
        table.setText(row, col, vstr);
      }

      col++;
    }

    fmt.addStyleName(row, col - 1, Gerrit.RESOURCES.css().rightmost());
  }

  private void doRemove(final ApprovalDetail ad, final PushButton remove) {
    remove.setEnabled(false);
    PatchUtil.DETAIL_SVC.removeReviewer(changeId, ad.getAccount(),
        new GerritCallback<ReviewerResult>() {
          @Override
          public void onSuccess(ReviewerResult result) {
            if (result.getErrors().isEmpty()) {
              final ChangeDetail r = result.getChange();
              display(r);
            } else {
              final ReviewerResult.Error resultError =
                  result.getErrors().get(0);
              String message;
              switch (resultError.getType()) {
                case REMOVE_NOT_PERMITTED:
                  message = Util.C.approvalTableRemoveNotPermitted();
                  break;
                case COULD_NOT_REMOVE:
                default:
                  message = Util.C.approvalTableCouldNotRemove();
              }
              new ErrorDialog(message + " " + resultError.getName()).center();
            }
          }

          @Override
          public void onFailure(final Throwable caught) {
            remove.setEnabled(true);
            super.onFailure(caught);
          }
        });
  }
}
