// 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.AvatarImage;
import com.google.gerrit.client.FormatUtil;
import com.google.gerrit.client.Gerrit;
import com.google.gerrit.client.api.ApiGlue;
import com.google.gerrit.client.changes.CommentInfo;
import com.google.gerrit.client.changes.Util;
import com.google.gerrit.client.info.ChangeInfo.MessageInfo;
import com.google.gerrit.client.ui.CommentLinkProcessor;
import com.google.gerrit.reviewdb.client.Patch;
import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.Style.Visibility;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.resources.client.CssResource;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.HTMLPanel;
import com.google.gwt.user.client.ui.UIObject;
import com.google.gwtexpui.safehtml.client.SafeHtmlBuilder;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

class Message extends Composite {
  interface Binder extends UiBinder<HTMLPanel, Message> {}

  private static final Binder uiBinder = GWT.create(Binder.class);

  interface Style extends CssResource {
    String closed();
  }

  @UiField Style style;
  @UiField HTMLPanel header;
  @UiField Element name;
  @UiField Element summary;
  @UiField Element date;
  @UiField Button reply;
  @UiField Element message;
  @UiField FlowPanel comments;

  private final History history;
  private final MessageInfo info;
  private List<CommentInfo> commentList;
  private boolean autoOpen;

  @UiField(provided = true)
  AvatarImage avatar;

  Message(History parent, MessageInfo info) {
    if (info.author() != null) {
      avatar = new AvatarImage(info.author());
      avatar.setSize("", "");
    } else {
      avatar = new AvatarImage();
    }

    initWidget(uiBinder.createAndBindUi(this));
    header.addDomHandler(
        new ClickHandler() {
          @Override
          public void onClick(ClickEvent event) {
            setOpen(!isOpen());
          }
        },
        ClickEvent.getType());

    this.history = parent;
    this.info = info;

    setName(false);
    date.setInnerText(FormatUtil.shortFormatDayTime(info.date()));
    if (info.message() != null) {
      String msg = info.message().trim();
      summary.setInnerText(msg);
      message.setInnerSafeHtml(
          history.getCommentLinkProcessor().apply(new SafeHtmlBuilder().append(msg).wikify()));
      ApiGlue.fireEvent("comment", message);
    } else {
      reply.getElement().getStyle().setVisibility(Visibility.HIDDEN);
    }
  }

  @UiHandler("reply")
  void onReply(ClickEvent e) {
    e.stopPropagation();

    if (Gerrit.isSignedIn()) {
      history.replyTo(info);
    } else {
      Gerrit.doSignIn(com.google.gwt.user.client.History.getToken());
    }
  }

  MessageInfo getMessageInfo() {
    return info;
  }

  private boolean isOpen() {
    return UIObject.isVisible(message);
  }

  void setOpen(boolean open) {
    if (open && info._revisionNumber() > 0 && !commentList.isEmpty()) {
      renderComments(commentList);
      commentList = Collections.emptyList();
    }
    setName(open);

    UIObject.setVisible(summary, !open);
    UIObject.setVisible(message, open);
    comments.setVisible(open && comments.getWidgetCount() > 0);
    if (open) {
      removeStyleName(style.closed());
    } else {
      addStyleName(style.closed());
    }
  }

  private void setName(boolean open) {
    name.setInnerText(
        open ? authorName(info) : com.google.gerrit.common.FormatUtil.elide(authorName(info), 20));
  }

  void autoOpen() {
    if (commentList == null) {
      autoOpen = true;
    } else if (!commentList.isEmpty()) {
      setOpen(true);
    }
  }

  void addComments(List<CommentInfo> list) {
    if (isOpen()) {
      renderComments(list);
      comments.setVisible(comments.getWidgetCount() > 0);
      commentList = Collections.emptyList();
    } else {
      commentList = list;
      if (autoOpen && !commentList.isEmpty()) {
        setOpen(true);
      }
    }
  }

  private void renderComments(List<CommentInfo> list) {
    CommentLinkProcessor clp = history.getCommentLinkProcessor();
    PatchSet.Id ps = new PatchSet.Id(history.getChangeId(), info._revisionNumber());
    TreeMap<String, List<CommentInfo>> m = byPath(list);
    List<CommentInfo> l = m.remove(Patch.COMMIT_MSG);
    if (l != null) {
      comments.add(new FileComments(clp, ps, Util.C.commitMessage(), l));
    }
    l = m.remove(Patch.MERGE_LIST);
    if (l != null) {
      comments.add(new FileComments(clp, ps, Util.C.mergeList(), l));
    }
    for (Map.Entry<String, List<CommentInfo>> e : m.entrySet()) {
      comments.add(new FileComments(clp, ps, e.getKey(), e.getValue()));
    }
  }

  private static TreeMap<String, List<CommentInfo>> byPath(List<CommentInfo> list) {
    TreeMap<String, List<CommentInfo>> m = new TreeMap<>();
    for (CommentInfo c : list) {
      List<CommentInfo> l = m.get(c.path());
      if (l == null) {
        l = new ArrayList<>();
        m.put(c.path(), l);
      }
      l.add(c);
    }
    return m;
  }

  static String authorName(MessageInfo info) {
    if (info.author() != null) {
      if (info.author().name() != null) {
        return info.author().name();
      }
      return Gerrit.info().user().anonymousCowardName();
    }
    return Util.C.messageNoAuthor();
  }
}
