/*
 * (C) 1999-2003 Lars Knoll (knoll@kde.org)
 * Copyright (C) 2004, 2006, 2007, 2008, 2009, 2010, 2012, 2013 Apple 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.
 */

#pragma once

#include "CSSRuleList.h"
#include "CommonAtomStrings.h"
#include "ExceptionOr.h"
#include "StyleSheet.h"
#include <memory>
#include <wtf/Noncopyable.h>
#include <wtf/TypeCasts.h>
#include <wtf/WeakPtr.h>
#include <wtf/text/AtomStringHash.h>
#include <wtf/text/TextPosition.h>

namespace WebCore {

class CSSImportRule;
class CSSParser;
class CSSRule;
class CSSStyleSheet;
class CachedCSSStyleSheet;
class Document;
class Element;
class MediaQuerySet;
class StyleRuleKeyframes;
class StyleSheetContents;

namespace Style {
class Scope;
}

class CSSStyleSheet final : public StyleSheet {
public:
    static Ref<CSSStyleSheet> create(Ref<StyleSheetContents>&&, CSSImportRule* ownerRule = 0);
    static Ref<CSSStyleSheet> create(Ref<StyleSheetContents>&&, Node& ownerNode, const std::optional<bool>& isOriginClean = std::nullopt);
    static Ref<CSSStyleSheet> createInline(Ref<StyleSheetContents>&&, Element& owner, const TextPosition& startPosition);

    virtual ~CSSStyleSheet();

    CSSStyleSheet* parentStyleSheet() const final;
    Node* ownerNode() const final { return m_ownerNode; }
    MediaList* media() const final;
    String href() const final;
    String title() const final { return m_title; }
    bool disabled() const final { return m_isDisabled; }
    void setDisabled(bool) final;

    WEBCORE_EXPORT RefPtr<CSSRuleList> cssRules();
    ExceptionOr<Ref<CSSRuleList>> cssRulesForBindings();
    ExceptionOr<Ref<CSSRuleList>> rules() { return this->cssRulesForBindings(); }

    WEBCORE_EXPORT ExceptionOr<unsigned> insertRule(const String& rule, unsigned index);
    WEBCORE_EXPORT ExceptionOr<void> deleteRule(unsigned index);
    
    WEBCORE_EXPORT ExceptionOr<int> addRule(const String& selector, const String& style, std::optional<unsigned> index);
    ExceptionOr<void> removeRule(unsigned index) { return deleteRule(index); }
    
    // For CSSRuleList.
    unsigned length() const;
    CSSRule* item(unsigned index);

    void clearOwnerNode() final;
    CSSImportRule* ownerRule() const final { return m_ownerRule; }
    URL baseURL() const final;
    bool isLoading() const final;
    
    void clearOwnerRule() { m_ownerRule = 0; }

    Document* ownerDocument() const;
    CSSStyleSheet& rootStyleSheet();
    const CSSStyleSheet& rootStyleSheet() const;
    Style::Scope* styleScope();

    MediaQuerySet* mediaQueries() const { return m_mediaQueries.get(); }
    void setMediaQueries(Ref<MediaQuerySet>&&);
    void setTitle(const String& title) { m_title = title; }

    bool hadRulesMutation() const { return m_mutatedRules; }
    void clearHadRulesMutation() { m_mutatedRules = false; }

    enum RuleMutationType { OtherMutation, RuleInsertion, KeyframesRuleMutation };
    enum WhetherContentsWereClonedForMutation { ContentsWereNotClonedForMutation = 0, ContentsWereClonedForMutation };

    class RuleMutationScope {
        WTF_MAKE_NONCOPYABLE(RuleMutationScope);
    public:
        RuleMutationScope(CSSStyleSheet*, RuleMutationType = OtherMutation, StyleRuleKeyframes* insertedKeyframesRule = nullptr);
        RuleMutationScope(CSSRule*);
        ~RuleMutationScope();

    private:
        CSSStyleSheet* m_styleSheet;
        RuleMutationType m_mutationType;
        WhetherContentsWereClonedForMutation m_contentsWereClonedForMutation;
        RefPtr<StyleRuleKeyframes> m_insertedKeyframesRule;
        String m_modifiedKeyframesRuleName;
    };

    WhetherContentsWereClonedForMutation willMutateRules();
    void didMutateRules(RuleMutationType, WhetherContentsWereClonedForMutation, StyleRuleKeyframes* insertedKeyframesRule, const String& modifiedKeyframesRuleName);
    void didMutateRuleFromCSSStyleDeclaration();
    void didMutate();
    
    void clearChildRuleCSSOMWrappers();
    void reattachChildRuleCSSOMWrappers();

    StyleSheetContents& contents() { return m_contents; }

    bool isInline() const { return m_isInlineStylesheet; }
    TextPosition startPosition() const { return m_startPosition; }

    void detachFromDocument() { m_ownerNode = nullptr; }

    bool canAccessRules() const;

    String debugDescription() const final;

private:
    CSSStyleSheet(Ref<StyleSheetContents>&&, CSSImportRule* ownerRule);
    CSSStyleSheet(Ref<StyleSheetContents>&&, Node* ownerNode, const TextPosition& startPosition, bool isInlineStylesheet);
    CSSStyleSheet(Ref<StyleSheetContents>&&, Node& ownerNode, const TextPosition& startPosition, bool isInlineStylesheet, const std::optional<bool>&);

    bool isCSSStyleSheet() const final { return true; }
    String type() const final { return cssContentTypeAtom(); }

    Ref<StyleSheetContents> m_contents;
    bool m_isInlineStylesheet { false };
    bool m_isDisabled { false };
    bool m_mutatedRules { false };
    std::optional<bool> m_isOriginClean;
    String m_title;
    RefPtr<MediaQuerySet> m_mediaQueries;
    WeakPtr<Style::Scope> m_styleScope;

    Node* m_ownerNode { nullptr };
    CSSImportRule* m_ownerRule { nullptr };

    TextPosition m_startPosition;

    mutable RefPtr<MediaList> m_mediaCSSOMWrapper;
    mutable Vector<RefPtr<CSSRule>> m_childRuleCSSOMWrappers;
    mutable std::unique_ptr<CSSRuleList> m_ruleListCSSOMWrapper;
};

} // namespace WebCore

SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::CSSStyleSheet)
    static bool isType(const WebCore::StyleSheet& styleSheet) { return styleSheet.isCSSStyleSheet(); }
SPECIALIZE_TYPE_TRAITS_END()
