// 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 static com.google.gerrit.common.data.LabelValue.formatValue;

import com.google.gerrit.client.ConfirmationCallback;
import com.google.gerrit.client.ConfirmationDialog;
import com.google.gerrit.client.ErrorDialog;
import com.google.gerrit.client.Gerrit;
import com.google.gerrit.client.account.AccountInfo;
import com.google.gerrit.client.changes.ChangeInfo.ApprovalInfo;
import com.google.gerrit.client.changes.ChangeInfo.LabelInfo;
import com.google.gerrit.client.rpc.GerritCallback;
import com.google.gerrit.client.rpc.NativeMap;
import com.google.gerrit.client.rpc.NativeString;
import com.google.gerrit.client.rpc.Natives;
import com.google.gerrit.client.ui.AccountLinkPanel;
import com.google.gerrit.client.ui.AddMemberBox;
import com.google.gerrit.client.ui.ReviewerSuggestOracle;
import com.google.gerrit.common.data.ApprovalDetail;
import com.google.gerrit.common.data.SubmitRecord;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.core.client.JsArray;
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.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

/** Displays a table of {@link ApprovalDetail} objects for a change record. */
public class ApprovalTable extends Composite {
  private final Grid table;
  private final Widget missing;
  private final Panel addReviewer;
  private final ReviewerSuggestOracle reviewerSuggestOracle;
  private final AddMemberBox addMemberBox;
  private ChangeInfo lastChange;
  private Map<Integer, Integer> rows;

  public ApprovalTable() {
    rows = new HashMap<Integer, Integer>();
    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(Collection<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());
  }

  void display(ChangeInfo change) {
    lastChange = change;
    reviewerSuggestOracle.setChange(change.legacy_id());
    Map<Integer, ApprovalDetail> byUser =
        new LinkedHashMap<Integer, ApprovalDetail>();
    Map<Integer, AccountInfo> accounts =
        new LinkedHashMap<Integer, AccountInfo>();
    List<String> missingLabels = initLabels(change, accounts, byUser);

    removeAllChildren(missing.getElement());
    for (String label : missingLabels) {
      addMissingLabel(Util.M.needApproval(label));
    }

    if (byUser.isEmpty()) {
      table.setVisible(false);
    } else {
      displayHeader(change.labels());
      table.resizeRows(1 + byUser.size());
      int i = 1;
      for (ApprovalDetail ad : ApprovalDetail.sort(
          byUser.values(), change.owner()._account_id())) {
        displayRow(i++, ad, change, accounts.get(ad.getAccount().get()));
      }
      table.setVisible(true);
    }

    if (Gerrit.getConfig().testChangeMerge()
        && change.status() != Change.Status.MERGED
        && !change.mergeable()) {
      addMissingLabel(Util.C.messageNeedsRebaseOrHasDependency());
    }
    missing.setVisible(DOM.getChildCount(missing.getElement()) > 0);
    addReviewer.setVisible(Gerrit.isSignedIn());
  }

  private void removeAllChildren(Element el) {
    for (int i = DOM.getChildCount(el) - 1; i >= 0; i--) {
      DOM.removeChild(el, DOM.getChild(el, i));
    }
  }

  private void addMissingLabel(String text) {
    Element li = DOM.createElement("li");
    li.setClassName(Gerrit.RESOURCES.css().missingApproval());
    DOM.setInnerText(li, text);
    DOM.appendChild(missing.getElement(), li);
  }

  private Set<Integer> removableReviewers(ChangeInfo change) {
    Set<Integer> result =
        new HashSet<Integer>(change.removable_reviewers().length());
    for (int i = 0; i < change.removable_reviewers().length(); i++) {
      result.add(change.removable_reviewers().get(i)._account_id());
    }
    return result;
  }

  private List<String> initLabels(ChangeInfo change,
      Map<Integer, AccountInfo> accounts,
      Map<Integer, ApprovalDetail> byUser) {
    Set<Integer> removableReviewers = removableReviewers(change);
    List<String> missing = new ArrayList<String>();
    for (String name : change.labels()) {
      LabelInfo label = change.label(name);

      String min = null;
      String max = null;
      for (String v : label.values()) {
        if (min == null) {
          min = v;
        }
        if (v.startsWith("+")) {
          max = v;
        }
      }

      if (label.status() == SubmitRecord.Label.Status.NEED) {
        missing.add(name);
      }

      if (label.all() != null) {
        for (ApprovalInfo ai : Natives.asList(label.all())) {
          if (!accounts.containsKey(ai._account_id())) {
            accounts.put(ai._account_id(), ai);
          }
          int id = ai._account_id();
          ApprovalDetail ad = byUser.get(id);
          if (ad == null) {
            ad = new ApprovalDetail(new Account.Id(id));
            ad.setCanRemove(removableReviewers.contains(id));
            byUser.put(id, ad);
          }
          if (ai.has_value()) {
            ad.votable(name);
            ad.value(name, ai.value());
            String fv = formatValue(ai.value());
            if (fv.equals(max)) {
              ad.approved(name);
            } else if (ai.value() < 0 && fv.equals(min)) {
              ad.rejected(name);
            }
          }
        }
      }
    }
    return missing;
  }

