// 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.
/**
 * @unrestricted
 */
export default class CSSMatchedStyles {
  /**
   * @param {!SDK.CSSModel} cssModel
   * @param {!SDK.DOMNode} node
   * @param {?Protocol.CSS.CSSStyle} inlinePayload
   * @param {?Protocol.CSS.CSSStyle} attributesPayload
   * @param {!Array.<!Protocol.CSS.RuleMatch>} matchedPayload
   * @param {!Array.<!Protocol.CSS.PseudoElementMatches>} pseudoPayload
   * @param {!Array.<!Protocol.CSS.InheritedStyleEntry>} inheritedPayload
   * @param {!Array.<!Protocol.CSS.CSSKeyframesRule>} animationsPayload
   */
  constructor(
      cssModel,
      node,
      inlinePayload,
      attributesPayload,
      matchedPayload,
      pseudoPayload,
      inheritedPayload,
      animationsPayload) {
    this._cssModel = cssModel;
    this._node = node;
    /** @type {!Map<!SDK.CSSStyleDeclaration, !SDK.DOMNode>} */
    this._addedStyles = new Map();
    /** @type {!Map<!Protocol.DOM.NodeId, !Map<string, boolean>>} */
    this._matchingSelectors = new Map();
    this._keyframes = [];
    if (animationsPayload) {
      this._keyframes = animationsPayload.map(rule => new SDK.CSSKeyframesRule(cssModel, rule));
    }

    /** @type {!Map<!SDK.CSSStyleDeclaration, ?SDK.DOMNode>} */
    this._nodeForStyle = new Map();
    /** @type {!Set<!SDK.CSSStyleDeclaration>} */
    this._inheritedStyles = new Set();

    matchedPayload = cleanUserAgentPayload(matchedPayload);
    for (const inheritedResult of inheritedPayload) {
      inheritedResult.matchedCSSRules = cleanUserAgentPayload(inheritedResult.matchedCSSRules);
    }

    this._mainDOMCascade = this._buildMainCascade(inlinePayload, attributesPayload, matchedPayload, inheritedPayload);
    this._pseudoDOMCascades = this._buildPseudoCascades(pseudoPayload);

    /** @type {!Map<!SDK.CSSStyleDeclaration, !DOMInheritanceCascade>} */
    this._styleToDOMCascade = new Map();
    for (const domCascade of Array.from(this._pseudoDOMCascades.values()).concat(this._mainDOMCascade)) {
      for (const style of domCascade.styles()) {
        this._styleToDOMCascade.set(style, domCascade);
      }
    }

    /**
     * @param {!Array<!Protocol.CSS.RuleMatch>} payload
     * @return {!Array<!Protocol.CSS.RuleMatch>}
     */
    function cleanUserAgentPayload(payload) {
      for (const ruleMatch of payload) {
        cleanUserAgentSelectors(ruleMatch);
      }

      // Merge UA rules that are sequential and have similar selector/media.
      const cleanMatchedPayload = [];
      for (const ruleMatch of payload) {
        const lastMatch = cleanMatchedPayload.peekLast();
        if (!lastMatch || ruleMatch.rule.origin !== 'user-agent' || lastMatch.rule.origin !== 'user-agent' ||
            ruleMatch.rule.selectorList.text !== lastMatch.rule.selectorList.text ||
            mediaText(ruleMatch) !== mediaText(lastMatch)) {
          cleanMatchedPayload.push(ruleMatch);
          continue;
        }
        mergeRule(ruleMatch, lastMatch);
      }
      return cleanMatchedPayload;

      /**
       * @param {!Protocol.CSS.RuleMatch} from
       * @param {!Protocol.CSS.RuleMatch} to
       */
      function mergeRule(from, to) {
        const shorthands = /** @type {!Map<string, string>} */ (new Map());
        const properties = /** @type {!Map<string, string>} */ (new Map());
        for (const entry of to.rule.style.shorthandEntries) {
          shorthands.set(entry.name, entry.value);
        }
        for (const entry of to.rule.style.cssProperties) {
          properties.set(entry.name, entry.value);
        }
        for (const entry of from.rule.style.shorthandEntries) {
          shorthands.set(entry.name, entry.value);
        }
        for (const entry of from.rule.style.cssProperties) {
          properties.set(entry.name, entry.value);
        }
        to.rule.style.shorthandEntries = shorthands.keysArray().map(name => ({name, value: shorthands.get(name)}));
        to.rule.style.cssProperties = properties.keysArray().map(name => ({name, value: properties.get(name)}));
      }

      /**
       * @param {!Protocol.CSS.RuleMatch} ruleMatch
       * @return {?string}
       */
      function mediaText(ruleMatch) {
        if (!ruleMatch.rule.media) {
          return null;
        }
        return ruleMatch.rule.media.map(media => media.text).join(', ');
      }

      /**
       * @param {!Protocol.CSS.RuleMatch} ruleMatch
       */
      function cleanUserAgentSelectors(ruleMatch) {
        const {matchingSelectors, rule} = ruleMatch;
        if (rule.origin !== 'user-agent' || !matchingSelectors.length) {
          return;
        }
        rule.selectorList.selectors = rule.selectorList.selectors.filter((item, i) => matchingSelectors.includes(i));
        rule.selectorList.text = rule.selectorList.selectors.map(item => item.text).join(', ');
        ruleMatch.matchingSelectors = matchingSelectors.map((item, i) => i);
      }
    }
  }

