// 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.diff;

import com.google.gerrit.client.AvatarImage;
import com.google.gerrit.client.Dispatcher;
import com.google.gerrit.client.FormatUtil;
import com.google.gerrit.client.Gerrit;
import com.google.gerrit.client.changes.CommentApi;
import com.google.gerrit.client.changes.CommentInfo;
import com.google.gerrit.client.changes.Util;
import com.google.gerrit.client.patches.PatchUtil;
import com.google.gerrit.client.rpc.GerritCallback;
import com.google.gerrit.client.ui.CommentLinkProcessor;
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.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.HTMLPanel;
import com.google.gwt.user.client.ui.UIObject;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwtexpui.safehtml.client.SafeHtmlBuilder;

/** An HtmlPanel for displaying a published comment */
class PublishedBox extends CommentBox {
  interface Binder extends UiBinder<HTMLPanel, PublishedBox> {}
  private static final Binder uiBinder = GWT.create(Binder.class);

  static interface Style extends CssResource {
    String closed();
  }

  private final PatchSet.Id psId;
  private final CommentInfo comment;
  private DraftBox replyBox;

  @UiField Style style;
  @UiField Widget header;
  @UiField Element name;
  @UiField Element summary;
  @UiField Element date;
  @UiField Element message;
  @UiField Element buttons;
  @UiField Button reply;
  @UiField Button done;
  @UiField Button fix;

  @UiField(provided = true)
  AvatarImage avatar;

  PublishedBox(
      CommentGroup group,
      CommentLinkProcessor clp,
      PatchSet.Id psId,
      CommentInfo info,
      boolean open) {
    super(group, info.range());

    this.psId = psId;
    this.comment = 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());

    name.setInnerText(authorName(info));
    date.setInnerText(FormatUtil.shortFormatDayTime(info.updated()));
    if (info.message() != null) {
      String msg = info.message().trim();
      summary.setInnerText(msg);
      message.setInnerSafeHtml(clp.apply(
          new SafeHtmlBuilder().append(msg).wikify()));
    }

    fix.setVisible(open);
  }

  @Override
  CommentInfo getCommentInfo() {
    return comment;
  }

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

  @Override
  void setOpen(boolean open) {
    UIObject.setVisible(summary, !open);
    UIObject.setVisible(message, open);
    UIObject.setVisible(buttons, open && replyBox == null);
    if (open) {
      removeStyleName(style.closed());
    } else {
      addStyleName(style.closed());
    }
    super.setOpen(open);
  }

  void setReplyBox(DraftBox box) {
    replyBox = box;
    UIObject.setVisible(buttons, false);
    box.setReplyToBox(this);
  }

  void unregisterReplyBox() {
    replyBox = null;
    UIObject.setVisible(buttons, isOpen());
  }

  private void openReplyBox() {
    replyBox.setOpen(true);
    replyBox.setEdit(true);
  }

  void addReplyBox() {
    getCommentManager().addDraftBox(
      getCm().side(),
      CommentInfo.createReply(comment)).setEdit(true);
  }

  void doReply() {
    if (!Gerrit.isSignedIn()) {
      Gerrit.doSignIn(getCommentManager().getSideBySide().getToken());
    } else if (replyBox == null) {
      addReplyBox();
    } else {
      openReplyBox();
    }
  }

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

  @UiHandler("done")
  void onReplyDone(ClickEvent e) {
    e.stopPropagation();
    if (!Gerrit.isSignedIn()) {
      Gerrit.doSignIn(getCommentManager().getSideBySide().getToken());
    } else if (replyBox == null) {
      done.setEnabled(false);
      CommentInfo input = CommentInfo.createReply(comment);
      input.message(PatchUtil.C.cannedReplyDone());
      CommentApi.createDraft(psId, input,
          new GerritCallback<CommentInfo>() {
            @Override
            public void onSuccess(CommentInfo result) {
              done.setEnabled(true);
              setOpen(false);
              getCommentManager().addDraftBox(getCm().side(), result);
            }
          });
    } else {
      openReplyBox();
      setOpen(false);
    }
  }

  @UiHandler("fix")
  void onFix(ClickEvent e) {
    e.stopPropagation();
    String t = Dispatcher.toEditScreen(psId, comment.path(), comment.line());
    if (!Gerrit.isSignedIn()) {
      Gerrit.doSignIn(t);
    } else {
      Gerrit.display(t);
    }
  }

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