// 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.Gerrit;
import com.google.gerrit.client.change.RelatedChanges.ChangeAndCommit;
import com.google.gerrit.client.changes.Util;
import com.google.gerrit.client.info.ChangeInfo.CommitInfo;
import com.google.gerrit.common.PageLinks;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.JsArray;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.RepeatingCommand;
import com.google.gwt.dom.client.AnchorElement;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.NativeEvent;
import com.google.gwt.dom.client.Node;
import com.google.gwt.dom.client.NodeList;
import com.google.gwt.dom.client.Style;
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.event.dom.client.DoubleClickEvent;
import com.google.gwt.event.dom.client.DoubleClickHandler;
import com.google.gwt.event.dom.client.KeyPressEvent;
import com.google.gwt.event.dom.client.ScrollEvent;
import com.google.gwt.event.dom.client.ScrollHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.safehtml.shared.SafeHtml;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.AbstractImagePrototype;
import com.google.gwt.user.client.ui.InlineLabel;
import com.google.gwt.user.client.ui.IsWidget;
import com.google.gwt.user.client.ui.ScrollPanel;
import com.google.gwt.user.client.ui.SimplePanel;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.user.client.ui.impl.HyperlinkImpl;
import com.google.gwtexpui.globalkey.client.GlobalKey;
import com.google.gwtexpui.globalkey.client.KeyCommand;
import com.google.gwtexpui.globalkey.client.KeyCommandSet;
import com.google.gwtexpui.safehtml.client.SafeHtmlBuilder;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

class RelatedChangesTab implements IsWidget {
  private static final String OPEN = init(DOM.createUniqueId().replace('-', '_'));
  private static final HyperlinkImpl LINK = GWT.create(HyperlinkImpl.class);
  private static final SafeHtml POINTER_HTML =
      AbstractImagePrototype.create(Gerrit.RESOURCES.arrowRight()).getSafeHtml();

  private static native String init(String o) /*-{
    $wnd[o] = $entry(@com.google.gerrit.client.change.RelatedChangesTab::onOpen(
      Lcom/google/gwt/dom/client/NativeEvent;Lcom/google/gwt/dom/client/Element;));
    return o + '(event,this)';
  }-*/;

  private static boolean onOpen(NativeEvent evt, Element e) {
    if (LINK.handleAsClick(evt.<Event>cast())) {
      Gerrit.display(e.getAttribute("href").substring(1));
      evt.preventDefault();
      return false;
    }
    return true;
  }

  private final SimplePanel panel;
  private final RelatedChanges.Tab subject;

  private boolean showBranches;
  private boolean showProjects;
  private boolean showSubmittable;
  private boolean showIndirectAncestors;
  private boolean registerKeys;
  private int maxHeight;

  private String project;
  private NavigationList view;

  RelatedChangesTab(RelatedChanges.Tab subject) {
    panel = new SimplePanel();
    this.subject = subject;
  }

  @Override
  public Widget asWidget() {
    return panel;
  }

  void setShowBranches(boolean showBranches) {
    this.showBranches = showBranches;
  }

  void setShowProjects(boolean showProjects) {
    this.showProjects = showProjects;
  }

  void setShowSubmittable(boolean submittable) {
    this.showSubmittable = submittable;
  }

  void setShowIndirectAncestors(boolean showIndirectAncestors) {
    this.showIndirectAncestors = showIndirectAncestors;
  }

  void setMaxHeight(int height) {
    maxHeight = height;
    if (view != null) {
      view.setHeight(height + "px");
      view.ensureRowMeasurements();
      view.movePointerTo(view.selectedRow, true);
    }
  }

  void registerKeys(boolean on) {
    registerKeys = on;
    if (view != null) {
      view.setRegisterKeys(on);
    }
  }

  void setError(String message) {
    panel.setWidget(new InlineLabel(message));
    view = null;
    project = null;
  }

  void setChanges(String project, String revision, JsArray<ChangeAndCommit> changes) {
    if (0 == changes.length()) {
      setError(Resources.C.noChanges());
      return;
    }

    this.project = project;
    view = new NavigationList();
    panel.setWidget(view);

    DisplayCommand display = new DisplayCommand(revision, changes, view);
    if (display.execute()) {
      Scheduler.get().scheduleIncremental(display);
    }
  }

