/*
 * Copyright (C) 2008 Apple Inc. All Rights Reserved.
 * Copyright (C) 2011 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:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. 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.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``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 APPLE INC. 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
 */
export default class Widget extends Common.Object {
  /**
   * @param {boolean=} isWebComponent
   * @param {boolean=} delegatesFocus
   */
  constructor(isWebComponent, delegatesFocus) {
    super();
    this.contentElement = createElementWithClass('div', 'widget');
    if (isWebComponent) {
      this.element = createElementWithClass('div', 'vbox flex-auto');
      this._shadowRoot = UI.createShadowRootWithCoreStyles(this.element, undefined, delegatesFocus);
      this._shadowRoot.appendChild(this.contentElement);
    } else {
      this.element = this.contentElement;
    }
    this._isWebComponent = isWebComponent;
    this.element.__widget = this;
    this._visible = false;
    this._isRoot = false;
    this._isShowing = false;
    this._children = [];
    this._hideOnDetach = false;
    this._notificationDepth = 0;
    this._invalidationsSuspended = 0;
    this._defaultFocusedChild = null;
  }

  static _incrementWidgetCounter(parentElement, childElement) {
    const count = (childElement.__widgetCounter || 0) + (childElement.__widget ? 1 : 0);
    if (!count) {
      return;
    }

    while (parentElement) {
      parentElement.__widgetCounter = (parentElement.__widgetCounter || 0) + count;
      parentElement = parentElement.parentElementOrShadowHost();
    }
  }

  static _decrementWidgetCounter(parentElement, childElement) {
    const count = (childElement.__widgetCounter || 0) + (childElement.__widget ? 1 : 0);
    if (!count) {
      return;
    }

    while (parentElement) {
      parentElement.__widgetCounter -= count;
      parentElement = parentElement.parentElementOrShadowHost();
    }
  }

  static __assert(condition, message) {
    if (!condition) {
      throw new Error(message);
    }
  }

  /**
   * @param {?Node} node
   */
  static focusWidgetForNode(node) {
    while (node) {
      if (node.__widget) {
        break;
      }
      node = node.parentNodeOrShadowHost();
    }
    if (!node) {
      return;
    }

    let widget = node.__widget;
    while (widget._parentWidget) {
      widget._parentWidget._defaultFocusedChild = widget;
      widget = widget._parentWidget;
    }
  }

  markAsRoot() {
    Widget.__assert(!this.element.parentElement, 'Attempt to mark as root attached node');
    this._isRoot = true;
  }

  /**
   * @return {?Widget}
   */
  parentWidget() {
    return this._parentWidget;
  }

  /**
   * @return {!Array.<!Widget>}
   */
  children() {
    return this._children;
  }

  /**
   * @param {!Widget} widget
   * @protected
   */
  childWasDetached(widget) {
  }

  /**
   * @return {boolean}
   */
  isShowing() {
    return this._isShowing;
  }

  /**
   * @return {boolean}
   */
  shouldHideOnDetach() {
    if (!this.element.parentElement) {
      return false;
    }
    if (this._hideOnDetach) {
      return true;
    }
    for (const child of this._children) {
      if (child.shouldHideOnDetach()) {
        return true;
      }
    }
    return false;
  }

  setHideOnDetach() {
    this._hideOnDetach = true;
  }

  /**
   * @return {boolean}
   */
  _inNotification() {
    return !!this._notificationDepth || (this._parentWidget && this._parentWidget._inNotification());
  }

  _parentIsShowing() {
    if (this._isRoot) {
      return true;
    }
    return !!this._parentWidget && this._parentWidget.isShowing();
  }

  /**
   * @param {function(this:Widget)} method
   */
  _callOnVisibleChildren(method) {
    const copy = this._children.slice();
    for (let i = 0; i < copy.length; ++i) {
      if (copy[i]._parentWidget === this && copy[i]._visible) {
        method.call(copy[i]);
      }
    }
  }

  _processWillShow() {
    this._callOnVisibleChildren(this._processWillShow);
    this._isShowing = true;
  }

