// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/**
 * @interface
 */
PerfUI.ChartViewportDelegate = function() {};

PerfUI.ChartViewportDelegate.prototype = {
  /**
   * @param {number} startTime
   * @param {number} endTime
   * @param {boolean} animate
   */
  windowChanged(startTime, endTime, animate) {},

  /**
   * @param {number} startTime
   * @param {number} endTime
   */
  updateRangeSelection(startTime, endTime) {},

  /**
   * @param {number} width
   * @param {number} height
   */
  setSize(width, height) {},

  update() {}
};

/**
 * @unrestricted
 */
PerfUI.ChartViewport = class extends UI.VBox {
  /**
   * @param {!PerfUI.ChartViewportDelegate} delegate
   */
  constructor(delegate) {
    super();
    this.registerRequiredCSS('perf_ui/chartViewport.css');

    this._delegate = delegate;

    this.viewportElement = this.contentElement.createChild('div', 'fill');
    this.viewportElement.addEventListener('mousemove', this._updateCursorPosition.bind(this), false);
    this.viewportElement.addEventListener('mouseout', this._onMouseOut.bind(this), false);
    this.viewportElement.addEventListener('mousewheel', this._onMouseWheel.bind(this), false);
    this.viewportElement.addEventListener('keydown', this._onChartKeyDown.bind(this), false);
    this.viewportElement.addEventListener('keyup', this._onChartKeyUp.bind(this), false);

    UI.installDragHandle(
        this.viewportElement, this._startDragging.bind(this), this._dragging.bind(this), this._endDragging.bind(this),
        '-webkit-grabbing', null);
    UI.installDragHandle(
        this.viewportElement, this._startRangeSelection.bind(this), this._rangeSelectionDragging.bind(this),
        this._endRangeSelection.bind(this), 'text', null);

    this._alwaysShowVerticalScroll = false;
    this._rangeSelectionEnabled = true;
    this._vScrollElement = this.contentElement.createChild('div', 'chart-viewport-v-scroll');
    this._vScrollContent = this._vScrollElement.createChild('div');
    this._vScrollElement.addEventListener('scroll', this._onScroll.bind(this), false);

    this._selectionOverlay = this.contentElement.createChild('div', 'chart-viewport-selection-overlay hidden');
    this._selectedTimeSpanLabel = this._selectionOverlay.createChild('div', 'time-span');

    this._cursorElement = this.contentElement.createChild('div', 'chart-cursor-element hidden');

    this.reset();
  }

  alwaysShowVerticalScroll() {
    this._alwaysShowVerticalScroll = true;
    this._vScrollElement.classList.add('always-show-scrollbar');
  }

  disableRangeSelection() {
    this._rangeSelectionEnabled = false;
    this._rangeSelectionStart = null;
    this._rangeSelectionEnd = null;
    this._updateRangeSelectionOverlay();
  }

  /**
   * @return {boolean}
   */
  isDragging() {
    return this._isDragging;
  }

  /**
   * @override
   * @return {!Array<!Element>}
   */
  elementsToRestoreScrollPositionsFor() {
    return [this._vScrollElement];
  }

  _updateScrollBar() {
    const showScroll = this._alwaysShowVerticalScroll || this._totalHeight > this._offsetHeight;
    if (this._vScrollElement.classList.contains('hidden') !== showScroll) {
      return;
    }
    this._vScrollElement.classList.toggle('hidden', !showScroll);
    this._updateContentElementSize();
  }

  /**
   * @override
   */
  onResize() {
    this._updateScrollBar();
    this._updateContentElementSize();
    this.scheduleUpdate();
  }

  reset() {
    this._vScrollElement.scrollTop = 0;
    this._scrollTop = 0;
    this._rangeSelectionStart = null;
    this._rangeSelectionEnd = null;
    this._isDragging = false;
    this._dragStartPointX = 0;
    this._dragStartPointY = 0;
    this._dragStartScrollTop = 0;
    this._visibleLeftTime = 0;
    this._visibleRightTime = 0;
    this._offsetWidth = 0;
    this._offsetHeight = 0;
    this._totalHeight = 0;
    this._targetLeftTime = 0;
    this._targetRightTime = 0;
    this._updateContentElementSize();
  }

  _updateContentElementSize() {
    let offsetWidth = this._vScrollElement.offsetLeft;
    if (!offsetWidth) {
      offsetWidth = this.contentElement.offsetWidth;
    }
    this._offsetWidth = offsetWidth;
    this._offsetHeight = this.contentElement.offsetHeight;
    this._delegate.setSize(this._offsetWidth, this._offsetHeight);
  }

  /**
   * @param {number} totalHeight
   */
  setContentHeight(totalHeight) {
    this._totalHeight = totalHeight;
    this._vScrollContent.style.height = totalHeight + 'px';
    this._updateScrollBar();
    if (this._scrollTop + this._offsetHeight <= totalHeight) {
      return;
    }
    this._scrollTop = Math.max(0, totalHeight - this._offsetHeight);
    this._vScrollElement.scrollTop = this._scrollTop;
  }

  /**
   * @param {number} offset
   * @param {number=} height
   */
  setScrollOffset(offset, height) {
    height = height || 0;
    if (this._vScrollElement.scrollTop > offset) {
      this._vScrollElement.scrollTop = offset;
    } else if (this._vScrollElement.scrollTop < offset - this._offsetHeight + height) {
      this._vScrollElement.scrollTop = offset - this._offsetHeight + height;
    }
  }

  /**
   * @return {number}
   */
  scrollOffset() {
    return this._vScrollElement.scrollTop;
  }

  /**
   * @param {number} zeroTime
   * @param {number} totalTime
   */
  setBoundaries(zeroTime, totalTime) {
    this._minimumBoundary = zeroTime;
    this._totalTime = totalTime;
  }

  /**
   * @param {!Event} e
   */
  _onMouseWheel(e) {
    const doZoomInstead = e.shiftKey ^ (Common.moduleSetting('flamechartMouseWheelAction').get() === 'zoom');
    const panVertically = !doZoomInstead && (e.wheelDeltaY || Math.abs(e.wheelDeltaX) === 120);
    const panHorizontally = doZoomInstead && Math.abs(e.wheelDeltaX) > Math.abs(e.wheelDeltaY);
    if (panVertically) {
      this._vScrollElement.scrollTop -= (e.wheelDeltaY || e.wheelDeltaX) / 120 * this._offsetHeight / 8;
    } else if (panHorizontally) {
      this._handlePanGesture(-e.wheelDeltaX, /* animate */ true);
    } else {  // Zoom.
      const mouseWheelZoomSpeed = 1 / 120;
      this._handleZoomGesture(Math.pow(1.2, -(e.wheelDeltaY || e.wheelDeltaX) * mouseWheelZoomSpeed) - 1);
    }

    // Block swipe gesture.
    e.consume(true);
  }

  /**
   * @param {!MouseEvent} event
   * @return {boolean}
   */
  _startDragging(event) {
    if (event.shiftKey) {
      return false;
    }
    this._isDragging = true;
    this._dragStartPointX = event.pageX;
    this._dragStartPointY = event.pageY;
    this._dragStartScrollTop = this._vScrollElement.scrollTop;
    this.viewportElement.style.cursor = '';
    return true;
  }

  /**
   * @param {!MouseEvent} event
   */
  _dragging(event) {
    const pixelShift = this._dragStartPointX - event.pageX;
    this._dragStartPointX = event.pageX;
    this._handlePanGesture(pixelShift);
    const pixelScroll = this._dragStartPointY - event.pageY;
    this._vScrollElement.scrollTop = this._dragStartScrollTop + pixelScroll;
  }

  _endDragging() {
    this._isDragging = false;
  }

  /**
   * @param {!MouseEvent} event
   * @return {boolean}
   */
  _startRangeSelection(event) {
    if (!event.shiftKey || !this._rangeSelectionEnabled) {
      return false;
    }
    this._isDragging = true;
    this._selectionOffsetShiftX = event.offsetX - event.pageX;
    this._selectionOffsetShiftY = event.offsetY - event.pageY;
    this._selectionStartX = event.offsetX;
    const style = this._selectionOverlay.style;
    style.left = this._selectionStartX + 'px';
    style.width = '1px';
    this._selectedTimeSpanLabel.textContent = '';
    this._selectionOverlay.classList.remove('hidden');
    return true;
  }

  _endRangeSelection() {
    this._isDragging = false;
    this._selectionStartX = null;
  }

  hideRangeSelection() {
    this._selectionOverlay.classList.add('hidden');
    this._rangeSelectionStart = null;
    this._rangeSelectionEnd = null;
  }

  /**
   * @param {number} startTime
   * @param {number} endTime
   */
  setRangeSelection(startTime, endTime) {
    if (!this._rangeSelectionEnabled) {
      return;
    }
    this._rangeSelectionStart = Math.min(startTime, endTime);
    this._rangeSelectionEnd = Math.max(startTime, endTime);
    this._updateRangeSelectionOverlay();
    this._delegate.updateRangeSelection(this._rangeSelectionStart, this._rangeSelectionEnd);
  }

  /**
   * @param {!Event} event
   */
  onClick(event) {
    const time = this.pixelToTime(event.offsetX);
    if (this._rangeSelectionStart !== null && time >= this._rangeSelectionStart && time <= this._rangeSelectionEnd) {
      return;
    }
    this.hideRangeSelection();
  }

  /**
   * @param {!MouseEvent} event
   */
  _rangeSelectionDragging(event) {
    const x = Number.constrain(event.pageX + this._selectionOffsetShiftX, 0, this._offsetWidth);
    const start = this.pixelToTime(this._selectionStartX);
    const end = this.pixelToTime(x);
    this.setRangeSelection(start, end);
  }

  _updateRangeSelectionOverlay() {
    const /** @const */ margin = 100;
    const left = Number.constrain(this.timeToPosition(this._rangeSelectionStart), -margin, this._offsetWidth + margin);
    const right = Number.constrain(this.timeToPosition(this._rangeSelectionEnd), -margin, this._offsetWidth + margin);
    const style = this._selectionOverlay.style;
    style.left = left + 'px';
    style.width = (right - left) + 'px';
    const timeSpan = this._rangeSelectionEnd - this._rangeSelectionStart;
    this._selectedTimeSpanLabel.textContent = Number.preciseMillisToString(timeSpan, 2);
  }

  _onScroll() {
    this._scrollTop = this._vScrollElement.scrollTop;
    this.scheduleUpdate();
  }

  _onMouseOut() {
    this._lastMouseOffsetX = -1;
    this._showCursor(false);
  }

  /**
   * @param {!Event} e
   */
  _updateCursorPosition(e) {
    this._showCursor(e.shiftKey);
    this._cursorElement.style.left = e.offsetX + 'px';
    this._lastMouseOffsetX = e.offsetX;
  }

  /**
   * @param {number} x
   * @return {number}
   */
  pixelToTime(x) {
    return this.pixelToTimeOffset(x) + this._visibleLeftTime;
  }

  /**
   * @param {number} x
   * @return {number}
   */
  pixelToTimeOffset(x) {
    return x * (this._visibleRightTime - this._visibleLeftTime) / this._offsetWidth;
  }

  /**
   * @param {number} time
   * @return {number}
   */
  timeToPosition(time) {
    return Math.floor(
        (time - this._visibleLeftTime) / (this._visibleRightTime - this._visibleLeftTime) * this._offsetWidth);
  }

  /**
   * @return {number}
   */
  timeToPixel() {
    return this._offsetWidth / (this._visibleRightTime - this._visibleLeftTime);
  }

  /**
   * @param {boolean} visible
   */
  _showCursor(visible) {
    this._cursorElement.classList.toggle('hidden', !visible || this._isDragging);
  }

  /**
   * @param {!Event} e
   */
  _onChartKeyDown(e) {
    this._showCursor(e.shiftKey);
    this._handleZoomPanKeys(e);
  }

  /**
   * @param {!Event} e
   */
  _onChartKeyUp(e) {
    this._showCursor(e.shiftKey);
  }

  /**
   * @param {!Event} e
   */
  _handleZoomPanKeys(e) {
    if (!UI.KeyboardShortcut.hasNoModifiers(e)) {
      return;
    }
    const zoomFactor = e.shiftKey ? 0.8 : 0.3;
    const panOffset = e.shiftKey ? 320 : 160;
    switch (e.code) {
      case 'KeyA':
        this._handlePanGesture(-panOffset, /* animate */ true);
        break;
      case 'KeyD':
        this._handlePanGesture(panOffset, /* animate */ true);
        break;
      case 'KeyW':
        this._handleZoomGesture(-zoomFactor);
        break;
      case 'KeyS':
        this._handleZoomGesture(zoomFactor);
        break;
      default:
        return;
    }
    e.consume(true);
  }

  /**
   * @param {number} zoom
   */
  _handleZoomGesture(zoom) {
    const bounds = {left: this._targetLeftTime, right: this._targetRightTime};
    const cursorTime = this.pixelToTime(this._lastMouseOffsetX);
    bounds.left += (bounds.left - cursorTime) * zoom;
    bounds.right += (bounds.right - cursorTime) * zoom;
    this._requestWindowTimes(bounds, /* animate */ true);
  }

  /**
   * @param {number} offset
   * @param {boolean=} animate
   */
  _handlePanGesture(offset, animate) {
    const bounds = {left: this._targetLeftTime, right: this._targetRightTime};
    const timeOffset = Number.constrain(
        this.pixelToTimeOffset(offset), this._minimumBoundary - bounds.left,
        this._totalTime + this._minimumBoundary - bounds.right);
    bounds.left += timeOffset;
    bounds.right += timeOffset;
    this._requestWindowTimes(bounds, !!animate);
  }

  /**
   * @param {!{left: number, right: number}} bounds
   * @param {boolean} animate
   */
  _requestWindowTimes(bounds, animate) {
    const maxBound = this._minimumBoundary + this._totalTime;
    if (bounds.left < this._minimumBoundary) {
      bounds.right = Math.min(bounds.right + this._minimumBoundary - bounds.left, maxBound);
      bounds.left = this._minimumBoundary;
    } else if (bounds.right > maxBound) {
      bounds.left = Math.max(bounds.left - bounds.right + maxBound, this._minimumBoundary);
      bounds.right = maxBound;
    }
    if (bounds.right - bounds.left < PerfUI.FlameChart.MinimalTimeWindowMs) {
      return;
    }
    this._delegate.windowChanged(bounds.left, bounds.right, animate);
  }

  scheduleUpdate() {
    if (this._updateTimerId || this._cancelWindowTimesAnimation) {
      return;
    }
    this._updateTimerId = this.element.window().requestAnimationFrame(() => {
      this._updateTimerId = 0;
      this._update();
    });
  }

  _update() {
    this._updateRangeSelectionOverlay();
    this._delegate.update();
  }

  /**
   * @param {number} startTime
   * @param {number} endTime
   * @param {boolean=} animate
   */
  setWindowTimes(startTime, endTime, animate) {
    if (startTime === this._targetLeftTime && endTime === this._targetRightTime) {
      return;
    }
    if (!animate || this._visibleLeftTime === 0 || this._visibleRightTime === Infinity ||
        (startTime === 0 && endTime === Infinity) || (startTime === Infinity && endTime === Infinity)) {
      // Skip animation, move instantly.
      this._targetLeftTime = startTime;
      this._targetRightTime = endTime;
      this._visibleLeftTime = startTime;
      this._visibleRightTime = endTime;
      this.scheduleUpdate();
      return;
    }
    if (this._cancelWindowTimesAnimation) {
      this._cancelWindowTimesAnimation();
      this._visibleLeftTime = this._targetLeftTime;
      this._visibleRightTime = this._targetRightTime;
    }
    this._targetLeftTime = startTime;
    this._targetRightTime = endTime;
    this._cancelWindowTimesAnimation = UI.animateFunction(
        this.element.window(), animateWindowTimes.bind(this),
        [{from: this._visibleLeftTime, to: startTime}, {from: this._visibleRightTime, to: endTime}], 100,
        () => this._cancelWindowTimesAnimation = null);

    /**
     * @param {number} startTime
     * @param {number} endTime
     * @this {PerfUI.ChartViewport}
     */
    function animateWindowTimes(startTime, endTime) {
      this._visibleLeftTime = startTime;
      this._visibleRightTime = endTime;
      this._update();
    }
  }

  /**
   * @return {number}
   */
  windowLeftTime() {
    return this._visibleLeftTime;
  }

  /**
   * @return {number}
   */
  windowRightTime() {
    return this._visibleRightTime;
  }
};