  private final class DisplayCommand implements RepeatingCommand {
    private final String revision;
    private final JsArray<ChangeAndCommit> changes;
    private final List<SafeHtml> rows;
    private final Set<String> connected;
    private final NavigationList navList;

    private double start;
    private int row;
    private int connectedPos;
    private int selected;

    private DisplayCommand(
        String revision, JsArray<ChangeAndCommit> changes, NavigationList navList) {
      this.revision = revision;
      this.changes = changes;
      this.navList = navList;
      rows = new ArrayList<>(changes.length());
      connectedPos = changes.length() - 1;
      connected =
          showIndirectAncestors ? new HashSet<>(Math.max(changes.length() * 4 / 3, 16)) : null;
    }

    private boolean computeConnected() {
      // Since TOPO sorted, when can walk the list in reverse and find all
      // the connections.
      if (!connected.contains(revision)) {
        while (connectedPos >= 0) {
          CommitInfo c = changes.get(connectedPos).commit();
          connected.add(c.commit());
          if (longRunning(--connectedPos)) {
            return true;
          }
          if (c.commit().equals(revision)) {
            break;
          }
        }
      }
      while (connectedPos >= 0) {
        CommitInfo c = changes.get(connectedPos).commit();
        for (int j = 0; j < c.parents().length(); j++) {
          if (connected.contains(c.parents().get(j).commit())) {
            connected.add(c.commit());
            break;
          }
        }
        if (longRunning(--connectedPos)) {
          return true;
        }
      }
      return false;
    }

    @Override
    public boolean execute() {
      if (navList != view || !panel.isAttached()) {
        // If the user navigated away, we aren't in the DOM anymore.
        // Don't continue to render.
        return false;
      }

      start = System.currentTimeMillis();

      if (connected != null && computeConnected()) {
        return true;
      }

      while (row < changes.length()) {
        ChangeAndCommit info = changes.get(row);
        String commit = info.commit().commit();
        rows.add(new RowSafeHtml(info, connected != null && !connected.contains(commit)));
        if (revision.equals(commit)) {
          selected = row;
        }
        if (longRunning(++row)) {
          return true;
        }
      }

      navList.rows = rows;
      navList.ensureRowMeasurements();
      navList.movePointerTo(selected, true);
      return false;
    }

    private boolean longRunning(int i) {
      return (i % 10) == 0 && System.currentTimeMillis() - start > 50;
    }
  }

  private class RowSafeHtml implements SafeHtml {
    private static final long serialVersionUID = 1L;

    private String html;
    private ChangeAndCommit info;
    private final boolean notConnected;

    RowSafeHtml(ChangeAndCommit info, boolean notConnected) {
      this.info = info;
      this.notConnected = notConnected;
    }

    @Override
    public String asString() {
      if (html == null) {
        SafeHtmlBuilder sb = new SafeHtmlBuilder();
        renderRow(sb);
        html = sb.asString();
        info = null;
      }
      return html;
    }

    private void renderRow(SafeHtmlBuilder sb) {
      sb.openDiv().setStyleName(RelatedChanges.R.css().row());

      sb.openSpan().setStyleName(RelatedChanges.R.css().pointer());
      sb.append(POINTER_HTML);
      sb.closeSpan();

      if (info.status() == Change.Status.ABANDONED) {
        sb.openSpan().setStyleName(RelatedChanges.R.css().strikedSubject());
      } else {
        sb.openSpan().setStyleName(RelatedChanges.R.css().subject());
      }
      sb.setAttribute("data-branch", info.branch());
      sb.setAttribute("data-project", info.project());
      String url = url();
      if (url != null) {
        sb.openAnchor().setAttribute("href", url);
        if (url.startsWith("#")) {
          sb.setAttribute("onclick", OPEN);
        }
        sb.setAttribute("title", info.commit().subject());
        if (showProjects) {
          sb.append(info.project()).append(": ");
        }
        if (showBranches) {
          sb.append(info.branch()).append(": ");
        }
        sb.append(info.commit().subject());
        sb.closeAnchor();
      } else {
        sb.append(info.commit().subject());
      }
      sb.closeSpan();

      sb.openSpan();
      if (info.status() != null && !info.status().isOpen()) {
        sb.setStyleName(RelatedChanges.R.css().gitweb());
        sb.setAttribute("title", Util.toLongString(info.status()));
        sb.append('\u25CF'); // Unicode 'BLACK CIRCLE'
      } else if (notConnected) {
        sb.setStyleName(RelatedChanges.R.css().indirect());
        sb.setAttribute("title", Resources.C.indirectAncestor());
        sb.append('~');
      } else if (info.hasCurrentRevisionNumber()
          && info.hasRevisionNumber()
          && info._currentRevisionNumber() != info._revisionNumber()) {
        sb.setStyleName(RelatedChanges.R.css().notCurrent());
        sb.setAttribute("title", Util.C.notCurrent());
        sb.append('\u25CF'); // Unicode 'BLACK CIRCLE'
      } else if (showSubmittable && info.submittable()) {
        sb.setStyleName(RelatedChanges.R.css().submittable());
        sb.setAttribute("title", Util.C.submittable());
        sb.append('\u2713'); // Unicode 'CHECK MARK'
      } else {
        sb.setStyleName(RelatedChanges.R.css().current());
      }
      sb.closeSpan();

      sb.closeDiv();
    }