  _processWasShown() {
    if (this._inNotification()) {
      return;
    }
    this.restoreScrollPositions();
    this._notify(this.wasShown);
    this._callOnVisibleChildren(this._processWasShown);
  }

  _processWillHide() {
    if (this._inNotification()) {
      return;
    }
    this.storeScrollPositions();

    this._callOnVisibleChildren(this._processWillHide);
    this._notify(this.willHide);
    this._isShowing = false;
  }

  _processWasHidden() {
    this._callOnVisibleChildren(this._processWasHidden);
  }

  _processOnResize() {
    if (this._inNotification()) {
      return;
    }
    if (!this.isShowing()) {
      return;
    }
    this._notify(this.onResize);
    this._callOnVisibleChildren(this._processOnResize);
  }

  /**
   * @param {function(this:Widget)} notification
   */
  _notify(notification) {
    ++this._notificationDepth;
    try {
      notification.call(this);
    } finally {
      --this._notificationDepth;
    }
  }

  wasShown() {
  }

  willHide() {
  }

  onResize() {
  }

  onLayout() {
  }

  ownerViewDisposed() {
  }

  /**
   * @param {!Element} parentElement
   * @param {?Node=} insertBefore
   */
  show(parentElement, insertBefore) {
    Widget.__assert(parentElement, 'Attempt to attach widget with no parent element');

    if (!this._isRoot) {
      // Update widget hierarchy.
      let currentParent = parentElement;
      while (currentParent && !currentParent.__widget) {
        currentParent = currentParent.parentElementOrShadowHost();
      }
      Widget.__assert(currentParent, 'Attempt to attach widget to orphan node');
      this._attach(currentParent.__widget);
    }

    this._showWidget(parentElement, insertBefore);
  }

  /**
   * @param {!Widget} parentWidget
   */
  _attach(parentWidget) {
    if (parentWidget === this._parentWidget) {
      return;
    }
    if (this._parentWidget) {
      this.detach();
    }
    this._parentWidget = parentWidget;
    this._parentWidget._children.push(this);
    this._isRoot = false;
  }

  showWidget() {
    if (this._visible) {
      return;
    }
    Widget.__assert(this.element.parentElement, 'Attempt to show widget that is not hidden using hideWidget().');
    this._showWidget(/** @type {!Element} */ (this.element.parentElement), this.element.nextSibling);
  }

  /**
   * @param {!Element} parentElement
   * @param {?Node=} insertBefore
   */
  _showWidget(parentElement, insertBefore) {
    let currentParent = parentElement;
    while (currentParent && !currentParent.__widget) {
      currentParent = currentParent.parentElementOrShadowHost();
    }

    if (this._isRoot) {
      Widget.__assert(!currentParent, 'Attempt to show root widget under another widget');
    } else {
      Widget.__assert(
          currentParent && currentParent.__widget === this._parentWidget,
          'Attempt to show under node belonging to alien widget');
    }

    const wasVisible = this._visible;
    if (wasVisible && this.element.parentElement === parentElement) {
      return;
    }

    this._visible = true;

    if (!wasVisible && this._parentIsShowing()) {
      this._processWillShow();
    }

    this.element.classList.remove('hidden');

    // Reparent
    if (this.element.parentElement !== parentElement) {
      if (!this._externallyManaged) {
        Widget._incrementWidgetCounter(parentElement, this.element);
      }
      if (insertBefore) {
        Widget._originalInsertBefore.call(parentElement, this.element, insertBefore);
      } else {
        Widget._originalAppendChild.call(parentElement, this.element);
      }
    }

    if (!wasVisible && this._parentIsShowing()) {
      this._processWasShown();
    }

    if (this._parentWidget && this._hasNonZeroConstraints()) {
      this._parentWidget.invalidateConstraints();
    } else {
      this._processOnResize();
    }
  }

  hideWidget() {
    if (!this._visible) {
      return;
    }
    this._hideWidget(false);
  }

