// 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.info.AccountInfo;
import com.google.gerrit.client.info.ChangeInfo;
import com.google.gerrit.client.info.ChangeInfo.CommitInfo;
import com.google.gerrit.client.info.ChangeInfo.GitPerson;
import com.google.gerrit.client.info.ChangeInfo.RevisionInfo;
import com.google.gerrit.client.info.WebLinkInfo;
import com.google.gerrit.client.rpc.Natives;
import com.google.gerrit.client.ui.CommentLinkProcessor;
import com.google.gerrit.client.ui.InlineHyperlink;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.common.PageLinks;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.JsArray;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.TableRowElement;
import com.google.gwt.event.dom.client.ClickEvent;
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.DOM;
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.HTML;
import com.google.gwt.user.client.ui.HTMLPanel;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.ScrollPanel;
import com.google.gwt.user.client.ui.UIObject;
import com.google.gwtexpui.clippy.client.CopyableLabel;
import com.google.gwtexpui.safehtml.client.SafeHtmlBuilder;

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

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

  interface Style extends CssResource {
    String collapsed();

    String expanded();

    String clippy();

    String parentWebLink();
  }

  @UiField Style style;
  @UiField FlowPanel authorPanel;
  @UiField FlowPanel committerPanel;
  @UiField Image mergeCommit;
  @UiField CopyableLabel commitName;
  @UiField FlowPanel webLinkPanel;
  @UiField TableRowElement firstParent;
  @UiField FlowPanel parentCommits;
  @UiField FlowPanel parentWebLinks;
  @UiField InlineHyperlink authorNameEmail;
  @UiField Element authorDate;
  @UiField InlineHyperlink committerNameEmail;
  @UiField Element committerDate;
  @UiField CopyableLabel idText;
  @UiField HTML text;
  @UiField ScrollPanel scroll;
  @UiField Button more;
  @UiField Element parentNotCurrentText;
  private boolean expanded;

  CommitBox() {
    initWidget(uiBinder.createAndBindUi(this));
    addStyleName(style.collapsed());
  }

  void onShowView() {
    more.setVisible(scroll.getMaximumVerticalScrollPosition() > 0);
  }

  @UiHandler("more")
  void onMore(@SuppressWarnings("unused") ClickEvent e) {
    if (expanded) {
      removeStyleName(style.expanded());
      addStyleName(style.collapsed());
    } else {
      removeStyleName(style.collapsed());
      addStyleName(style.expanded());
    }
    expanded = !expanded;
  }

  void set(CommentLinkProcessor commentLinkProcessor, ChangeInfo change, String revision) {
    RevisionInfo revInfo = change.revision(revision);
    CommitInfo commit = revInfo.commit();

    commitName.setText(revision);
    idText.setText("Change-Id: " + change.changeId());
    idText.setPreviewText(change.changeId());

    formatLink(commit.author(), authorPanel, authorNameEmail, authorDate, change);
    formatLink(commit.committer(), committerPanel, committerNameEmail, committerDate, change);
    text.setHTML(
        commentLinkProcessor.apply(new SafeHtmlBuilder().append(commit.message()).linkify()));
    setWebLinks(webLinkPanel, revInfo.commit());

    if (revInfo.commit().parents().length() > 1) {
      mergeCommit.setVisible(true);
    }

    setParents(revInfo.commit().parents());
  }

  void setParentNotCurrent(boolean parentNotCurrent) {
    // display the orange ball if parent has moved on (not current)
    UIObject.setVisible(parentNotCurrentText, parentNotCurrent);
    parentNotCurrentText.setInnerText(parentNotCurrent ? "\u25CF" : "");
  }

  private void setWebLinks(FlowPanel panel, CommitInfo commit) {
    JsArray<WebLinkInfo> links = commit.webLinks();
    if (links != null) {
      for (WebLinkInfo link : Natives.asList(links)) {
        panel.add(link.toAnchor());
      }
    }
  }

  private void setParents(JsArray<CommitInfo> commits) {
    setVisible(firstParent, true);
    TableRowElement next = firstParent;
    TableRowElement previous = null;
    for (CommitInfo c : Natives.asList(commits)) {
      if (next == firstParent) {
        CopyableLabel copyLabel = getCommitLabel(c);
        parentCommits.add(copyLabel);
        setWebLinks(parentWebLinks, c);
      } else {
        next.appendChild(DOM.createTD());
        Element td1 = DOM.createTD();
        td1.appendChild(getCommitLabel(c).getElement());
        next.appendChild(td1);
        FlowPanel linksPanel = new FlowPanel();
        linksPanel.addStyleName(style.parentWebLink());
        setWebLinks(linksPanel, c);
        Element td2 = DOM.createTD();
        td2.appendChild(linksPanel.getElement());
        next.appendChild(td2);
        previous.getParentElement().insertAfter(next, previous);
      }
      previous = next;
      next = DOM.createTR().cast();
    }
  }

  private CopyableLabel getCommitLabel(CommitInfo c) {
    CopyableLabel copyLabel;
    copyLabel = new CopyableLabel(c.commit());
    copyLabel.setTitle(c.subject());
    copyLabel.setStyleName(style.clippy());
    return copyLabel;
  }

  private static void formatLink(
      GitPerson person, FlowPanel p, InlineHyperlink name, Element date, ChangeInfo change) {
    // only try to fetch the avatar image for author and committer if an avatar
    // plugin is installed, if the change owner has no avatar info assume that
    // no avatar plugin is installed
    if (change.owner().hasAvatarInfo()) {
      AvatarImage avatar;
      if (sameEmail(change.owner(), person)) {
        avatar = new AvatarImage(change.owner());
      } else {
        avatar = new AvatarImage(AccountInfo.create(0, person.name(), person.email(), null));
      }
      p.insert(avatar, 0);
    }

    name.setText(renderName(person));
    name.setTargetHistoryToken(PageLinks.toAccountQuery(owner(person), change.status()));
    date.setInnerText(FormatUtil.mediumFormat(person.date()));
  }

  private static String renderName(GitPerson person) {
    return person.name() + " <" + person.email() + ">";
  }

  private static String owner(GitPerson person) {
    if (person.email() != null) {
      return person.email();
    } else if (person.name() != null) {
      return person.name();
    } else {
      return "";
    }
  }

  private static boolean sameEmail(@Nullable AccountInfo p1, @Nullable GitPerson p2) {
    return p1 != null
        && p2 != null
        && p1.email() != null
        && p2.email() != null
        && p1.email().equals(p2.email());
  }
}
