// Copyright (C) 2013 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.change;

import com.google.gerrit.client.Gerrit;
import com.google.gerrit.client.changes.ChangeApi;
import com.google.gerrit.client.changes.Util;
import com.google.gerrit.client.info.AccountInfo;
import com.google.gerrit.client.info.AccountInfo.AvatarInfo;
import com.google.gerrit.client.info.ChangeInfo;
import com.google.gerrit.client.info.ChangeInfo.ApprovalInfo;
import com.google.gerrit.client.info.ChangeInfo.LabelInfo;
import com.google.gerrit.client.rpc.GerritCallback;
import com.google.gerrit.client.rpc.Natives;
import com.google.gerrit.common.PageLinks;
import com.google.gerrit.common.data.LabelValue;
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.NativeEvent;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.ui.Grid;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwtexpui.safehtml.client.SafeHtml;
import com.google.gwtexpui.safehtml.client.SafeHtmlBuilder;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

/** Displays a table of label and reviewer scores. */
class Labels extends Grid {
  private static final String DATA_ID = "data-id";
  private static final String DATA_VOTE = "data-vote";
  private static final String REMOVE_REVIEWER;
  private static final String REMOVE_VOTE;

  static {
    REMOVE_REVIEWER = DOM.createUniqueId().replace('-', '_');
    REMOVE_VOTE = DOM.createUniqueId().replace('-', '_');
    init(REMOVE_REVIEWER, REMOVE_VOTE);
  }

  private static final native void init(String r, String v) /*-{
    $wnd[r] = $entry(function(e) {
      @com.google.gerrit.client.change.Labels::onRemoveReviewer(Lcom/google/gwt/dom/client/NativeEvent;)(e)
    });
    $wnd[v] = $entry(function(e) {
      @com.google.gerrit.client.change.Labels::onRemoveVote(Lcom/google/gwt/dom/client/NativeEvent;)(e)
    });
  }-*/;

  private static void onRemoveReviewer(NativeEvent event) {
    Integer user = getDataId(event);
    if (user != null) {
      final ChangeScreen screen = ChangeScreen.get(event);
      ChangeApi.reviewer(screen.getChangeId().get(), user).delete(
          new GerritCallback<JavaScriptObject>() {
            @Override
            public void onSuccess(JavaScriptObject result) {
              if (screen.isCurrentView()) {
                Gerrit.display(PageLinks.toChange(screen.getChangeId()));
              }
            }
          });
    }
  }

  private static void onRemoveVote(NativeEvent event) {
    Integer user = getDataId(event);
    String vote = getVoteId(event);
    if (user != null && vote != null) {
      final ChangeScreen screen = ChangeScreen.get(event);
      ChangeApi.vote(screen.getChangeId().get(), user, vote).delete(
          new GerritCallback<JavaScriptObject>() {
            @Override
            public void onSuccess(JavaScriptObject result) {
              if (screen.isCurrentView()) {
                Gerrit.display(PageLinks.toChange(screen.getChangeId()));
              }
            }
          });
    }
  }

  private static Integer getDataId(NativeEvent event) {
    Element e = event.getEventTarget().cast();
    while (e != null) {
      String v = e.getAttribute(DATA_ID);
      if (!v.isEmpty()) {
        return Integer.parseInt(v);
      }
      e = e.getParentElement();
    }
    return null;
  }

  private static String getVoteId(NativeEvent event) {
    Element e = event.getEventTarget().cast();
    while (e != null) {
      String v = e.getAttribute(DATA_VOTE);
      if (!v.isEmpty()) {
        return v;
      }
      e = e.getParentElement();
    }
    return null;
  }

  private ChangeScreen.Style style;

  void init(ChangeScreen.Style style) {
    this.style = style;
  }

  void set(ChangeInfo info) {
    List<String> names = new ArrayList<>(info.labels());
    Set<Integer> removable = info.removableReviewerIds();
    Collections.sort(names);

    resize(names.size(), 2);

    for (int row = 0; row < names.size(); row++) {
      String name = names.get(row);
      LabelInfo label = info.label(name);
      setText(row, 0, name);
      if (label.all() != null) {
        setWidget(row, 1, renderUsers(label, removable));
      }
      getCellFormatter().setStyleName(row, 0, style.labelName());
      getCellFormatter().addStyleName(row, 0, getStyleForLabel(label));
    }
  }