  /**
   * @param {?Protocol.CSS.CSSStyle} inlinePayload
   * @param {?Protocol.CSS.CSSStyle} attributesPayload
   * @param {!Array.<!Protocol.CSS.RuleMatch>} matchedPayload
   * @param {!Array.<!Protocol.CSS.InheritedStyleEntry>} inheritedPayload
   * @return {!DOMInheritanceCascade}
   */
  _buildMainCascade(inlinePayload, attributesPayload, matchedPayload, inheritedPayload) {
    /** @type {!Array<!NodeCascade>} */
    const nodeCascades = [];

    /** @type {!Array<!SDK.CSSStyleDeclaration>} */
    const nodeStyles = [];

    /**
     * @this {CSSMatchedStyles}
     */
    function addAttributesStyle() {
      if (!attributesPayload) {
        return;
      }
      const style =
          new SDK.CSSStyleDeclaration(this._cssModel, null, attributesPayload, SDK.CSSStyleDeclaration.Type.Attributes);
      this._nodeForStyle.set(style, this._node);
      nodeStyles.push(style);
    }

    // Inline style has the greatest specificity.
    if (inlinePayload && this._node.nodeType() === Node.ELEMENT_NODE) {
      const style =
          new SDK.CSSStyleDeclaration(this._cssModel, null, inlinePayload, SDK.CSSStyleDeclaration.Type.Inline);
      this._nodeForStyle.set(style, this._node);
      nodeStyles.push(style);
    }

    // Add rules in reverse order to match the cascade order.
    let addedAttributesStyle;
    for (let i = matchedPayload.length - 1; i >= 0; --i) {
      const rule = new SDK.CSSStyleRule(this._cssModel, matchedPayload[i].rule);
      if ((rule.isInjected() || rule.isUserAgent()) && !addedAttributesStyle) {
        // Show element's Style Attributes after all author rules.
        addedAttributesStyle = true;
        addAttributesStyle.call(this);
      }
      this._nodeForStyle.set(rule.style, this._node);
      nodeStyles.push(rule.style);
      this._addMatchingSelectors(this._node, rule, matchedPayload[i].matchingSelectors);
    }

    if (!addedAttributesStyle) {
      addAttributesStyle.call(this);
    }
    nodeCascades.push(new NodeCascade(this, nodeStyles, false /* isInherited */));

    // Walk the node structure and identify styles with inherited properties.
    let parentNode = this._node.parentNode;
    for (let i = 0; parentNode && inheritedPayload && i < inheritedPayload.length; ++i) {
      const inheritedStyles = [];
      const entryPayload = inheritedPayload[i];
      const inheritedInlineStyle = entryPayload.inlineStyle ?
          new SDK.CSSStyleDeclaration(
              this._cssModel, null, entryPayload.inlineStyle, SDK.CSSStyleDeclaration.Type.Inline) :
          null;
      if (inheritedInlineStyle && this._containsInherited(inheritedInlineStyle)) {
        this._nodeForStyle.set(inheritedInlineStyle, parentNode);
        inheritedStyles.push(inheritedInlineStyle);
        this._inheritedStyles.add(inheritedInlineStyle);
      }

      const inheritedMatchedCSSRules = entryPayload.matchedCSSRules || [];
      for (let j = inheritedMatchedCSSRules.length - 1; j >= 0; --j) {
        const inheritedRule = new SDK.CSSStyleRule(this._cssModel, inheritedMatchedCSSRules[j].rule);
        this._addMatchingSelectors(parentNode, inheritedRule, inheritedMatchedCSSRules[j].matchingSelectors);
        if (!this._containsInherited(inheritedRule.style)) {
          continue;
        }
        if (containsStyle(nodeStyles, inheritedRule.style) ||
            containsStyle(this._inheritedStyles, inheritedRule.style)) {
          continue;
        }
        this._nodeForStyle.set(inheritedRule.style, parentNode);
        inheritedStyles.push(inheritedRule.style);
        this._inheritedStyles.add(inheritedRule.style);
      }
      parentNode = parentNode.parentNode;
      nodeCascades.push(new NodeCascade(this, inheritedStyles, true /* isInherited */));
    }

    return new DOMInheritanceCascade(nodeCascades);

    /**
     * @param {!Array<!SDK.CSSStyleDeclaration>|!Set<!SDK.CSSStyleDeclaration>} styles
     * @param {!SDK.CSSStyleDeclaration} query
     * @return {boolean}
     */
    function containsStyle(styles, query) {
      if (!query.styleSheetId || !query.range) {
        return false;
      }
      for (const style of styles) {
        if (query.styleSheetId === style.styleSheetId && style.range && query.range.equal(style.range)) {
          return true;
        }
      }
      return false;
    }
  }

