// 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.patches.PatchUtil;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Style.Unit;
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.Anchor;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HTMLPanel;

import net.codemirror.lib.CodeMirror;
import net.codemirror.lib.Configuration;
import net.codemirror.lib.LineWidget;
import net.codemirror.lib.Pos;
import net.codemirror.lib.TextMarker;
import net.codemirror.lib.TextMarker.FromTo;

/** The Widget that handles expanding of skipped lines */
class SkipBar extends Composite {
  interface Binder extends UiBinder<HTMLPanel, SkipBar> {}
  private static final Binder uiBinder = GWT.create(Binder.class);
  private static final int NUM_ROWS_TO_EXPAND = 10;
  private static final int UP_DOWN_THRESHOLD = 30;

  interface SkipBarStyle extends CssResource {
    String noExpand();
  }

  @UiField(provided=true) Anchor skipNum;
  @UiField(provided=true) Anchor upArrow;
  @UiField(provided=true) Anchor downArrow;
  @UiField SkipBarStyle style;

  private final SkipManager manager;
  private final CodeMirror cm;

  private LineWidget lineWidget;
  private TextMarker textMarker;
  private SkipBar otherBar;

  SkipBar(SkipManager manager, final CodeMirror cm) {
    this.manager = manager;
    this.cm = cm;

    skipNum = new Anchor(true);
    upArrow = new Anchor(true);
    downArrow = new Anchor(true);
    initWidget(uiBinder.createAndBindUi(this));
    addDomHandler(new ClickHandler() {
      @Override
      public void onClick(ClickEvent event) {
        cm.focus();
      }
    }, ClickEvent.getType());
  }

  void collapse(int start, int end, boolean attach) {
    if (attach) {
      boolean isNew = lineWidget == null;
      Configuration cfg = Configuration.create()
          .set("coverGutter", true)
          .set("noHScroll", true);
      if (start == 0) { // First line workaround
        lineWidget = cm.addLineWidget(end + 1, getElement(), cfg.set("above", true));
      } else {
        lineWidget = cm.addLineWidget(start - 1, getElement(), cfg);
      }
      if (isNew) {
        lineWidget.onFirstRedraw(new Runnable() {
          @Override
          public void run() {
            int w = cm.getGutterElement().getOffsetWidth();
            getElement().getStyle().setPaddingLeft(w, Unit.PX);
          }
        });
      }
    }

    textMarker = cm.markText(
        Pos.create(start, 0),
        Pos.create(end),
        Configuration.create()
          .set("collapsed", true)
          .set("inclusiveLeft", true)
          .set("inclusiveRight", true));

    textMarker.on("beforeCursorEnter", new Runnable() {
      @Override
      public void run() {
        expandAll();
      }
    });

    int skipped = end - start + 1;
    if (skipped <= UP_DOWN_THRESHOLD) {
      addStyleName(style.noExpand());
    } else {
      upArrow.setHTML(PatchUtil.M.expandBefore(NUM_ROWS_TO_EXPAND));
      downArrow.setHTML(PatchUtil.M.expandAfter(NUM_ROWS_TO_EXPAND));
    }
    skipNum.setText(PatchUtil.M.patchSkipRegion(Integer
        .toString(skipped)));
  }

  static void link(SkipBar barA, SkipBar barB) {
    barA.otherBar = barB;
    barB.otherBar = barA;
  }

  private void clearMarkerAndWidget() {
    textMarker.clear();
    lineWidget.clear();
  }

  void expandBefore(int cnt) {
    expandSideBefore(cnt);
    otherBar.expandSideBefore(cnt);
  }

  private void expandSideBefore(int cnt) {
    FromTo range = textMarker.find();
    int oldStart = range.from().line();
    int newStart = oldStart + cnt;
    int end = range.to().line();
    clearMarkerAndWidget();
    collapse(newStart, end, true);
    updateSelection();
  }

  void expandSideAll() {
    clearMarkerAndWidget();
    removeFromParent();
  }

  private void expandAfter() {
    FromTo range = textMarker.find();
    int start = range.from().line();
    int oldEnd = range.to().line();
    int newEnd = oldEnd - NUM_ROWS_TO_EXPAND;
    boolean attach = start == 0;
    if (attach) {
      clearMarkerAndWidget();
    } else {
      textMarker.clear();
    }
    collapse(start, newEnd, attach);
    updateSelection();
  }

  private void updateSelection() {
    if (cm.somethingSelected()) {
      FromTo sel = cm.getSelectedRange();
      cm.setSelection(sel.from(), sel.to());
    }
  }

  @UiHandler("skipNum")
  void onExpandAll(@SuppressWarnings("unused") ClickEvent e) {
    expandAll();
    updateSelection();
    otherBar.updateSelection();
    cm.focus();
  }

  private void expandAll() {
    expandSideAll();
    otherBar.expandSideAll();
    manager.remove(this, otherBar);
  }

  @UiHandler("upArrow")
  void onExpandBefore(@SuppressWarnings("unused") ClickEvent e) {
    expandBefore(NUM_ROWS_TO_EXPAND);
    cm.focus();
  }

  @UiHandler("downArrow")
  void onExpandAfter(@SuppressWarnings("unused") ClickEvent e) {
    expandAfter();
    otherBar.expandAfter();
    cm.focus();
  }
}