  private Widget renderUsers(LabelInfo label, Set<Integer> removable) {
    Map<Integer, List<ApprovalInfo>> m = new HashMap<>(4);
    int approved = 0;
    int rejected = 0;

    for (ApprovalInfo ai : Natives.asList(label.all())) {
      if (ai.value() != 0) {
        List<ApprovalInfo> l = m.get(Integer.valueOf(ai.value()));
        if (l == null) {
          l = new ArrayList<>(label.all().length());
          m.put(Integer.valueOf(ai.value()), l);
        }
        l.add(ai);

        if (isRejected(label, ai)) {
          rejected = ai.value();
        } else if (isApproved(label, ai)) {
          approved = ai.value();
        }
      }
    }

    SafeHtmlBuilder html = new SafeHtmlBuilder();
    for (Integer v : sort(m.keySet(), approved, rejected)) {
      if (!html.isEmpty()) {
        html.br();
      }

      String val = LabelValue.formatValue(v.shortValue());
      html.openSpan();
      html.setAttribute("title", label.valueText(val));
      if (v.intValue() == approved) {
        html.setStyleName(style.label_ok());
      } else if (v.intValue() == rejected) {
        html.setStyleName(style.label_reject());
      }
      html.append(val).append(" ");
      html.append(formatUserList(style, m.get(v), removable,
          label.name(), null));
      html.closeSpan();
    }
    return html.toBlockWidget();
  }

  private static List<Integer> sort(Set<Integer> keySet, int a, int b) {
    List<Integer> r = new ArrayList<>(keySet);
    Collections.sort(r);
    if (keySet.contains(a)) {
      r.remove(Integer.valueOf(a));
      r.add(0, a);
    } else if (keySet.contains(b)) {
      r.remove(Integer.valueOf(b));
      r.add(0, b);
    }
    return r;
  }

  private static boolean isApproved(LabelInfo label, ApprovalInfo ai) {
    return label.approved() != null
        && label.approved()._accountId() == ai._accountId();
  }

  private static boolean isRejected(LabelInfo label, ApprovalInfo ai) {
    return label.rejected() != null
        && label.rejected()._accountId() == ai._accountId();
  }

  private String getStyleForLabel(LabelInfo label) {
    switch (label.status()) {
      case OK:
        return style.label_ok();
      case NEED:
        return style.label_need();
      case REJECT:
      case IMPOSSIBLE:
        return style.label_reject();
      default:
      case MAY:
        return style.label_may();
    }
  }

  static SafeHtml formatUserList(ChangeScreen.Style style,
      Collection<? extends AccountInfo> in,
      Set<Integer> removable,
      String label,
      Map<Integer, VotableInfo> votable) {
    List<AccountInfo> users = new ArrayList<>(in);
    Collections.sort(users, new Comparator<AccountInfo>() {
      @Override
      public int compare(AccountInfo a, AccountInfo b) {
        String as = name(a);
        String bs = name(b);
        if (as.isEmpty()) {
          return 1;
        } else if (bs.isEmpty()) {
          return -1;
        }
        return as.compareTo(bs);
      }

      private String name(AccountInfo a) {
        if (a.name() != null) {
          return a.name();
        } else if (a.email() != null) {
          return a.email();
        }
        return "";
      }
    });

    SafeHtmlBuilder html = new SafeHtmlBuilder();
    Iterator<? extends AccountInfo> itr = users.iterator();
    while (itr.hasNext()) {
      AccountInfo ai = itr.next();
      AvatarInfo img = ai.avatar(AvatarInfo.DEFAULT_SIZE);
      String name;
      if (ai.name() != null) {
        name = ai.name();
      } else if (ai.email() != null) {
        name = ai.email();
      } else {
        name = Integer.toString(ai._accountId());
      }

      String votableCategories = "";
      if (votable != null) {
        Set<String> s = votable.get(ai._accountId()).votableLabels();
        if (!s.isEmpty()) {
          StringBuilder sb = new StringBuilder(Util.C.votable());
          sb.append(" ");
          for (Iterator<String> it = s.iterator(); it.hasNext();) {
            sb.append(it.next());
            if (it.hasNext()) {
              sb.append(", ");
            }
          }
          votableCategories = sb.toString();
        }
      }
      html.openSpan()
          .setAttribute("role", "listitem")
          .setAttribute(DATA_ID, ai._accountId())
          .setAttribute("title", getTitle(ai, votableCategories))
          .setStyleName(style.label_user());
      if (label != null) {
        html.setAttribute(DATA_VOTE, label);
      }
      if (img != null) {
        html.openElement("img")
            .setStyleName(style.avatar())
            .setAttribute("src", img.url());
        if (img.width() > 0) {
          html.setAttribute("width", img.width());
        }
        if (img.height() > 0) {
          html.setAttribute("height", img.height());
        }
        html.closeSelf();
      }
      html.append(name);
      if (removable.contains(ai._accountId())) {
        html.openElement("button");
        if (label != null) {
          html.setAttribute("title", Util.M.removeVote(label))
              .setAttribute("onclick", REMOVE_VOTE + "(event)");
        } else {
          html.setAttribute("title", Util.M.removeReviewer(name))
              .setAttribute("onclick", REMOVE_REVIEWER + "(event)");
        }
        html.append("×")
            .closeElement("button");
      }
      html.closeSpan();
      if (itr.hasNext()) {
        html.append(' ');
      }
    }
    return html;
  }

  private static String getTitle(AccountInfo ai, String votableCategories) {
    String title = ai.email() != null ? ai.email() : "";
    if (!votableCategories.isEmpty()) {
      if (!title.isEmpty()) {
        title += " ";
      }
      title += votableCategories;
    }
    return title;
  }
}