  /**
   * @param {!Array.<!Protocol.CSS.PseudoElementMatches>} pseudoPayload
   * @return {!Map<!Protocol.DOM.PseudoType, !DOMInheritanceCascade>}
   */
  _buildPseudoCascades(pseudoPayload) {
    /** @type {!Map<!Protocol.DOM.PseudoType, !DOMInheritanceCascade>} */
    const pseudoCascades = new Map();
    if (!pseudoPayload) {
      return pseudoCascades;
    }
    for (let i = 0; i < pseudoPayload.length; ++i) {
      const entryPayload = pseudoPayload[i];
      // PseudoElement nodes are not created unless "content" css property is set.
      const pseudoElement = this._node.pseudoElements().get(entryPayload.pseudoType) || null;
      const pseudoStyles = [];
      const rules = entryPayload.matches || [];
      for (let j = rules.length - 1; j >= 0; --j) {
        const pseudoRule = new SDK.CSSStyleRule(this._cssModel, rules[j].rule);
        pseudoStyles.push(pseudoRule.style);
        this._nodeForStyle.set(pseudoRule.style, pseudoElement);
        if (pseudoElement) {
          this._addMatchingSelectors(pseudoElement, pseudoRule, rules[j].matchingSelectors);
        }
      }
      const nodeCascade = new NodeCascade(this, pseudoStyles, false /* isInherited */);
      pseudoCascades.set(entryPayload.pseudoType, new DOMInheritanceCascade([nodeCascade]));
    }
    return pseudoCascades;
  }

  /**
   * @param {!SDK.DOMNode} node
   * @param {!SDK.CSSStyleRule} rule
   * @param {!Array<number>} matchingSelectorIndices
   * @this {CSSMatchedStyles}
   */
  _addMatchingSelectors(node, rule, matchingSelectorIndices) {
    for (const matchingSelectorIndex of matchingSelectorIndices) {
      const selector = rule.selectors[matchingSelectorIndex];
      this._setSelectorMatches(node, selector.text, true);
    }
  }

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

