/*
 * Copyright (C) 2013 Google Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/**
 * @unrestricted
 */
Console.ConsoleViewport = class {
  /**
   * @param {!Console.ConsoleViewportProvider} provider
   */
  constructor(provider) {
    this.element = createElement('div');
    this.element.style.overflow = 'auto';
    this._topGapElement = this.element.createChild('div');
    this._topGapElement.style.height = '0px';
    this._topGapElement.style.color = 'transparent';
    this._contentElement = this.element.createChild('div');
    this._bottomGapElement = this.element.createChild('div');
    this._bottomGapElement.style.height = '0px';
    this._bottomGapElement.style.color = 'transparent';

    // Text content needed for range intersection checks in _updateSelectionModel.
    // Use Unicode ZERO WIDTH NO-BREAK SPACE, which avoids contributing any height to the element's layout overflow.
    this._topGapElement.textContent = '\uFEFF';
    this._bottomGapElement.textContent = '\uFEFF';

    this._provider = provider;
    this.element.addEventListener('scroll', this._onScroll.bind(this), false);
    this.element.addEventListener('copy', this._onCopy.bind(this), false);
    this.element.addEventListener('dragstart', this._onDragStart.bind(this), false);

    this._firstActiveIndex = -1;
    this._lastActiveIndex = -1;
    this._renderedItems = [];
    this._anchorSelection = null;
    this._headSelection = null;
    this._itemCount = 0;
    this._cumulativeHeights = new Int32Array(0);
    this._muteCopyHandler = false;

    // Listen for any changes to descendants and trigger a refresh. This ensures
    // that items updated asynchronously will not break stick-to-bottom behavior
    // if they change the scroll height.
    this._observer = new MutationObserver(this.refresh.bind(this));
    this._observerConfig = {childList: true, subtree: true};
  }

  /**
   * @return {boolean}
   */
  stickToBottom() {
    return this._stickToBottom;
  }

  /**
   * @param {boolean} value
   */
  setStickToBottom(value) {
    this._stickToBottom = value;
    if (this._stickToBottom)
      this._observer.observe(this._contentElement, this._observerConfig);
    else
      this._observer.disconnect();
  }

  copyWithStyles() {
    this._muteCopyHandler = true;
    this.element.ownerDocument.execCommand('copy');
    this._muteCopyHandler = false;
  }

  /**
   * @param {!Event} event
   */
  _onCopy(event) {
    if (this._muteCopyHandler)
      return;
    const text = this._selectedText();
    if (!text)
      return;
    event.preventDefault();
    event.clipboardData.setData('text/plain', text);
  }

  /**
   * @param {!Event} event
   */
  _onDragStart(event) {
    const text = this._selectedText();
    if (!text)
      return false;
    event.dataTransfer.clearData();
    event.dataTransfer.setData('text/plain', text);
    event.dataTransfer.effectAllowed = 'copy';
    return true;
  }

  /**
   * @return {!Element}
   */
  contentElement() {
    return this._contentElement;
  }

  invalidate() {
    delete this._cachedProviderElements;
    this._itemCount = this._provider.itemCount();
    this._rebuildCumulativeHeights();
    this.refresh();
  }

  /**
   * @param {number} index
   * @return {?Console.ConsoleViewportElement}
   */
  _providerElement(index) {
    if (!this._cachedProviderElements)
      this._cachedProviderElements = new Array(this._itemCount);
    let element = this._cachedProviderElements[index];
    if (!element) {
      element = this._provider.itemElement(index);
      this._cachedProviderElements[index] = element;
    }
    return element;
  }

  _rebuildCumulativeHeights() {
    const firstActiveIndex = this._firstActiveIndex;
    const lastActiveIndex = this._lastActiveIndex;
    let height = 0;
    this._cumulativeHeights = new Int32Array(this._itemCount);
    for (let i = 0; i < this._itemCount; ++i) {
      if (firstActiveIndex <= i && i - firstActiveIndex < this._renderedItems.length && i <= lastActiveIndex)
        height += this._renderedItems[i - firstActiveIndex].element().offsetHeight;
      else
        height += this._provider.fastHeight(i);
      this._cumulativeHeights[i] = height;
    }
  }

  _rebuildCumulativeHeightsIfNeeded() {
    // Check whether current items in DOM have changed heights. Tolerate 1-pixel
    // error due to double-to-integer rounding errors.
    for (let i = 0; i < this._renderedItems.length; ++i) {
      const cachedItemHeight = this._cachedItemHeight(this._firstActiveIndex + i);
      if (Math.abs(cachedItemHeight - this._renderedItems[i].element().offsetHeight) > 1) {
        this._rebuildCumulativeHeights();
        break;
      }
    }
  }

  /**
   * @param {number} index
   * @return {number}
   */
  _cachedItemHeight(index) {
    return index === 0 ? this._cumulativeHeights[0] :
                         this._cumulativeHeights[index] - this._cumulativeHeights[index - 1];
  }

  /**
   * @param {?Selection} selection
   * @suppressGlobalPropertiesCheck
   */
  _isSelectionBackwards(selection) {
    if (!selection || !selection.rangeCount)
      return false;
    const range = document.createRange();
    range.setStart(selection.anchorNode, selection.anchorOffset);
    range.setEnd(selection.focusNode, selection.focusOffset);
    return range.collapsed;
  }

  /**
   * @param {number} itemIndex
   * @param {!Node} node
   * @param {number} offset
   * @return {!{item: number, node: !Node, offset: number}}
   */
  _createSelectionModel(itemIndex, node, offset) {
    return {item: itemIndex, node: node, offset: offset};
  }

  /**
   * @param {?Selection} selection
   */
  _updateSelectionModel(selection) {
    const range = selection && selection.rangeCount ? selection.getRangeAt(0) : null;
    if (!range || selection.isCollapsed || !this.element.hasSelection()) {
      this._headSelection = null;
      this._anchorSelection = null;
      return false;
    }

    let firstSelected = Number.MAX_VALUE;
    let lastSelected = -1;

    let hasVisibleSelection = false;
    for (let i = 0; i < this._renderedItems.length; ++i) {
      if (range.intersectsNode(this._renderedItems[i].element())) {
        const index = i + this._firstActiveIndex;
        firstSelected = Math.min(firstSelected, index);
        lastSelected = Math.max(lastSelected, index);
        hasVisibleSelection = true;
      }
    }
    if (hasVisibleSelection) {
      firstSelected =
          this._createSelectionModel(firstSelected, /** @type {!Node} */ (range.startContainer), range.startOffset);
      lastSelected =
          this._createSelectionModel(lastSelected, /** @type {!Node} */ (range.endContainer), range.endOffset);
    }
    const topOverlap = range.intersectsNode(this._topGapElement) && this._topGapElement._active;
    const bottomOverlap = range.intersectsNode(this._bottomGapElement) && this._bottomGapElement._active;
    if (!topOverlap && !bottomOverlap && !hasVisibleSelection) {
      this._headSelection = null;
      this._anchorSelection = null;
      return false;
    }

    if (!this._anchorSelection || !this._headSelection) {
      this._anchorSelection = this._createSelectionModel(0, this.element, 0);
      this._headSelection = this._createSelectionModel(this._itemCount - 1, this.element, this.element.children.length);
      this._selectionIsBackward = false;
    }

    const isBackward = this._isSelectionBackwards(selection);
    const startSelection = this._selectionIsBackward ? this._headSelection : this._anchorSelection;
    const endSelection = this._selectionIsBackward ? this._anchorSelection : this._headSelection;
    if (topOverlap && bottomOverlap && hasVisibleSelection) {
      firstSelected = firstSelected.item < startSelection.item ? firstSelected : startSelection;
      lastSelected = lastSelected.item > endSelection.item ? lastSelected : endSelection;
    } else if (!hasVisibleSelection) {
      firstSelected = startSelection;
      lastSelected = endSelection;
    } else if (topOverlap) {
      firstSelected = isBackward ? this._headSelection : this._anchorSelection;
    } else if (bottomOverlap) {
      lastSelected = isBackward ? this._anchorSelection : this._headSelection;
    }

    if (isBackward) {
      this._anchorSelection = lastSelected;
      this._headSelection = firstSelected;
    } else {
      this._anchorSelection = firstSelected;
      this._headSelection = lastSelected;
    }
    this._selectionIsBackward = isBackward;
    return true;
  }

  /**
   * @param {?Selection} selection
   */
  _restoreSelection(selection) {
    let anchorElement = null;
    let anchorOffset;
    if (this._firstActiveIndex <= this._anchorSelection.item && this._anchorSelection.item <= this._lastActiveIndex) {
      anchorElement = this._anchorSelection.node;
      anchorOffset = this._anchorSelection.offset;
    } else {
      if (this._anchorSelection.item < this._firstActiveIndex)
        anchorElement = this._topGapElement;
      else if (this._anchorSelection.item > this._lastActiveIndex)
        anchorElement = this._bottomGapElement;
      anchorOffset = this._selectionIsBackward ? 1 : 0;
    }

    let headElement = null;
    let headOffset;
    if (this._firstActiveIndex <= this._headSelection.item && this._headSelection.item <= this._lastActiveIndex) {
      headElement = this._headSelection.node;
      headOffset = this._headSelection.offset;
    } else {
      if (this._headSelection.item < this._firstActiveIndex)
        headElement = this._topGapElement;
      else if (this._headSelection.item > this._lastActiveIndex)
        headElement = this._bottomGapElement;
      headOffset = this._selectionIsBackward ? 0 : 1;
    }

    selection.setBaseAndExtent(anchorElement, anchorOffset, headElement, headOffset);
  }

  refresh() {
    this._observer.disconnect();
    this._innerRefresh();
    if (this._stickToBottom)
      this._observer.observe(this._contentElement, this._observerConfig);
  }

  _innerRefresh() {
    if (!this._visibleHeight())
      return;  // Do nothing for invisible controls.

    if (!this._itemCount) {
      for (let i = 0; i < this._renderedItems.length; ++i)
        this._renderedItems[i].willHide();
      this._renderedItems = [];
      this._contentElement.removeChildren();
      this._topGapElement.style.height = '0px';
      this._bottomGapElement.style.height = '0px';
      this._firstActiveIndex = -1;
      this._lastActiveIndex = -1;
      return;
    }

    const selection = this.element.getComponentSelection();
    const shouldRestoreSelection = this._updateSelectionModel(selection);

    const visibleFrom = this.element.scrollTop;
    const visibleHeight = this._visibleHeight();
    const activeHeight = visibleHeight * 2;
    this._rebuildCumulativeHeightsIfNeeded();

    // When the viewport is scrolled to the bottom, using the cumulative heights estimate is not
    // precise enough to determine next visible indices. This stickToBottom check avoids extra
    // calls to refresh in those cases.
    if (this._stickToBottom) {
      this._firstActiveIndex =
          Math.max(this._itemCount - Math.ceil(activeHeight / this._provider.minimumRowHeight()), 0);
      this._lastActiveIndex = this._itemCount - 1;
    } else {
      this._firstActiveIndex =
          Math.max(this._cumulativeHeights.lowerBound(visibleFrom + 1 - (activeHeight - visibleHeight) / 2), 0);
      // Proactively render more rows in case some of them will be collapsed without triggering refresh. @see crbug.com/390169
      this._lastActiveIndex = this._firstActiveIndex + Math.ceil(activeHeight / this._provider.minimumRowHeight()) - 1;
      this._lastActiveIndex = Math.min(this._lastActiveIndex, this._itemCount - 1);
    }

    const topGapHeight = this._cumulativeHeights[this._firstActiveIndex - 1] || 0;
    const bottomGapHeight =
        this._cumulativeHeights[this._cumulativeHeights.length - 1] - this._cumulativeHeights[this._lastActiveIndex];

    /**
     * @this {Console.ConsoleViewport}
     */
    function prepare() {
      this._topGapElement.style.height = topGapHeight + 'px';
      this._bottomGapElement.style.height = bottomGapHeight + 'px';
      this._topGapElement._active = !!topGapHeight;
      this._bottomGapElement._active = !!bottomGapHeight;
      this._contentElement.style.setProperty('height', '10000000px');
    }

    this._partialViewportUpdate(prepare.bind(this));
    this._contentElement.style.removeProperty('height');
    // Should be the last call in the method as it might force layout.
    if (shouldRestoreSelection)
      this._restoreSelection(selection);
    if (this._stickToBottom)
      this.element.scrollTop = 10000000;
  }

  /**
   * @param {function()} prepare
   */
  _partialViewportUpdate(prepare) {
    const itemsToRender = new Set();
    for (let i = this._firstActiveIndex; i <= this._lastActiveIndex; ++i)
      itemsToRender.add(this._providerElement(i));
    const willBeHidden = this._renderedItems.filter(item => !itemsToRender.has(item));
    for (let i = 0; i < willBeHidden.length; ++i)
      willBeHidden[i].willHide();
    prepare();
    for (let i = 0; i < willBeHidden.length; ++i)
      willBeHidden[i].element().remove();

    const wasShown = [];
    let anchor = this._contentElement.firstChild;
    for (const viewportElement of itemsToRender) {
      const element = viewportElement.element();
      if (element !== anchor) {
        const shouldCallWasShown = !element.parentElement;
        if (shouldCallWasShown)
          wasShown.push(viewportElement);
        this._contentElement.insertBefore(element, anchor);
      } else {
        anchor = anchor.nextSibling;
      }
    }
    for (let i = 0; i < wasShown.length; ++i)
      wasShown[i].wasShown();
    this._renderedItems = Array.from(itemsToRender);
  }

  /**
   * @return {?string}
   */
  _selectedText() {
    this._updateSelectionModel(this.element.getComponentSelection());
    if (!this._headSelection || !this._anchorSelection)
      return null;

    let startSelection = null;
    let endSelection = null;
    if (this._selectionIsBackward) {
      startSelection = this._headSelection;
      endSelection = this._anchorSelection;
    } else {
      startSelection = this._anchorSelection;
      endSelection = this._headSelection;
    }

    const textLines = [];
    for (let i = startSelection.item; i <= endSelection.item; ++i) {
      const element = this._providerElement(i).element();
      const lineContent = element.childTextNodes().map(Components.Linkifier.untruncatedNodeText).join('');
      textLines.push(lineContent);
    }

    const endSelectionElement = this._providerElement(endSelection.item).element();
    if (endSelection.node && endSelection.node.isSelfOrDescendant(endSelectionElement)) {
      const itemTextOffset = this._textOffsetInNode(endSelectionElement, endSelection.node, endSelection.offset);
      textLines[textLines.length - 1] = textLines.peekLast().substring(0, itemTextOffset);
    }

    const startSelectionElement = this._providerElement(startSelection.item).element();
    if (startSelection.node && startSelection.node.isSelfOrDescendant(startSelectionElement)) {
      const itemTextOffset = this._textOffsetInNode(startSelectionElement, startSelection.node, startSelection.offset);
      textLines[0] = textLines[0].substring(itemTextOffset);
    }

    return textLines.join('\n');
  }

  /**
   * @param {!Element} itemElement
   * @param {!Node} selectionNode
   * @param {number} offset
   * @return {number}
   */
  _textOffsetInNode(itemElement, selectionNode, offset) {
    // If the selectionNode is not a TextNode, we may need to convert a child offset into a character offset.
    if (selectionNode.nodeType !== Node.TEXT_NODE) {
      if (offset < selectionNode.childNodes.length) {
        selectionNode = /** @type {!Node} */ (selectionNode.childNodes.item(offset));
        offset = 0;
      } else {
        offset = selectionNode.textContent.length;
      }
    }

    let chars = 0;
    let node = itemElement;
    while ((node = node.traverseNextNode(itemElement)) && node !== selectionNode) {
      if (node.nodeType !== Node.TEXT_NODE || node.parentElement.nodeName === 'STYLE' ||
          node.parentElement.nodeName === 'SCRIPT')
        continue;
      chars += Components.Linkifier.untruncatedNodeText(node).length;
    }
    // If the selected node text was truncated, treat any non-zero offset as the full length.
    const untruncatedContainerLength = Components.Linkifier.untruncatedNodeText(selectionNode).length;
    if (offset > 0 && untruncatedContainerLength !== selectionNode.textContent.length)
      offset = untruncatedContainerLength;
    return chars + offset;
  }

  /**
   * @param {!Event} event
   */
  _onScroll(event) {
    this.refresh();
  }

  /**
   * @return {number}
   */
  firstVisibleIndex() {
    if (!this._cumulativeHeights.length)
      return -1;
    this._rebuildCumulativeHeightsIfNeeded();
    return this._cumulativeHeights.lowerBound(this.element.scrollTop + 1);
  }

  /**
   * @return {number}
   */
  lastVisibleIndex() {
    if (!this._cumulativeHeights.length)
      return -1;
    this._rebuildCumulativeHeightsIfNeeded();
    const scrollBottom = this.element.scrollTop + this.element.clientHeight;
    const right = this._itemCount - 1;
    return this._cumulativeHeights.lowerBound(scrollBottom, undefined, undefined, right);
  }

  /**
   * @return {?Element}
   */
  renderedElementAt(index) {
    if (index < this._firstActiveIndex)
      return null;
    if (index > this._lastActiveIndex)
      return null;
    return this._renderedItems[index - this._firstActiveIndex].element();
  }

  /**
   * @param {number} index
   * @param {boolean=} makeLast
   */
  scrollItemIntoView(index, makeLast) {
    const firstVisibleIndex = this.firstVisibleIndex();
    const lastVisibleIndex = this.lastVisibleIndex();
    if (index > firstVisibleIndex && index < lastVisibleIndex)
      return;
    if (makeLast)
      this.forceScrollItemToBeLast(index);
    else if (index <= firstVisibleIndex)
      this.forceScrollItemToBeFirst(index);
    else if (index >= lastVisibleIndex)
      this.forceScrollItemToBeLast(index);
  }

  /**
   * @param {number} index
   */
  forceScrollItemToBeFirst(index) {
    console.assert(index >= 0 && index < this._itemCount, 'Cannot scroll item at invalid index');
    this.setStickToBottom(false);
    this._rebuildCumulativeHeightsIfNeeded();
    this.element.scrollTop = index > 0 ? this._cumulativeHeights[index - 1] : 0;
    if (this.element.isScrolledToBottom())
      this.setStickToBottom(true);
    this.refresh();
  }

  /**
   * @param {number} index
   */
  forceScrollItemToBeLast(index) {
    console.assert(index >= 0 && index < this._itemCount, 'Cannot scroll item at invalid index');
    this.setStickToBottom(false);
    this._rebuildCumulativeHeightsIfNeeded();
    this.element.scrollTop = this._cumulativeHeights[index] - this._visibleHeight();
    if (this.element.isScrolledToBottom())
      this.setStickToBottom(true);
    this.refresh();
  }

  /**
   * @return {number}
   */
  _visibleHeight() {
    // Use offsetHeight instead of clientHeight to avoid being affected by horizontal scroll.
    return this.element.offsetHeight;
  }
};

/**
 * @interface
 */
Console.ConsoleViewportProvider = function() {};

Console.ConsoleViewportProvider.prototype = {
  /**
   * @param {number} index
   * @return {number}
   */
  fastHeight(index) {
    return 0;
  },

  /**
   * @return {number}
   */
  itemCount() {
    return 0;
  },

  /**
   * @return {number}
   */
  minimumRowHeight() {
    return 0;
  },

  /**
   * @param {number} index
   * @return {?Console.ConsoleViewportElement}
   */
  itemElement(index) {
    return null;
  }
};

/**
 * @interface
 */
Console.ConsoleViewportElement = function() {};
Console.ConsoleViewportElement.prototype = {
  willHide() {},

  wasShown() {},

  /**
   * @return {!Element}
   */
  element() {},
};