  private void doAddReviewer() {
    String reviewer = addMemberBox.getText();
    if (!reviewer.isEmpty()) {
      addMemberBox.setEnabled(false);
      addReviewer(reviewer, false);
    }
  }

  private static class PostInput extends JavaScriptObject {
    static PostInput create(String reviewer, boolean confirmed) {
      PostInput input = createObject().cast();
      input.init(reviewer, confirmed);
      return input;
    }

    private native void init(String reviewer, boolean confirmed) /*-{
      this.reviewer = reviewer;
      if (confirmed) {
        this.confirmed = true;
      }
    }-*/;

    protected PostInput() {
    }
  }

  private static class ReviewerInfo extends AccountInfo {
    final Set<String> approvals() {
      return Natives.keys(_approvals());
    }
    final native String approval(String l) /*-{ return this.approvals[l]; }-*/;
    private final native NativeMap<NativeString> _approvals() /*-{ return this.approvals; }-*/;

    protected ReviewerInfo() {
    }
  }

  private static class PostResult extends JavaScriptObject {
    final native JsArray<ReviewerInfo> reviewers() /*-{ return this.reviewers; }-*/;
    final native boolean confirm() /*-{ return this.confirm || false; }-*/;
    final native String error() /*-{ return this.error; }-*/;

    protected PostResult() {
    }
  }

  private void addReviewer(final String reviewer, boolean confirmed) {
    ChangeApi.reviewers(lastChange.legacy_id().get()).post(
        PostInput.create(reviewer, confirmed),
        new GerritCallback<PostResult>() {
          public void onSuccess(PostResult result) {
            addMemberBox.setEnabled(true);
            addMemberBox.setText("");
            if (result.error() == null) {
              reload();
            } else if (result.confirm()) {
              askForConfirmation(result.error());
            } else {
              new ErrorDialog(new SafeHtmlBuilder().append(result.error()));
            }
          }

          private void askForConfirmation(String text) {
            String title = Util.C
                .approvalTableAddManyReviewersConfirmationDialogTitle();
            ConfirmationDialog confirmationDialog = new ConfirmationDialog(
                title, new SafeHtmlBuilder().append(text),
                new ConfirmationCallback() {
                  @Override
                  public void onOk() {
                    addReviewer(reviewer, true);
                  }
                });
            confirmationDialog.center();
          }

          @Override
          public void onFailure(final Throwable caught) {
            addMemberBox.setEnabled(true);
            if (isNoSuchEntity(caught)) {
              new ErrorDialog(Util.M.reviewerNotFound(reviewer)).center();
            } else {
              super.onFailure(caught);
            }
          }
        });
  }

  private void displayRow(int row, final ApprovalDetail ad, ChangeInfo change,
      AccountInfo account) {
    final CellFormatter fmt = table.getCellFormatter();
    int col = 0;

    table.setWidget(row, col++, new AccountLinkPanel(account));
    rows.put(account._account_id(), row);

    if (ad.canRemove()) {
      final PushButton remove = new PushButton( //
          new Image(Util.R.removeReviewerNormal()), //
          new Image(Util.R.removeReviewerPressed()));
      remove.setTitle(Util.M.removeReviewer(account.name()));
      remove.setStyleName(Gerrit.RESOURCES.css().removeReviewer());
      remove.addStyleName(Gerrit.RESOURCES.css().link());
      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 : change.labels()) {
      fmt.setStyleName(row, col, Gerrit.RESOURCES.css().approvalscore());
      if (!ad.canVote(labelName)) {
        fmt.addStyleName(row, col, Gerrit.RESOURCES.css().notVotable());
        fmt.getElement(row, col).setTitle(Gerrit.C.userCannotVoteToolTip());
      }

      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 {
        int v = ad.getValue(labelName);
        if (v == 0) {
          table.clearCell(row, col);
          col++;
          continue;
        }
        String vstr = String.valueOf(ad.getValue(labelName));
        if (v > 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 reload() {
    ChangeApi.detail(lastChange.legacy_id().get(),
        new GerritCallback<ChangeInfo>() {
          @Override
          public void onSuccess(ChangeInfo result) {
            display(result);
          }
        });
  }

  private void doRemove(ApprovalDetail ad, final PushButton remove) {
    remove.setEnabled(false);
    ChangeApi.reviewer(lastChange.legacy_id().get(), ad.getAccount().get())
      .delete(new GerritCallback<JavaScriptObject>() {
          @Override
          public void onSuccess(JavaScriptObject result) {
            reload();
          }

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