/*
 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
 *           (C) 2004-2005 Allan Sandfeld Jensen (kde@carewolf.com)
 * Copyright (C) 2006, 2007 Nicholas Shanks (webkit@nickshanks.com)
 * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple Inc. All
 * rights reserved.
 * Copyright (C) 2007 Alexey Proskuryakov <ap@webkit.org>
 * Copyright (C) 2007, 2008 Eric Seidel <eric@webkit.org>
 * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved.
 * (http://www.torchmobile.com/)
 * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
 * Copyright (C) Research In Motion Limited 2011. All rights reserved.
 * Copyright (C) 2012 Google Inc. All rights reserved.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

#include "core/css/RuleSet.h"

#include "core/HTMLNames.h"
#include "core/css/CSSFontSelector.h"
#include "core/css/CSSSelector.h"
#include "core/css/CSSSelectorList.h"
#include "core/css/SelectorFilter.h"
#include "core/css/StyleRuleImport.h"
#include "core/css/StyleSheetContents.h"
#include "core/html/track/TextTrackCue.h"
#include "platform/RuntimeEnabledFeatures.h"
#include "platform/heap/HeapTerminatedArrayBuilder.h"
#include "platform/tracing/TraceEvent.h"
#include "platform/weborigin/SecurityOrigin.h"

#include "wtf/TerminatedArrayBuilder.h"

namespace blink {

using namespace HTMLNames;

// -----------------------------------------------------------------

static bool containsUncommonAttributeSelector(const CSSSelector&);

static inline bool selectorListContainsUncommonAttributeSelector(
    const CSSSelector* selector) {
  const CSSSelectorList* selectorList = selector->selectorList();
  if (!selectorList)
    return false;
  for (const CSSSelector* selector = selectorList->first(); selector;
       selector = CSSSelectorList::next(*selector)) {
    if (containsUncommonAttributeSelector(*selector))
      return true;
  }
  return false;
}

static inline bool isCommonAttributeSelectorAttribute(
    const QualifiedName& attribute) {
  // These are explicitly tested for equality in canShareStyleWithElement.
  return attribute == typeAttr || attribute == readonlyAttr;
}

static bool containsUncommonAttributeSelector(const CSSSelector& selector) {
  const CSSSelector* current = &selector;
  for (; current; current = current->tagHistory()) {
    // Allow certain common attributes (used in the default style) in the
    // selectors that match the current element.
    if (current->isAttributeSelector() &&
        !isCommonAttributeSelectorAttribute(current->attribute()))
      return true;
    if (selectorListContainsUncommonAttributeSelector(current))
      return true;
    if (current->relationIsAffectedByPseudoContent() ||
        current->getPseudoType() == CSSSelector::PseudoSlotted)
      return false;
    if (current->relation() != CSSSelector::SubSelector) {
      current = current->tagHistory();
      break;
    }
  }

  for (; current; current = current->tagHistory()) {
    if (current->isAttributeSelector())
      return true;
    if (selectorListContainsUncommonAttributeSelector(current))
      return true;
  }
  return false;
}

static inline PropertyWhitelistType determinePropertyWhitelistType(
    const AddRuleFlags addRuleFlags,
    const CSSSelector& selector) {
  for (const CSSSelector* component = &selector; component;
       component = component->tagHistory()) {
    if (component->getPseudoType() == CSSSelector::PseudoCue ||
        (component->match() == CSSSelector::PseudoElement &&
         component->value() == TextTrackCue::cueShadowPseudoId()))
      return PropertyWhitelistCue;
    if (component->getPseudoType() == CSSSelector::PseudoFirstLetter)
      return PropertyWhitelistFirstLetter;
  }
  return PropertyWhitelistNone;
}

RuleData::RuleData(StyleRule* rule,
                   unsigned selectorIndex,
                   unsigned position,
                   AddRuleFlags addRuleFlags)
    : m_rule(rule),
      m_selectorIndex(selectorIndex),
      m_isLastInArray(false),
      m_position(position),
      m_specificity(selector().specificity()),
      m_containsUncommonAttributeSelector(
          blink::containsUncommonAttributeSelector(selector())),
      m_linkMatchType(selector().computeLinkMatchType()),
      m_hasDocumentSecurityOrigin(addRuleFlags & RuleHasDocumentSecurityOrigin),
      m_propertyWhitelist(
          determinePropertyWhitelistType(addRuleFlags, selector())) {
  SelectorFilter::collectIdentifierHashes(
      selector(), m_descendantSelectorIdentifierHashes, maximumIdentifierCount);
}

void RuleSet::addToRuleSet(const AtomicString& key,
                           PendingRuleMap& map,
                           const RuleData& ruleData) {
  Member<HeapLinkedStack<RuleData>>& rules =
      map.add(key, nullptr).storedValue->value;
  if (!rules)
    rules = new HeapLinkedStack<RuleData>;
  rules->push(ruleData);
}

static void extractValuesforSelector(const CSSSelector* selector,
                                     AtomicString& id,
                                     AtomicString& className,
                                     AtomicString& customPseudoElementName,
                                     AtomicString& tagName) {
  switch (selector->match()) {
    case CSSSelector::Id:
      id = selector->value();
      break;
    case CSSSelector::Class:
      className = selector->value();
      break;
    case CSSSelector::Tag:
      if (selector->tagQName().localName() != starAtom)
        tagName = selector->tagQName().localName();
      break;
    default:
      break;
  }
  if (selector->getPseudoType() == CSSSelector::PseudoWebKitCustomElement ||
      selector->getPseudoType() == CSSSelector::PseudoBlinkInternalElement)
    customPseudoElementName = selector->value();
}

bool RuleSet::findBestRuleSetAndAdd(const CSSSelector& component,
                                    RuleData& ruleData) {
  AtomicString id;
  AtomicString className;
  AtomicString customPseudoElementName;
  AtomicString tagName;

#ifndef NDEBUG
  m_allRules.append(ruleData);
#endif

  const CSSSelector* it = &component;
  for (; it && it->relation() == CSSSelector::SubSelector;
       it = it->tagHistory())
    extractValuesforSelector(it, id, className, customPseudoElementName,
                             tagName);
  if (it)
    extractValuesforSelector(it, id, className, customPseudoElementName,
                             tagName);

  // Prefer rule sets in order of most likely to apply infrequently.
  if (!id.isEmpty()) {
    addToRuleSet(id, ensurePendingRules()->idRules, ruleData);
    return true;
  }
  if (!className.isEmpty()) {
    addToRuleSet(className, ensurePendingRules()->classRules, ruleData);
    return true;
  }
  if (!customPseudoElementName.isEmpty()) {
    // Custom pseudos come before ids and classes in the order of tagHistory,
    // and have a relation of ShadowPseudo between them. Therefore we should
    // never be a situation where extractValuesforSelector finsd id and
    // className in addition to custom pseudo.
    ASSERT(id.isEmpty() && className.isEmpty());
    addToRuleSet(customPseudoElementName,
                 ensurePendingRules()->shadowPseudoElementRules, ruleData);
    return true;
  }

  switch (component.getPseudoType()) {
    case CSSSelector::PseudoCue:
      m_cuePseudoRules.append(ruleData);
      return true;
    case CSSSelector::PseudoLink:
    case CSSSelector::PseudoVisited:
    case CSSSelector::PseudoAnyLink:
      m_linkPseudoClassRules.append(ruleData);
      return true;
    case CSSSelector::PseudoFocus:
      m_focusPseudoClassRules.append(ruleData);
      return true;
    default:
      break;
  }

  if (!tagName.isEmpty()) {
    addToRuleSet(tagName, ensurePendingRules()->tagRules, ruleData);
    return true;
  }

  if (component.isHostPseudoClass()) {
    m_shadowHostRules.append(ruleData);
    return true;
  }

  return false;
}

void RuleSet::addRule(StyleRule* rule,
                      unsigned selectorIndex,
                      AddRuleFlags addRuleFlags) {
  RuleData ruleData(rule, selectorIndex, m_ruleCount++, addRuleFlags);
  if (m_features.collectFeaturesFromRuleData(ruleData) ==
      RuleFeatureSet::SelectorNeverMatches)
    return;

  if (!findBestRuleSetAndAdd(ruleData.selector(), ruleData)) {
    // If we didn't find a specialized map to stick it in, file under universal
    // rules.
    m_universalRules.append(ruleData);
  }
}

void RuleSet::addPageRule(StyleRulePage* rule) {
  ensurePendingRules();  // So that m_pageRules.shrinkToFit() gets called.
  m_pageRules.append(rule);
}

void RuleSet::addFontFaceRule(StyleRuleFontFace* rule) {
  ensurePendingRules();  // So that m_fontFaceRules.shrinkToFit() gets called.
  m_fontFaceRules.append(rule);
}

void RuleSet::addKeyframesRule(StyleRuleKeyframes* rule) {
  ensurePendingRules();  // So that m_keyframesRules.shrinkToFit() gets called.
  m_keyframesRules.append(rule);
}

void RuleSet::addChildRules(const HeapVector<Member<StyleRuleBase>>& rules,
                            const MediaQueryEvaluator& medium,
                            AddRuleFlags addRuleFlags) {
  for (unsigned i = 0; i < rules.size(); ++i) {
    StyleRuleBase* rule = rules[i].get();

    if (rule->isStyleRule()) {
      StyleRule* styleRule = toStyleRule(rule);

      const CSSSelectorList& selectorList = styleRule->selectorList();
      for (const CSSSelector* selector = selectorList.first(); selector;
           selector = selectorList.next(*selector)) {
        size_t selectorIndex = selectorList.selectorIndex(*selector);
        if (selector->hasDeepCombinatorOrShadowPseudo()) {
          m_deepCombinatorOrShadowPseudoRules.append(
              MinimalRuleData(styleRule, selectorIndex, addRuleFlags));
        } else if (selector->hasContentPseudo()) {
          m_contentPseudoElementRules.append(
              MinimalRuleData(styleRule, selectorIndex, addRuleFlags));
        } else if (selector->hasSlottedPseudo()) {
          m_slottedPseudoElementRules.append(
              MinimalRuleData(styleRule, selectorIndex, addRuleFlags));
        } else {
          addRule(styleRule, selectorIndex, addRuleFlags);
        }
      }
    } else if (rule->isPageRule()) {
      addPageRule(toStyleRulePage(rule));
    } else if (rule->isMediaRule()) {
      StyleRuleMedia* mediaRule = toStyleRuleMedia(rule);
      if ((!mediaRule->mediaQueries() ||
           medium.eval(mediaRule->mediaQueries(),
                       &m_viewportDependentMediaQueryResults,
                       &m_deviceDependentMediaQueryResults)))
        addChildRules(mediaRule->childRules(), medium, addRuleFlags);
    } else if (rule->isFontFaceRule()) {
      addFontFaceRule(toStyleRuleFontFace(rule));
    } else if (rule->isKeyframesRule()) {
      addKeyframesRule(toStyleRuleKeyframes(rule));
    } else if (rule->isSupportsRule() &&
               toStyleRuleSupports(rule)->conditionIsSupported()) {
      addChildRules(toStyleRuleSupports(rule)->childRules(), medium,
                    addRuleFlags);
    }
  }
}

void RuleSet::addRulesFromSheet(StyleSheetContents* sheet,
                                const MediaQueryEvaluator& medium,
                                AddRuleFlags addRuleFlags) {
  TRACE_EVENT0("blink", "RuleSet::addRulesFromSheet");

  ASSERT(sheet);

  const HeapVector<Member<StyleRuleImport>>& importRules = sheet->importRules();
  for (unsigned i = 0; i < importRules.size(); ++i) {
    StyleRuleImport* importRule = importRules[i].get();
    if (importRule->styleSheet() &&
        (!importRule->mediaQueries() ||
         medium.eval(importRule->mediaQueries(),
                     &m_viewportDependentMediaQueryResults,
                     &m_deviceDependentMediaQueryResults)))
      addRulesFromSheet(importRule->styleSheet(), medium, addRuleFlags);
  }

  addChildRules(sheet->childRules(), medium, addRuleFlags);
}

void RuleSet::addStyleRule(StyleRule* rule, AddRuleFlags addRuleFlags) {
  for (size_t selectorIndex = 0; selectorIndex != kNotFound;
       selectorIndex =
           rule->selectorList().indexOfNextSelectorAfter(selectorIndex))
    addRule(rule, selectorIndex, addRuleFlags);
}

void RuleSet::compactPendingRules(PendingRuleMap& pendingMap,
                                  CompactRuleMap& compactMap) {
  for (auto& item : pendingMap) {
    HeapLinkedStack<RuleData>* pendingRules = item.value.release();
    CompactRuleMap::ValueType* compactRules =
        compactMap.add(item.key, nullptr).storedValue;

    HeapTerminatedArrayBuilder<RuleData> builder(compactRules->value.release());
    builder.grow(pendingRules->size());
    while (!pendingRules->isEmpty()) {
      builder.append(pendingRules->peek());
      pendingRules->pop();
    }

    compactRules->value = builder.release();
  }
}

void RuleSet::compactRules() {
  ASSERT(m_pendingRules);
  PendingRuleMaps* pendingRules = m_pendingRules.release();
  compactPendingRules(pendingRules->idRules, m_idRules);
  compactPendingRules(pendingRules->classRules, m_classRules);
  compactPendingRules(pendingRules->tagRules, m_tagRules);
  compactPendingRules(pendingRules->shadowPseudoElementRules,
                      m_shadowPseudoElementRules);
  m_linkPseudoClassRules.shrinkToFit();
  m_cuePseudoRules.shrinkToFit();
  m_focusPseudoClassRules.shrinkToFit();
  m_universalRules.shrinkToFit();
  m_shadowHostRules.shrinkToFit();
  m_pageRules.shrinkToFit();
  m_fontFaceRules.shrinkToFit();
  m_keyframesRules.shrinkToFit();
  m_deepCombinatorOrShadowPseudoRules.shrinkToFit();
  m_contentPseudoElementRules.shrinkToFit();
  m_slottedPseudoElementRules.shrinkToFit();
}

DEFINE_TRACE(MinimalRuleData) {
  visitor->trace(m_rule);
}

DEFINE_TRACE(RuleData) {
  visitor->trace(m_rule);
}

DEFINE_TRACE(RuleSet::PendingRuleMaps) {
  visitor->trace(idRules);
  visitor->trace(classRules);
  visitor->trace(tagRules);
  visitor->trace(shadowPseudoElementRules);
}

DEFINE_TRACE(RuleSet) {
  visitor->trace(m_idRules);
  visitor->trace(m_classRules);
  visitor->trace(m_tagRules);
  visitor->trace(m_shadowPseudoElementRules);
  visitor->trace(m_linkPseudoClassRules);
  visitor->trace(m_cuePseudoRules);
  visitor->trace(m_focusPseudoClassRules);
  visitor->trace(m_universalRules);
  visitor->trace(m_shadowHostRules);
  visitor->trace(m_features);
  visitor->trace(m_pageRules);
  visitor->trace(m_fontFaceRules);
  visitor->trace(m_keyframesRules);
  visitor->trace(m_deepCombinatorOrShadowPseudoRules);
  visitor->trace(m_contentPseudoElementRules);
  visitor->trace(m_slottedPseudoElementRules);
  visitor->trace(m_viewportDependentMediaQueryResults);
  visitor->trace(m_deviceDependentMediaQueryResults);
  visitor->trace(m_pendingRules);
#ifndef NDEBUG
  visitor->trace(m_allRules);
#endif
}

#ifndef NDEBUG
void RuleSet::show() const {
  for (const auto& rule : m_allRules)
    rule.selector().show();
}
#endif

}  // namespace blink