  /**
   * @param {boolean} removeFromDOM
   */
  _hideWidget(removeFromDOM) {
    this._visible = false;
    const parentElement = this.element.parentElement;

    if (this._parentIsShowing()) {
      this._processWillHide();
    }

    if (removeFromDOM) {
      // Force legal removal
      Widget._decrementWidgetCounter(parentElement, this.element);
      Widget._originalRemoveChild.call(parentElement, this.element);
    } else {
      this.element.classList.add('hidden');
    }

    if (this._parentIsShowing()) {
      this._processWasHidden();
    }
    if (this._parentWidget && this._hasNonZeroConstraints()) {
      this._parentWidget.invalidateConstraints();
    }
  }

  /**
   * @param {boolean=} overrideHideOnDetach
   */
  detach(overrideHideOnDetach) {
    if (!this._parentWidget && !this._isRoot) {
      return;
    }

    // hideOnDetach means that we should never remove element from dom - content
    // has iframes and detaching it will hurt.
    //
    // overrideHideOnDetach will override hideOnDetach and the client takes
    // responsibility for the consequences.
    const removeFromDOM = overrideHideOnDetach || !this.shouldHideOnDetach();
    if (this._visible) {
      this._hideWidget(removeFromDOM);
    } else if (removeFromDOM && this.element.parentElement) {
      const parentElement = this.element.parentElement;
      // Force kick out from DOM.
      Widget._decrementWidgetCounter(parentElement, this.element);
      Widget._originalRemoveChild.call(parentElement, this.element);
    }

    // Update widget hierarchy.
    if (this._parentWidget) {
      const childIndex = this._parentWidget._children.indexOf(this);
      Widget.__assert(childIndex >= 0, 'Attempt to remove non-child widget');
      this._parentWidget._children.splice(childIndex, 1);
      if (this._parentWidget._defaultFocusedChild === this) {
        this._parentWidget._defaultFocusedChild = null;
      }
      this._parentWidget.childWasDetached(this);
      this._parentWidget = null;
    } else {
      Widget.__assert(this._isRoot, 'Removing non-root widget from DOM');
    }
  }

  detachChildWidgets() {
    const children = this._children.slice();
    for (let i = 0; i < children.length; ++i) {
      children[i].detach();
    }
  }

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

  storeScrollPositions() {
    const elements = this.elementsToRestoreScrollPositionsFor();
    for (let i = 0; i < elements.length; ++i) {
      const container = elements[i];
      container._scrollTop = container.scrollTop;
      container._scrollLeft = container.scrollLeft;
    }
  }

  restoreScrollPositions() {
    const elements = this.elementsToRestoreScrollPositionsFor();
    for (let i = 0; i < elements.length; ++i) {
      const container = elements[i];
      if (container._scrollTop) {
        container.scrollTop = container._scrollTop;
      }
      if (container._scrollLeft) {
        container.scrollLeft = container._scrollLeft;
      }
    }
  }

  doResize() {
    if (!this.isShowing()) {
      return;
    }
    // No matter what notification we are in, dispatching onResize is not needed.
    if (!this._inNotification()) {
      this._callOnVisibleChildren(this._processOnResize);
    }
  }

  doLayout() {
    if (!this.isShowing()) {
      return;
    }
    this._notify(this.onLayout);
    this.doResize();
  }

  /**
   * @param {string} cssFile
   */
  registerRequiredCSS(cssFile) {
    UI.appendStyle(this._isWebComponent ? this._shadowRoot : this.element, cssFile);
  }

  printWidgetHierarchy() {
    const lines = [];
    this._collectWidgetHierarchy('', lines);
    console.log(lines.join('\n'));  // eslint-disable-line no-console
  }

  _collectWidgetHierarchy(prefix, lines) {
    lines.push(prefix + '[' + this.element.className + ']' + (this._children.length ? ' {' : ''));

    for (let i = 0; i < this._children.length; ++i) {
      this._children[i]._collectWidgetHierarchy(prefix + '    ', lines);
    }

    if (this._children.length) {
      lines.push(prefix + '}');
    }
  }

  /**
   * @param {?Element} element
   */
  setDefaultFocusedElement(element) {
    this._defaultFocusedElement = element;
  }