  /**
   * @return {!SDK.CSSModel}
   */
  cssModel() {
    return this._cssModel;
  }

  /**
   * @param {!SDK.CSSStyleRule} rule
   * @return {boolean}
   */
  hasMatchingSelectors(rule) {
    const matchingSelectors = this.matchingSelectors(rule);
    return matchingSelectors.length > 0 && this.mediaMatches(rule.style);
  }

  /**
   * @param {!SDK.CSSStyleRule} rule
   * @return {!Array<number>}
   */
  matchingSelectors(rule) {
    const node = this.nodeForStyle(rule.style);
    if (!node) {
      return [];
    }
    const map = this._matchingSelectors.get(node.id);
    if (!map) {
      return [];
    }
    const result = [];
    for (let i = 0; i < rule.selectors.length; ++i) {
      if (map.get(rule.selectors[i].text)) {
        result.push(i);
      }
    }
    return result;
  }

  /**
   * @param {!SDK.CSSStyleRule} rule
   * @return {!Promise}
   */
  recomputeMatchingSelectors(rule) {
    const node = this.nodeForStyle(rule.style);
    if (!node) {
      return Promise.resolve();
    }
    const promises = [];
    for (const selector of rule.selectors) {
      promises.push(querySelector.call(this, node, selector.text));
    }
    return Promise.all(promises);

    /**
     * @param {!SDK.DOMNode} node
     * @param {string} selectorText
     * @this {CSSMatchedStyles}
     */
    async function querySelector(node, selectorText) {
      const ownerDocument = node.ownerDocument || null;
      // We assume that "matching" property does not ever change during the
      // MatchedStyleResult's lifetime.
      const map = this._matchingSelectors.get(node.id);
      if ((map && map.has(selectorText)) || !ownerDocument) {
        return;
      }

      const matchingNodeIds = await this._node.domModel().querySelectorAll(ownerDocument.id, selectorText);

      if (matchingNodeIds) {
        this._setSelectorMatches(node, selectorText, matchingNodeIds.indexOf(node.id) !== -1);
      }
    }
  }

  /**
   * @param {!SDK.CSSStyleRule} rule
   * @param {!SDK.DOMNode} node
   * @return {!Promise}
   */
  addNewRule(rule, node) {
    this._addedStyles.set(rule.style, node);
    return this.recomputeMatchingSelectors(rule);
  }

  /**
   * @param {!SDK.DOMNode} node
   * @param {string} selectorText
   * @param {boolean} value
   */
  _setSelectorMatches(node, selectorText, value) {
    let map = this._matchingSelectors.get(node.id);
    if (!map) {
      map = new Map();
      this._matchingSelectors.set(node.id, map);
    }
    map.set(selectorText, value);
  }

  /**
   * @param {!SDK.CSSStyleDeclaration} style
   * @return {boolean}
   */
  mediaMatches(style) {
    const media = style.parentRule ? style.parentRule.media : [];
    for (let i = 0; media && i < media.length; ++i) {
      if (!media[i].active()) {
        return false;
      }
    }
    return true;
  }

  /**
   * @return {!Array<!SDK.CSSStyleDeclaration>}
   */
  nodeStyles() {
    return this._mainDOMCascade.styles();
  }

  /**
   * @return {!Array.<!SDK.CSSKeyframesRule>}
   */
  keyframes() {
    return this._keyframes;
  }

  /**
   * @param {!Protocol.DOM.PseudoType} pseudoType
   * @return {!Array<!SDK.CSSStyleDeclaration>}
   */
  pseudoStyles(pseudoType) {
    const domCascade = this._pseudoDOMCascades.get(pseudoType);
    return domCascade ? domCascade.styles() : [];
  }

  /**
   * @return {!Set<!Protocol.DOM.PseudoType>}
   */
  pseudoTypes() {
    return new Set(this._pseudoDOMCascades.keys());
  }

