// Copyright (C) 2010 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 com.google.gerrit.client.Gerrit;
import com.google.gerrit.client.rpc.GerritCallback;
import com.google.gerrit.client.ui.ChangeLink;
import com.google.gerrit.client.ui.CommentLinkProcessor;
import com.google.gerrit.client.ui.CommentedActionDialog;
import com.google.gerrit.client.ui.TextBoxChangeListener;
import com.google.gerrit.common.PageLinks;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.dom.client.PreElement;
import com.google.gwt.dom.client.Style.Display;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
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.Image;
import com.google.gwt.user.client.ui.SimplePanel;
import com.google.gwtexpui.clippy.client.CopyableLabel;
import com.google.gwtexpui.globalkey.client.KeyCommandSet;
import com.google.gwtexpui.safehtml.client.SafeHtml;
import com.google.gwtexpui.safehtml.client.SafeHtmlBuilder;
import com.google.gwtjsonrpc.common.AsyncCallback;

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

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

  private KeyCommandSet keysAction;

  @UiField
  SimplePanel starPanel;
  @UiField
  FlowPanel permalinkPanel;
  @UiField
  PreElement commitSummaryPre;
  @UiField
  PreElement commitBodyPre;

  public CommitMessageBlock() {
    initWidget(uiBinder.createAndBindUi(this));
  }

  public CommitMessageBlock(KeyCommandSet keysAction) {
    this.keysAction = keysAction;
    initWidget(uiBinder.createAndBindUi(this));
  }

  public void display(String commitMessage,
      CommentLinkProcessor commentLinkProcessor) {
    display(null, null, null, false, commitMessage, commentLinkProcessor);
  }

  private abstract class CommitMessageEditDialog
      extends CommentedActionDialog<JavaScriptObject> {
    private final String originalMessage;
    public CommitMessageEditDialog(final String title, final String heading,
        final String commitMessage, AsyncCallback<JavaScriptObject> callback) {
      super(title, heading, callback);
      originalMessage = commitMessage.trim();
      message.setCharacterWidth(72);
      message.setVisibleLines(20);
      message.setText(originalMessage);
      message.addStyleName(Gerrit.RESOURCES.css().changeScreenDescription());
      sendButton.setEnabled(false);

      new TextBoxChangeListener(message) {
        public void onTextChanged(String newText) {
          // Trim the new text so we don't consider trailing
          // newlines as changes
          sendButton.setEnabled(!newText.trim().equals(originalMessage));
        }
      };
    }

    public String getMessageText() {
      // As we rely on commit message lines ending in LF, we convert CRLF to
      // LF. Additionally, the commit message should be trimmed to remove any
      // excess newlines at the end, but we need to make sure it still has at
      // least one trailing newline.
      return message.getText().replaceAll("\r\n", "\n").trim() + '\n';
    }
  }

  public void display(final PatchSet.Id patchSetId, final String revision,
      Boolean starred, Boolean canEditCommitMessage, final String commitMessage,
      CommentLinkProcessor commentLinkProcessor) {
    starPanel.clear();
    if (patchSetId != null && starred != null && Gerrit.isSignedIn()) {
      Change.Id changeId = patchSetId.getParentKey();
      StarredChanges.Icon star = StarredChanges.createIcon(changeId, starred);
      star.setStyleName(Gerrit.RESOURCES.css().changeScreenStarIcon());
      starPanel.add(star);

      if (keysAction != null) {
        keysAction.add(StarredChanges.newKeyCommand(star));
      }
    }

    permalinkPanel.clear();
    if (patchSetId != null && revision != null) {
      final Change.Id changeId = patchSetId.getParentKey();
      permalinkPanel.add(new ChangeLink(Util.C.changePermalink(), changeId));
      permalinkPanel.add(new CopyableLabel(ChangeLink.permalink(changeId),
          false));
      if (canEditCommitMessage) {
        final Image edit = new Image(Gerrit.RESOURCES.edit());
        edit.setTitle(Util.C.editCommitMessageToolTip());
        edit.addStyleName(Gerrit.RESOURCES.css().link());
        edit.addClickHandler(new ClickHandler() {
          @Override
          public void onClick(final ClickEvent event) {
            new CommitMessageEditDialog(Util.C.titleEditCommitMessage(),
                Util.C.headingEditCommitMessage(),
                commitMessage,
                new GerritCallback<JavaScriptObject>() {
                  @Override
                  public void onSuccess(JavaScriptObject result) {}
                }) {
              @Override
              public void onSend() {
                ChangeApi.message(changeId.get(), revision, getMessageText(),
                    new GerritCallback<JavaScriptObject>() {
                      @Override
                      public void onSuccess(JavaScriptObject msg) {
                        Gerrit.display(PageLinks.toChange(changeId));
                        hide();
                      }
                    });
              }
            }.center();
          }
        });

        permalinkPanel.add(edit);
      }
    }

    String[] splitCommitMessage = commitMessage.split("\n", 2);

    String commitSummary = splitCommitMessage[0];
    String commitBody = "";
    if (splitCommitMessage.length > 1) {
      commitBody = splitCommitMessage[1];
    }

    // Linkify commit summary
    SafeHtml commitSummaryLinkified = new SafeHtmlBuilder().append(commitSummary);
    commitSummaryLinkified = commitSummaryLinkified.linkify();
    commitSummaryLinkified = commentLinkProcessor.apply(commitSummaryLinkified);
    commitSummaryPre.setInnerHTML(commitSummaryLinkified.asString());

    // Hide commit body if there is no body
    if (commitBody.trim().isEmpty()) {
      commitBodyPre.getStyle().setDisplay(Display.NONE);
    } else {
      // Linkify commit body
      SafeHtml commitBodyLinkified = new SafeHtmlBuilder().append(commitBody);
      commitBodyLinkified = commitBodyLinkified.linkify();
      commitBodyLinkified = commentLinkProcessor.apply(commitBodyLinkified);
      commitBodyLinkified = commitBodyLinkified.replaceAll("\n\n", "<p></p>");
      commitBodyLinkified = commitBodyLinkified.replaceAll("\n", "<br />");
      commitBodyPre.setInnerHTML(commitBodyLinkified.asString());
    }
  }
}
