// 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.changes.ChangeInfo.MessageInfo;
import com.google.gerrit.client.changes.CommentInfo;
import com.google.gerrit.client.changes.Util;
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);

  static 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()));
    } 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) {
      if (commentList == null) {
        history.load(info._revisionNumber());
      } else if (!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) : elide(authorName(info), 20));
  }

  private static String elide(final String s, final int len) {
    if (s == null || s.length() <= len || len <= 10) {
      return s;
    }
    int i = (len - 3) / 2;
    return s.substring(0, i) + "..." + s.substring(s.length() - i);
  }

  void autoOpen() {
    if (commentList == null) {
      autoOpen = true;
      history.load(info._revisionNumber());
    } 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));
    }
    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.getConfig().getAnonymousCowardName();
    }
    return Util.C.messageNoAuthor();
  }
}