  /**
   * @param {!SDK.CSSStyleDeclaration} style
   * @return {boolean}
   */
  _containsInherited(style) {
    const properties = style.allProperties();
    for (let i = 0; i < properties.length; ++i) {
      const property = properties[i];
      // Does this style contain non-overridden inherited property?
      if (property.activeInStyle() && SDK.cssMetadata().isPropertyInherited(property.name)) {
        return true;
      }
    }
    return false;
  }

  /**
   * @param {!SDK.CSSStyleDeclaration} style
   * @return {?SDK.DOMNode}
   */
  nodeForStyle(style) {
    return this._addedStyles.get(style) || this._nodeForStyle.get(style) || null;
  }

  /**
   * @param {!SDK.CSSStyleDeclaration} style
   * @return {!Array<string>}
   */
  availableCSSVariables(style) {
    const domCascade = this._styleToDOMCascade.get(style) || null;
    return domCascade ? domCascade.availableCSSVariables(style) : [];
  }

  /**
   * @param {!SDK.CSSStyleDeclaration} style
   * @param {string} variableName
   * @return {?string}
   */
  computeCSSVariable(style, variableName) {
    const domCascade = this._styleToDOMCascade.get(style) || null;
    return domCascade ? domCascade.computeCSSVariable(style, variableName) : null;
  }

  /**
   * @param {!SDK.CSSStyleDeclaration} style
   * @param {string} value
   * @return {?string}
   */
  computeValue(style, value) {
    const domCascade = this._styleToDOMCascade.get(style) || null;
    return domCascade ? domCascade.computeValue(style, value) : null;
  }

  /**
   * @param {!SDK.CSSStyleDeclaration} style
   * @return {boolean}
   */
  isInherited(style) {
    return this._inheritedStyles.has(style);
  }

  /**
   * @param {!SDK.CSSProperty} property
   * @return {?PropertyState}
   */
  propertyState(property) {
    const domCascade = this._styleToDOMCascade.get(property.ownerStyle);
    return domCascade ? domCascade.propertyState(property) : null;
  }

  resetActiveProperties() {
    this._mainDOMCascade.reset();
    for (const domCascade of this._pseudoDOMCascades.values()) {
      domCascade.reset();
    }
  }
}

class NodeCascade {
  /**
   * @param {!CSSMatchedStyles} matchedStyles
   * @param {!Array<!SDK.CSSStyleDeclaration>} styles
   * @param {boolean} isInherited
   */
  constructor(matchedStyles, styles, isInherited) {
    this._matchedStyles = matchedStyles;
    this._styles = styles;
    this._isInherited = isInherited;
    /** @type {!Map<!SDK.CSSProperty, !PropertyState>} */
    this._propertiesState = new Map();
    /** @type {!Map.<string, !SDK.CSSProperty>} */
    this._activeProperties = new Map();
  }

  _computeActiveProperties() {
    this._propertiesState.clear();
    this._activeProperties.clear();

    for (const style of this._styles) {
      const rule = style.parentRule;
      // Compute cascade for CSSStyleRules only.
      if (rule && !(rule instanceof SDK.CSSStyleRule)) {
        continue;
      }
      if (rule && !this._matchedStyles.hasMatchingSelectors(rule)) {
        continue;
      }

      for (const property of style.allProperties()) {
        // Do not pick non-inherited properties from inherited styles.
        if (this._isInherited && !SDK.cssMetadata().isPropertyInherited(property.name)) {
          continue;
        }

        if (!property.activeInStyle()) {
          this._propertiesState.set(property, PropertyState.Overloaded);
          continue;
        }

        const canonicalName = SDK.cssMetadata().canonicalPropertyName(property.name);
        const activeProperty = this._activeProperties.get(canonicalName);
        if (activeProperty && (activeProperty.important || !property.important)) {
          this._propertiesState.set(property, PropertyState.Overloaded);
          continue;
        }

        if (activeProperty) {
          this._propertiesState.set(activeProperty, PropertyState.Overloaded);
        }
        this._propertiesState.set(property, PropertyState.Active);
        this._activeProperties.set(canonicalName, property);
      }
    }
  }
}

