/*
 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
 * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc.
 * All rights reserved.
 * Copyright (C) 2012 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. AND ITS 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 APPLE INC. OR ITS 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.
 */

#ifndef ScopedStyleResolver_h
#define ScopedStyleResolver_h

#include "core/css/ActiveStyleSheets.h"
#include "core/css/ElementRuleCollector.h"
#include "core/css/RuleSet.h"
#include "core/dom/TreeScope.h"
#include "wtf/HashMap.h"
#include "wtf/HashSet.h"

namespace blink {

class PageRuleCollector;
class StyleSheetContents;
class ViewportStyleResolver;

// This class selects a ComputedStyle for a given element based on a collection
// of stylesheets.
class ScopedStyleResolver final : public GarbageCollected<ScopedStyleResolver> {
  WTF_MAKE_NONCOPYABLE(ScopedStyleResolver);

 public:
  static ScopedStyleResolver* create(TreeScope& scope) {
    return new ScopedStyleResolver(scope);
  }

  const TreeScope& treeScope() const { return *m_scope; }
  ScopedStyleResolver* parent() const;

  StyleRuleKeyframes* keyframeStylesForAnimation(
      const StringImpl* animationName);

  void appendCSSStyleSheet(CSSStyleSheet&, const MediaQueryEvaluator&);
  void appendActiveStyleSheets(unsigned index, const ActiveStyleSheetVector&);
  void collectMatchingAuthorRules(ElementRuleCollector&,
                                  CascadeOrder = ignoreCascadeOrder);
  void collectMatchingShadowHostRules(ElementRuleCollector&,
                                      CascadeOrder = ignoreCascadeOrder);
  void collectMatchingTreeBoundaryCrossingRules(
      ElementRuleCollector&,
      CascadeOrder = ignoreCascadeOrder);
  void matchPageRules(PageRuleCollector&);
  void collectFeaturesTo(RuleFeatureSet&,
                         HeapHashSet<Member<const StyleSheetContents>>&
                             visitedSharedStyleSheetContents) const;
  void resetAuthorStyle();
  bool hasDeepOrShadowSelector() const { return m_hasDeepOrShadowSelector; }
  void setHasUnresolvedKeyframesRule() { m_hasUnresolvedKeyframesRule = true; }
  static void keyframesRulesAdded(const TreeScope&);
  static ContainerNode& invalidationRootForTreeScope(const TreeScope&);

  DECLARE_TRACE();

 private:
  explicit ScopedStyleResolver(TreeScope& scope) : m_scope(scope) {}

  void addTreeBoundaryCrossingRules(const RuleSet&,
                                    CSSStyleSheet*,
                                    unsigned sheetIndex);
  void addKeyframeRules(const RuleSet&);
  void addFontFaceRules(const RuleSet&);
  void addKeyframeStyle(StyleRuleKeyframes*);

  Member<TreeScope> m_scope;

  HeapVector<Member<CSSStyleSheet>> m_authorStyleSheets;

  using KeyframesRuleMap =
      HeapHashMap<const StringImpl*, Member<StyleRuleKeyframes>>;
  KeyframesRuleMap m_keyframesRuleMap;

  class RuleSubSet final : public GarbageCollected<RuleSubSet> {
   public:
    static RuleSubSet* create(CSSStyleSheet* sheet,
                              unsigned index,
                              RuleSet* rules) {
      return new RuleSubSet(sheet, index, rules);
    }

    Member<CSSStyleSheet> m_parentStyleSheet;
    unsigned m_parentIndex;
    Member<RuleSet> m_ruleSet;

    DECLARE_TRACE();

   private:
    RuleSubSet(CSSStyleSheet* sheet, unsigned index, RuleSet* rules)
        : m_parentStyleSheet(sheet), m_parentIndex(index), m_ruleSet(rules) {}
  };
  using CSSStyleSheetRuleSubSet = HeapVector<Member<RuleSubSet>>;

  Member<CSSStyleSheetRuleSubSet> m_treeBoundaryCrossingRuleSet;
  bool m_hasDeepOrShadowSelector = false;
  bool m_hasUnresolvedKeyframesRule = false;
};

}  // namespace blink

#endif  // ScopedStyleResolver_h