  /**
   * @param {!Widget} child
   */
  setDefaultFocusedChild(child) {
    Widget.__assert(child._parentWidget === this, 'Attempt to set non-child widget as default focused.');
    this._defaultFocusedChild = child;
  }

  focus() {
    if (!this.isShowing()) {
      return;
    }

    const element = this._defaultFocusedElement;
    if (element) {
      if (!element.hasFocus()) {
        element.focus();
      }
      return;
    }

    if (this._defaultFocusedChild && this._defaultFocusedChild._visible) {
      this._defaultFocusedChild.focus();
    } else {
      for (const child of this._children) {
        if (child._visible) {
          child.focus();
          return;
        }
      }
      let child = this.contentElement.traverseNextNode(this.contentElement);
      while (child) {
        if (child instanceof UI.XWidget) {
          child.focus();
          return;
        }
        child = child.traverseNextNode(this.contentElement);
      }
    }
  }

  /**
   * @return {boolean}
   */
  hasFocus() {
    return this.element.hasFocus();
  }

  /**
   * @return {!UI.Constraints}
   */
  calculateConstraints() {
    return new UI.Constraints();
  }

  /**
   * @return {!UI.Constraints}
   */
  constraints() {
    if (typeof this._constraints !== 'undefined') {
      return this._constraints;
    }
    if (typeof this._cachedConstraints === 'undefined') {
      this._cachedConstraints = this.calculateConstraints();
    }
    return this._cachedConstraints;
  }

  /**
   * @param {number} width
   * @param {number} height
   * @param {number} preferredWidth
   * @param {number} preferredHeight
   */
  setMinimumAndPreferredSizes(width, height, preferredWidth, preferredHeight) {
    this._constraints = new UI.Constraints(new UI.Size(width, height), new UI.Size(preferredWidth, preferredHeight));
    this.invalidateConstraints();
  }

  /**
   * @param {number} width
   * @param {number} height
   */
  setMinimumSize(width, height) {
    this._constraints = new UI.Constraints(new UI.Size(width, height));
    this.invalidateConstraints();
  }

  /**
   * @return {boolean}
   */
  _hasNonZeroConstraints() {
    const constraints = this.constraints();
    return !!(
        constraints.minimum.width || constraints.minimum.height || constraints.preferred.width ||
        constraints.preferred.height);
  }

  suspendInvalidations() {
    ++this._invalidationsSuspended;
  }

  resumeInvalidations() {
    --this._invalidationsSuspended;
    if (!this._invalidationsSuspended && this._invalidationsRequested) {
      this.invalidateConstraints();
    }
  }

  invalidateConstraints() {
    if (this._invalidationsSuspended) {
      this._invalidationsRequested = true;
      return;
    }
    this._invalidationsRequested = false;
    const cached = this._cachedConstraints;
    delete this._cachedConstraints;
    const actual = this.constraints();
    if (!actual.isEqual(cached) && this._parentWidget) {
      this._parentWidget.invalidateConstraints();
    } else {
      this.doLayout();
    }
  }

  // Excludes the widget from being tracked by its parents/ancestors via
  // __widgetCounter because the widget is being handled by external code.
  // Widgets marked as being externally managed are responsible for
  // finishing out their own lifecycle (i.e. calling detach() before being
  // removed from the DOM). This is e.g. used for CodeMirror.
  //
  // Also note that this must be called before the widget is shown so that
  // so that its ancestor's __widgetCounter is not incremented.
  markAsExternallyManaged() {
    Widget.__assert(!this._parentWidget, 'Attempt to mark widget as externally managed after insertion to the DOM');
    this._externallyManaged = true;
  }
}

export const _originalAppendChild = Element.prototype.appendChild;
export const _originalInsertBefore = Element.prototype.insertBefore;
export const _originalRemoveChild = Element.prototype.removeChild;
export const _originalRemoveChildren = Element.prototype.removeChildren;


/**
 * @unrestricted
 */
export class VBox extends Widget {
  /**
   * @param {boolean=} isWebComponent
   * @param {boolean=} delegatesFocus
   */
  constructor(isWebComponent, delegatesFocus) {
    super(isWebComponent, delegatesFocus);
    this.contentElement.classList.add('vbox');
  }