class DOMInheritanceCascade {
  /**
   * @param {!Array<!NodeCascade>} nodeCascades
   */
  constructor(nodeCascades) {
    this._nodeCascades = nodeCascades;
    /** @type {!Map<!SDK.CSSProperty, !PropertyState>} */
    this._propertiesState = new Map();
    /** @type {!Map<!NodeCascade, !Map<string, string>>} */
    this._availableCSSVariables = new Map();
    /** @type {!Map<!NodeCascade, !Map<string, ?string>>} */
    this._computedCSSVariables = new Map();
    this._initialized = false;

    /** @type {!Map<!SDK.CSSStyleDeclaration, !NodeCascade>} */
    this._styleToNodeCascade = new Map();
    for (const nodeCascade of nodeCascades) {
      for (const style of nodeCascade._styles) {
        this._styleToNodeCascade.set(style, nodeCascade);
      }
    }
  }

  /**
   * @param {!SDK.CSSStyleDeclaration} style
   * @return {!Array<string>}
   */
  availableCSSVariables(style) {
    const nodeCascade = this._styleToNodeCascade.get(style);
    if (!nodeCascade) {
      return [];
    }
    this._ensureInitialized();
    return Array.from(this._availableCSSVariables.get(nodeCascade).keys());
  }

  /**
   * @param {!SDK.CSSStyleDeclaration} style
   * @param {string} variableName
   * @return {?string}
   */
  computeCSSVariable(style, variableName) {
    const nodeCascade = this._styleToNodeCascade.get(style);
    if (!nodeCascade) {
      return null;
    }
    this._ensureInitialized();
    const availableCSSVariables = this._availableCSSVariables.get(nodeCascade);
    const computedCSSVariables = this._computedCSSVariables.get(nodeCascade);
    return this._innerComputeCSSVariable(availableCSSVariables, computedCSSVariables, variableName);
  }

  /**
   * @param {!SDK.CSSStyleDeclaration} style
   * @param {string} value
   * @return {?string}
   */
  computeValue(style, value) {
    const nodeCascade = this._styleToNodeCascade.get(style);
    if (!nodeCascade) {
      return null;
    }
    this._ensureInitialized();
    const availableCSSVariables = this._availableCSSVariables.get(nodeCascade);
    const computedCSSVariables = this._computedCSSVariables.get(nodeCascade);
    return this._innerComputeValue(availableCSSVariables, computedCSSVariables, value);
  }

  /**
   * @param {!Map<string, string>} availableCSSVariables
   * @param {!Map<string, ?string>} computedCSSVariables
   * @param {string} variableName
   * @return {?string}
   */
  _innerComputeCSSVariable(availableCSSVariables, computedCSSVariables, variableName) {
    if (!availableCSSVariables.has(variableName)) {
      return null;
    }
    if (computedCSSVariables.has(variableName)) {
      return computedCSSVariables.get(variableName);
    }
    // Set dummy value to avoid infinite recursion.
    computedCSSVariables.set(variableName, null);
    const definedValue = availableCSSVariables.get(variableName);
    const computedValue = this._innerComputeValue(availableCSSVariables, computedCSSVariables, definedValue);
    computedCSSVariables.set(variableName, computedValue);
    return computedValue;
  }

  /**
   * @param {!Map<string, string>} availableCSSVariables
   * @param {!Map<string, ?string>} computedCSSVariables
   * @param {string} value
   * @return {?string}
   */
  _innerComputeValue(availableCSSVariables, computedCSSVariables, value) {
    const results = TextUtils.TextUtils.splitStringByRegexes(value, [SDK.CSSMetadata.VariableRegex]);
    const tokens = [];
    for (const result of results) {
      if (result.regexIndex === -1) {
        tokens.push(result.value);
        continue;
      }
      // process var() function
      const regexMatch = result.value.match(/^var\((--[a-zA-Z0-9-_]+)[,]?\s*(.*)\)$/);
      if (!regexMatch) {
        return null;
      }
      const cssVariable = regexMatch[1];
      const computedValue = this._innerComputeCSSVariable(availableCSSVariables, computedCSSVariables, cssVariable);
      if (computedValue === null && !regexMatch[2]) {
        return null;
      }
      if (computedValue === null) {
        tokens.push(regexMatch[2]);
      } else {
        tokens.push(computedValue);
      }
    }
    return tokens.map(token => token.trim()).join(' ');
  }