    private String url() {
      if (info.hasChangeNumber() && info.hasRevisionNumber()) {
        return "#" + PageLinks.toChange(new Project.NameKey(info.project()), info.patchSetId());
      }
      return null;
    }
  }

  private class NavigationList extends ScrollPanel
      implements ClickHandler, DoubleClickHandler, ScrollHandler {
    private final KeyCommandSet keysNavigation;
    private final Element body;
    private final Element surrogate;
    private final Node fragment = createDocumentFragment();

    List<SafeHtml> rows;
    private HandlerRegistration regNavigation;
    private int selectedRow;
    private int startRow;
    private int rowHeight;
    private int rowWidth;

    NavigationList() {
      addDomHandler(this, ClickEvent.getType());
      addDomHandler(this, DoubleClickEvent.getType());
      addScrollHandler(this);

      keysNavigation = new KeyCommandSet(Resources.C.relatedChanges());
      keysNavigation.add(
          new KeyCommand(0, 'K', Resources.C.previousChange()) {
            @Override
            public void onKeyPress(KeyPressEvent event) {
              movePointerTo(selectedRow - 1, true);
            }
          },
          new KeyCommand(0, 'J', Resources.C.nextChange()) {
            @Override
            public void onKeyPress(KeyPressEvent event) {
              movePointerTo(selectedRow + 1, true);
            }
          });
      keysNavigation.add(
          new KeyCommand(0, 'O', Resources.C.openChange()) {
            @Override
            public void onKeyPress(KeyPressEvent event) {
              onOpenRow(getRow(selectedRow));
            }
          });

      if (maxHeight > 0) {
        setHeight(maxHeight + "px");
      }

      body = DOM.createDiv();
      body.getStyle().setPosition(Style.Position.RELATIVE);
      body.getStyle().setVisibility(Visibility.HIDDEN);
      getContainerElement().appendChild(body);

      surrogate = DOM.createDiv();
      surrogate.getStyle().setVisibility(Visibility.HIDDEN);
    }

    private boolean ensureRowMeasurements() {
      if (rowHeight == 0 && rows != null) {
        surrogate.setInnerSafeHtml(rows.get(0));
        getContainerElement().appendChild(surrogate);
        rowHeight = surrogate.getOffsetHeight();
        rowWidth = surrogate.getOffsetWidth();
        getContainerElement().removeChild(surrogate);
        getContainerElement().getStyle().setHeight(rowHeight * rows.size(), Style.Unit.PX);
        return true;
      }
      return false;
    }

    public void movePointerTo(int row, boolean scroll) {
      if (rows != null && 0 <= row && row < rows.size()) {
        renderSelected(selectedRow, false);
        selectedRow = row;

        if (scroll && rowHeight != 0) {
          // Position the selected row in the middle.
          setVerticalScrollPosition(Math.max(rowHeight * selectedRow - maxHeight / 2, 0));
          render();
        }
        renderSelected(selectedRow, true);
      }
    }

    private void renderSelected(int row, boolean selected) {
      Element e = getRow(row);
      if (e != null) {
        if (selected) {
          e.addClassName(RelatedChanges.R.css().activeRow());
        } else {
          e.removeClassName(RelatedChanges.R.css().activeRow());
        }
      }
    }

    private void render() {
      if (rows == null || rowHeight == 0) {
        return;
      }

      int currStart = startRow;
      int currEnd = startRow + body.getChildCount();

      int vpos = getVerticalScrollPosition();
      int start = Math.max(vpos / rowHeight - 5, 0);
      int end = Math.min((vpos + maxHeight) / rowHeight + 5, rows.size());
      if (currStart <= start && end <= currEnd) {
        return; // All of the required nodes are already in the DOM.
      }

      if (end <= currStart) {
        renderRange(start, end, true, true);
      } else if (start < currStart) {
        renderRange(start, currStart, false, true);
      } else if (start >= currEnd) {
        renderRange(start, end, true, false);
      } else if (end > currEnd) {
        renderRange(currEnd, end, false, false);
      }

      renderSelected(selectedRow, true);

      if (currEnd == 0) {
        // Account for the scroll bars
        int width = body.getOffsetWidth();
        if (rowWidth > width) {
          int w = 2 * rowWidth - width;
          setWidth(w + "px");
        }
        body.getStyle().clearVisibility();
      }
    }

    private void renderRange(int start, int end, boolean removeAll, boolean insertFirst) {
      SafeHtmlBuilder sb = new SafeHtmlBuilder();
      for (int i = start; i < end; i++) {
        sb.append(rows.get(i));
      }

      if (removeAll) {
        body.setInnerSafeHtml(sb);
      } else {
        surrogate.setInnerSafeHtml(sb);
        for (int cnt = surrogate.getChildCount(); cnt > 0; cnt--) {
          fragment.appendChild(surrogate.getFirstChild());
        }
        if (insertFirst) {
          body.insertFirst(fragment);
        } else {
          body.appendChild(fragment);
        }
      }

      if (insertFirst || removeAll) {
        startRow = start;
        body.getStyle().setTop(start * rowHeight, Style.Unit.PX);
      }
    }

    @Override
    public void onClick(ClickEvent event) {
      Element row = getRow(event.getNativeEvent().getEventTarget().<Element>cast());
      if (row != null) {
        movePointerTo(startRow + DOM.getChildIndex(body, row), false);
        event.stopPropagation();
      }
      saveSelectedTab();
    }

    @Override
    public void onDoubleClick(DoubleClickEvent event) {
      Element row = getRow(event.getNativeEvent().getEventTarget().<Element>cast());
      if (row != null) {
        movePointerTo(startRow + DOM.getChildIndex(body, row), false);
        onOpenRow(row);
        event.stopPropagation();
      }
    }

    @Override
    public void onScroll(ScrollEvent event) {
      render();
    }

    private Element getRow(Element e) {
      for (Element prev = e; e != null; prev = e) {
        if ((e = DOM.getParent(e)) == body) {
          return prev;
        }
      }
      return null;
    }

    private Element getRow(int row) {
      if (startRow <= row && row < startRow + body.getChildCount()) {
        return body.getChild(row - startRow).cast();
      }
      return null;
    }

    private void onOpenRow(Element row) {
      // Find the first HREF of the anchor of the select row (if any)
      if (row != null) {
        NodeList<Element> nodes = row.getElementsByTagName(AnchorElement.TAG);
        for (int i = 0; i < nodes.getLength(); i++) {
          String url = nodes.getItem(i).getAttribute("href");
          if (!url.isEmpty()) {
            if (url.startsWith("#")) {
              Gerrit.display(url.substring(1));
            } else {
              Window.Location.assign(url);
            }
            break;
          }
        }
      }

      saveSelectedTab();
    }

    private void saveSelectedTab() {
      RelatedChanges.setSavedTab(subject);
    }

    @Override
    protected void onLoad() {
      super.onLoad();
      setRegisterKeys(registerKeys);
    }

    @Override
    protected void onUnload() {
      setRegisterKeys(false);
      super.onUnload();
    }

    public void setRegisterKeys(boolean on) {
      if (on && isAttached()) {
        if (regNavigation == null) {
          regNavigation = GlobalKey.add(this, keysNavigation);
        }
        if (view.ensureRowMeasurements()) {
          view.movePointerTo(view.selectedRow, true);
        }
      } else if (regNavigation != null) {
        regNavigation.removeHandler();
        regNavigation = null;
      }
    }
  }

  private static native Node createDocumentFragment() /*-{
    return $doc.createDocumentFragment();
  }-*/;
}
