// Copyright (c) 2015 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.

/**
 * @unrestricted
 */
export default class ComputedStyleModel extends Common.Object {
  constructor() {
    super();
    this._node = UI.context.flavor(SDK.DOMNode);
    this._cssModel = null;
    this._eventListeners = [];
    UI.context.addFlavorChangeListener(SDK.DOMNode, this._onNodeChanged, this);
  }

  /**
   * @return {?SDK.DOMNode}
   */
  node() {
    return this._node;
  }

  /**
   * @return {?SDK.CSSModel}
   */
  cssModel() {
    return this._cssModel && this._cssModel.isEnabled() ? this._cssModel : null;
  }

  /**
   * @param {!Common.Event} event
   */
  _onNodeChanged(event) {
    this._node = /** @type {?SDK.DOMNode} */ (event.data);
    this._updateModel(this._node ? this._node.domModel().cssModel() : null);
    this._onComputedStyleChanged(null);
  }

  /**
   * @param {?SDK.CSSModel} cssModel
   */
  _updateModel(cssModel) {
    if (this._cssModel === cssModel) {
      return;
    }
    Common.EventTarget.removeEventListeners(this._eventListeners);
    this._cssModel = cssModel;
    const domModel = cssModel ? cssModel.domModel() : null;
    const resourceTreeModel = cssModel ? cssModel.target().model(SDK.ResourceTreeModel) : null;
    if (cssModel && domModel && resourceTreeModel) {
      this._eventListeners = [
        cssModel.addEventListener(SDK.CSSModel.Events.StyleSheetAdded, this._onComputedStyleChanged, this),
        cssModel.addEventListener(SDK.CSSModel.Events.StyleSheetRemoved, this._onComputedStyleChanged, this),
        cssModel.addEventListener(SDK.CSSModel.Events.StyleSheetChanged, this._onComputedStyleChanged, this),
        cssModel.addEventListener(SDK.CSSModel.Events.FontsUpdated, this._onComputedStyleChanged, this),
        cssModel.addEventListener(SDK.CSSModel.Events.MediaQueryResultChanged, this._onComputedStyleChanged, this),
        cssModel.addEventListener(SDK.CSSModel.Events.PseudoStateForced, this._onComputedStyleChanged, this),
        cssModel.addEventListener(SDK.CSSModel.Events.ModelWasEnabled, this._onComputedStyleChanged, this),
        domModel.addEventListener(SDK.DOMModel.Events.DOMMutated, this._onDOMModelChanged, this),
        resourceTreeModel.addEventListener(SDK.ResourceTreeModel.Events.FrameResized, this._onFrameResized, this),
      ];
    }
  }

  /**
   * @param {?Common.Event} event
   */
  _onComputedStyleChanged(event) {
    delete this._computedStylePromise;
    this.dispatchEventToListeners(Events.ComputedStyleChanged, event ? event.data : null);
  }

  /**
   * @param {!Common.Event} event
   */
  _onDOMModelChanged(event) {
    // Any attribute removal or modification can affect the styles of "related" nodes.
    const node = /** @type {!SDK.DOMNode} */ (event.data);
    if (!this._node ||
        this._node !== node && node.parentNode !== this._node.parentNode && !node.isAncestor(this._node)) {
      return;
    }
    this._onComputedStyleChanged(null);
  }

  /**
   * @param {!Common.Event} event
   */
  _onFrameResized(event) {
    /**
     * @this {ComputedStyleModel}
     */
    function refreshContents() {
      this._onComputedStyleChanged(null);
      delete this._frameResizedTimer;
    }

    if (this._frameResizedTimer) {
      clearTimeout(this._frameResizedTimer);
    }

    this._frameResizedTimer = setTimeout(refreshContents.bind(this), 100);
  }

  /**
   * @return {?SDK.DOMNode}
   */
  _elementNode() {
    return this.node() ? this.node().enclosingElementOrSelf() : null;
  }

  /**
   * @return {!Promise.<?ComputedStyle>}
   */
  fetchComputedStyle() {
    const elementNode = this._elementNode();
    const cssModel = this.cssModel();
    if (!elementNode || !cssModel) {
      return Promise.resolve(/** @type {?ComputedStyle} */ (null));
    }

    if (!this._computedStylePromise) {
      this._computedStylePromise =
          cssModel.computedStylePromise(elementNode.id).then(verifyOutdated.bind(this, elementNode));
    }

    return this._computedStylePromise;

    /**
     * @param {!SDK.DOMNode} elementNode
     * @param {?Map.<string, string>} style
     * @return {?ComputedStyle}
     * @this {ComputedStyleModel}
     */
    function verifyOutdated(elementNode, style) {
      return elementNode === this._elementNode() && style ? new ComputedStyle(elementNode, style) :
                                                            /** @type {?ComputedStyle} */ (null);
    }
  }
}

/** @enum {symbol} */
export const Events = {
  ComputedStyleChanged: Symbol('ComputedStyleChanged')
};

/**
 * @unrestricted
 */
export class ComputedStyle {
  /**
   * @param {!SDK.DOMNode} node
   * @param {!Map.<string, string>} computedStyle
   */
  constructor(node, computedStyle) {
    this.node = node;
    this.computedStyle = computedStyle;
  }
}

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

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

/** @constructor */
Elements.ComputedStyleModel = ComputedStyleModel;

/** @enum {symbol} */
Elements.ComputedStyleModel.Events = Events;

/** @constructor */
Elements.ComputedStyleModel.ComputedStyle = ComputedStyle;