  /**
   * @return {!Array<!SDK.CSSStyleDeclaration>}
   */
  styles() {
    return Array.from(this._styleToNodeCascade.keys());
  }

  /**
   * @param {!SDK.CSSProperty} property
   * @return {?PropertyState}
   */
  propertyState(property) {
    this._ensureInitialized();
    return this._propertiesState.get(property) || null;
  }

  reset() {
    this._initialized = false;
    this._propertiesState.clear();
    this._availableCSSVariables.clear();
    this._computedCSSVariables.clear();
  }

  _ensureInitialized() {
    if (this._initialized) {
      return;
    }
    this._initialized = true;

    const activeProperties = new Map();
    for (const nodeCascade of this._nodeCascades) {
      nodeCascade._computeActiveProperties();
      for (const entry of nodeCascade._propertiesState.entries()) {
        const property = /** @type {!SDK.CSSProperty} */ (entry[0]);
        const state = /** @type {!PropertyState} */ (entry[1]);
        if (state === PropertyState.Overloaded) {
          this._propertiesState.set(property, PropertyState.Overloaded);
          continue;
        }
        const canonicalName = SDK.cssMetadata().canonicalPropertyName(property.name);
        if (activeProperties.has(canonicalName)) {
          this._propertiesState.set(property, PropertyState.Overloaded);
          continue;
        }
        activeProperties.set(canonicalName, property);
        this._propertiesState.set(property, PropertyState.Active);
      }
    }
    // If every longhand of the shorthand is not active, then the shorthand is not active too.
    for (const entry of activeProperties.entries()) {
      const canonicalName = /** @type {string} */ (entry[0]);
      const shorthandProperty = /** @type {!SDK.CSSProperty} */ (entry[1]);
      const shorthandStyle = shorthandProperty.ownerStyle;
      const longhands = shorthandStyle.longhandProperties(shorthandProperty.name);
      if (!longhands.length) {
        continue;
      }
      let hasActiveLonghands = false;
      for (const longhand of longhands) {
        const longhandCanonicalName = SDK.cssMetadata().canonicalPropertyName(longhand.name);
        const longhandActiveProperty = activeProperties.get(longhandCanonicalName);
        if (!longhandActiveProperty) {
          continue;
        }
        if (longhandActiveProperty.ownerStyle === shorthandStyle) {
          hasActiveLonghands = true;
          break;
        }
      }
      if (hasActiveLonghands) {
        continue;
      }
      activeProperties.delete(canonicalName);
      this._propertiesState.set(shorthandProperty, PropertyState.Overloaded);
    }

    // Work inheritance chain backwards to compute visible CSS Variables.
    const accumulatedCSSVariables = new Map();
    for (let i = this._nodeCascades.length - 1; i >= 0; --i) {
      const nodeCascade = this._nodeCascades[i];
      for (const entry of nodeCascade._activeProperties.entries()) {
        const propertyName = /** @type {string} */ (entry[0]);
        const property = /** @type {!SDK.CSSProperty} */ (entry[1]);
        if (propertyName.startsWith('--')) {
          accumulatedCSSVariables.set(propertyName, property.value);
        }
      }
      this._availableCSSVariables.set(nodeCascade, new Map(accumulatedCSSVariables));
      this._computedCSSVariables.set(nodeCascade, new Map());
    }
  }
}

/** @enum {string} */
export const PropertyState = {
  Active: 'Active',
  Overloaded: 'Overloaded'
};

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

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

/** @constructor */
SDK.CSSMatchedStyles = CSSMatchedStyles;

/** @enum {string} */
SDK.CSSMatchedStyles.PropertyState = PropertyState;