  /**
   * @override
   * @return {!UI.Constraints}
   */
  calculateConstraints() {
    let constraints = new UI.Constraints();

    /**
     * @this {!Widget}
     * @suppressReceiverCheck
     */
    function updateForChild() {
      const child = this.constraints();
      constraints = constraints.widthToMax(child);
      constraints = constraints.addHeight(child);
    }

    this._callOnVisibleChildren(updateForChild);
    return constraints;
  }
}

/**
 * @unrestricted
 */
export class HBox extends Widget {
  /**
   * @param {boolean=} isWebComponent
   */
  constructor(isWebComponent) {
    super(isWebComponent);
    this.contentElement.classList.add('hbox');
  }

  /**
   * @override
   * @return {!UI.Constraints}
   */
  calculateConstraints() {
    let constraints = new UI.Constraints();

    /**
     * @this {!Widget}
     * @suppressReceiverCheck
     */
    function updateForChild() {
      const child = this.constraints();
      constraints = constraints.addWidth(child);
      constraints = constraints.heightToMax(child);
    }

    this._callOnVisibleChildren(updateForChild);
    return constraints;
  }
}

/**
 * @unrestricted
 */
export class VBoxWithResizeCallback extends VBox {
  /**
   * @param {function()} resizeCallback
   */
  constructor(resizeCallback) {
    super();
    this._resizeCallback = resizeCallback;
  }

  /**
   * @override
   */
  onResize() {
    this._resizeCallback();
  }
}

/**
 * @unrestricted
 */
export class WidgetFocusRestorer {
  /**
   * @param {!Widget} widget
   */
  constructor(widget) {
    this._widget = widget;
    this._previous = widget.element.ownerDocument.deepActiveElement();
    widget.focus();
  }

  restore() {
    if (!this._widget) {
      return;
    }
    if (this._widget.hasFocus() && this._previous) {
      this._previous.focus();
    }
    this._previous = null;
    this._widget = null;
  }
}

/**
 * @override
 * @param {?Node} child
 * @return {!Node}
 * @suppress {duplicate}
 */
Element.prototype.appendChild = function(child) {
  Widget.__assert(!child.__widget || child.parentElement === this, 'Attempt to add widget via regular DOM operation.');
  return Widget._originalAppendChild.call(this, child);
};

/**
 * @override
 * @param {?Node} child
 * @param {?Node} anchor
 * @return {!Node}
 * @suppress {duplicate}
 */
Element.prototype.insertBefore = function(child, anchor) {
  Widget.__assert(!child.__widget || child.parentElement === this, 'Attempt to add widget via regular DOM operation.');
  return Widget._originalInsertBefore.call(this, child, anchor);
};

/**
 * @override
 * @param {?Node} child
 * @return {!Node}
 * @suppress {duplicate}
 */
Element.prototype.removeChild = function(child) {
  Widget.__assert(
      !child.__widgetCounter && !child.__widget,
      'Attempt to remove element containing widget via regular DOM operation');
  return Widget._originalRemoveChild.call(this, child);
};

Element.prototype.removeChildren = function() {
  Widget.__assert(!this.__widgetCounter, 'Attempt to remove element containing widget via regular DOM operation');
  Widget._originalRemoveChildren.call(this);
};

/* Legacy exported object*/
self.UI = self.UI || {};

/* Legacy exported object*/
UI = UI || {};

/** @constructor */
UI.Widget = Widget;

Widget._originalAppendChild = _originalAppendChild;
Widget._originalInsertBefore = _originalInsertBefore;
Widget._originalRemoveChild = _originalRemoveChild;
Widget._originalRemoveChildren = _originalRemoveChildren;

/** @constructor */
UI.HBox = HBox;

/** @constructor */
UI.VBox = VBox;

/** @constructor */
UI.WidgetFocusRestorer = WidgetFocusRestorer;

/** @constructor */
UI.VBoxWithResizeCallback = VBoxWithResizeCallback;
