/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */

use std::cell::{Cell, Ref};
use std::rc::Rc;

use dom_struct::dom_struct;
use js::rust::HandleObject;
use script_bindings::inheritance::Castable;
use script_bindings::realms::InRealm;
use script_bindings::root::Dom;
use servo_arc::Arc;
use style::media_queries::MediaList as StyleMediaList;
use style::shared_lock::{SharedRwLock, SharedRwLockReadGuard};
use style::stylesheets::{
    AllowImportRules, CssRuleTypes, Origin, Stylesheet as StyleStyleSheet, UrlExtraData,
};

use crate::dom::bindings::cell::DomRefCell;
use crate::dom::bindings::codegen::Bindings::CSSStyleSheetBinding::{
    CSSStyleSheetInit, CSSStyleSheetMethods,
};
use crate::dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
use crate::dom::bindings::codegen::GenericBindings::CSSRuleListBinding::CSSRuleList_Binding::CSSRuleListMethods;
use crate::dom::bindings::codegen::UnionTypes::MediaListOrString;
use crate::dom::bindings::error::{Error, ErrorResult, Fallible};
use crate::dom::bindings::refcounted::Trusted;
use crate::dom::bindings::reflector::{
    DomGlobal, reflect_dom_object, reflect_dom_object_with_proto,
};
use crate::dom::bindings::root::{DomRoot, MutNullableDom};
use crate::dom::bindings::str::{DOMString, USVString};
use crate::dom::cssrulelist::{CSSRuleList, RulesSource};
use crate::dom::document::Document;
use crate::dom::element::Element;
use crate::dom::html::htmlstyleelement::HTMLStyleElement;
use crate::dom::medialist::MediaList;
use crate::dom::node::NodeTraits;
use crate::dom::stylesheet::StyleSheet;
use crate::dom::stylesheetlist::StyleSheetListOwner;
use crate::dom::types::Promise;
use crate::dom::window::Window;
use crate::script_runtime::CanGc;
use crate::test::TrustedPromise;

#[dom_struct]
pub(crate) struct CSSStyleSheet {
    stylesheet: StyleSheet,

    /// <https://drafts.csswg.org/cssom/#concept-css-style-sheet-owner-node>
    owner_node: MutNullableDom<Element>,

    /// <https://drafts.csswg.org/cssom/#ref-for-concept-css-style-sheet-css-rules>
    rulelist: MutNullableDom<CSSRuleList>,

    /// The inner Stylo's [Stylesheet].
    #[ignore_malloc_size_of = "Arc"]
    #[no_trace]
    style_stylesheet: DomRefCell<Arc<StyleStyleSheet>>,

    /// The inner Stylo's [SharedRwLock], stored at here to avoid referencing
    /// temporary variables.
    #[no_trace]
    style_shared_lock: SharedRwLock,

    /// <https://drafts.csswg.org/cssom/#concept-css-style-sheet-origin-clean-flag>
    origin_clean: Cell<bool>,

    /// In which [Document] that this stylesheet was constructed.
    ///
    /// <https://drafts.csswg.org/cssom/#concept-css-style-sheet-constructor-document>
    constructor_document: Option<Dom<Document>>,

    /// <https://drafts.csswg.org/cssom/#concept-css-style-sheet-disallow-modification-flag>
    disallow_modification: Cell<bool>,

    /// Documents or shadow DOMs thats adopt this stylesheet, they will be notified whenever
    /// the stylesheet is modified.
    adopters: DomRefCell<Vec<StyleSheetListOwner>>,
}

impl CSSStyleSheet {
    fn new_inherited(
        owner: Option<&Element>,
        type_: DOMString,
        href: Option<DOMString>,
        title: Option<DOMString>,
        stylesheet: Arc<StyleStyleSheet>,
        constructor_document: Option<&Document>,
    ) -> CSSStyleSheet {
        CSSStyleSheet {
            stylesheet: StyleSheet::new_inherited(type_, href, title),
            owner_node: MutNullableDom::new(owner),
            rulelist: MutNullableDom::new(None),
            style_shared_lock: stylesheet.shared_lock.clone(),
            style_stylesheet: DomRefCell::new(stylesheet),
            origin_clean: Cell::new(true),
            constructor_document: constructor_document.map(Dom::from_ref),
            adopters: Default::default(),
            disallow_modification: Cell::new(false),
        }
    }

    #[cfg_attr(crown, allow(crown::unrooted_must_root))]
    #[allow(clippy::too_many_arguments)]
    pub(crate) fn new(
        window: &Window,
        owner: Option<&Element>,
        type_: DOMString,
        href: Option<DOMString>,
        title: Option<DOMString>,
        stylesheet: Arc<StyleStyleSheet>,
        constructor_document: Option<&Document>,
        can_gc: CanGc,
    ) -> DomRoot<CSSStyleSheet> {
        reflect_dom_object(
            Box::new(CSSStyleSheet::new_inherited(
                owner,
                type_,
                href,
                title,
                stylesheet,
                constructor_document,
            )),
            window,
            can_gc,
        )
    }

    #[cfg_attr(crown, allow(crown::unrooted_must_root))]
    #[allow(clippy::too_many_arguments)]
    fn new_with_proto(
        window: &Window,
        proto: Option<HandleObject>,
        owner: Option<&Element>,
        type_: DOMString,
        href: Option<DOMString>,
        title: Option<DOMString>,
        stylesheet: Arc<StyleStyleSheet>,
        constructor_document: Option<&Document>,
        can_gc: CanGc,
    ) -> DomRoot<CSSStyleSheet> {
        reflect_dom_object_with_proto(
            Box::new(CSSStyleSheet::new_inherited(
                owner,
                type_,
                href,
                title,
                stylesheet,
                constructor_document,
            )),
            window,
            proto,
            can_gc,
        )
    }

    fn rulelist(&self, can_gc: CanGc) -> DomRoot<CSSRuleList> {
        self.rulelist.or_init(|| {
            let rules = self.style_stylesheet.borrow().contents.rules.clone();
            CSSRuleList::new(
                self.global().as_window(),
                self,
                RulesSource::Rules(rules),
                can_gc,
            )
        })
    }

    pub(crate) fn disabled(&self) -> bool {
        self.style_stylesheet.borrow().disabled()
    }

    pub(crate) fn owner_node(&self) -> Option<DomRoot<Element>> {
        self.owner_node.get()
    }

    pub(crate) fn set_disabled(&self, disabled: bool) {
        if self.style_stylesheet.borrow().set_disabled(disabled) {
            self.notify_invalidations();
        }
    }

    pub(crate) fn set_owner_node(&self, value: Option<&Element>) {
        self.owner_node.set(value);
    }

    pub(crate) fn shared_lock(&self) -> &SharedRwLock {
        &self.style_shared_lock
    }

    pub(crate) fn style_stylesheet(&self) -> Ref<'_, Arc<StyleStyleSheet>> {
        self.style_stylesheet.borrow()
    }

    pub(crate) fn set_origin_clean(&self, origin_clean: bool) {
        self.origin_clean.set(origin_clean);
    }

    pub(crate) fn medialist(&self, can_gc: CanGc) -> DomRoot<MediaList> {
        MediaList::new(
            self.global().as_window(),
            self,
            self.style_stylesheet().media.clone(),
            can_gc,
        )
    }

    /// <https://drafts.csswg.org/cssom/#concept-css-style-sheet-constructed-flag>
    #[inline]
    pub(crate) fn is_constructed(&self) -> bool {
        self.constructor_document.is_some()
    }

    pub(crate) fn constructor_document_matches(&self, other_doc: &Document) -> bool {
        match &self.constructor_document {
            Some(doc) => *doc == other_doc,
            None => false,
        }
    }

    /// Add a [StyleSheetListOwner] as an adopter to be notified whenever this stylesheet is
    /// modified.
    #[cfg_attr(crown, allow(crown::unrooted_must_root))]
    pub(crate) fn add_adopter(&self, owner: StyleSheetListOwner) {
        debug_assert!(self.is_constructed());
        self.adopters.borrow_mut().push(owner);
    }

    pub(crate) fn remove_adopter(&self, owner: &StyleSheetListOwner) {
        let adopters = &mut *self.adopters.borrow_mut();
        if let Some(index) = adopters.iter().position(|o| o == owner) {
            adopters.swap_remove(index);
        }
    }

    pub(crate) fn will_modify(&self) {
        let Some(node) = self.owner_node.get() else {
            return;
        };

        let Some(node) = node.downcast::<HTMLStyleElement>() else {
            return;
        };

        node.will_modify_stylesheet();
    }

    pub(crate) fn update_style_stylesheet(
        &self,
        style_stylesheet: &Arc<StyleStyleSheet>,
        guard: &SharedRwLockReadGuard,
    ) {
        // When the shared `StylesheetContents` is about to be modified,
        // `CSSStyleSheet::owner_node` performs a copy-on-write to avoid
        // affecting other sharers, see `CSSStyleSheet::will_modify`. And
        // then updates the references to `CssRule` or `PropertyDeclarationBlock`
        // stored in the CSSOMs to ensure that modifications are made only
        // on the new copy.
        *self.style_stylesheet.borrow_mut() = style_stylesheet.clone();
        if let Some(rulelist) = self.rulelist.get() {
            let rules = style_stylesheet.contents.rules.clone();
            rulelist.update_rules(RulesSource::Rules(rules), guard);
        }
    }

    /// Invalidate all stylesheet set this stylesheet is a part on.
    pub(crate) fn notify_invalidations(&self) {
        if let Some(owner) = self.owner_node() {
            owner.stylesheet_list_owner().invalidate_stylesheets();
        }
        for adopter in self.adopters.borrow().iter() {
            adopter.invalidate_stylesheets();
        }
    }

    /// <https://drafts.csswg.org/cssom/#concept-css-style-sheet-disallow-modification-flag>
    pub(crate) fn disallow_modification(&self) -> bool {
        self.disallow_modification.get()
    }
}

impl CSSStyleSheetMethods<crate::DomTypeHolder> for CSSStyleSheet {
    /// <https://drafts.csswg.org/cssom/#dom-cssstylesheet-cssstylesheet>
    fn Constructor(
        window: &Window,
        proto: Option<HandleObject>,
        can_gc: CanGc,
        options: &CSSStyleSheetInit,
    ) -> DomRoot<Self> {
        let doc = window.Document();
        let shared_lock = doc.style_shared_lock().clone();
        let media = Arc::new(shared_lock.wrap(match &options.media {
            Some(media) => match media {
                MediaListOrString::MediaList(media_list) => media_list.clone_media_list(),
                MediaListOrString::String(str) => MediaList::parse_media_list(str, window),
            },
            None => StyleMediaList::empty(),
        }));
        let stylesheet = Arc::new(StyleStyleSheet::from_str(
            "",
            UrlExtraData(window.get_url().get_arc()),
            Origin::Author,
            media,
            shared_lock,
            None,
            window.css_error_reporter(),
            doc.quirks_mode(),
            AllowImportRules::No,
        ));
        if options.disabled {
            stylesheet.set_disabled(true);
        }
        Self::new_with_proto(
            window,
            proto,
            None, // owner
            "text/css".into(),
            None, // href
            None, // title
            stylesheet,
            Some(&window.Document()), // constructor_document
            can_gc,
        )
    }

    /// <https://drafts.csswg.org/cssom/#dom-cssstylesheet-cssrules>
    fn GetCssRules(&self, can_gc: CanGc) -> Fallible<DomRoot<CSSRuleList>> {
        if !self.origin_clean.get() {
            return Err(Error::Security);
        }
        Ok(self.rulelist(can_gc))
    }

    /// <https://drafts.csswg.org/cssom/#dom-cssstylesheet-insertrule>
    fn InsertRule(&self, rule: DOMString, index: u32, can_gc: CanGc) -> Fallible<u32> {
        // Step 1. If the origin-clean flag is unset, throw a SecurityError exception.
        if !self.origin_clean.get() {
            return Err(Error::Security);
        }

        // Step 2. If the disallow modification flag is set, throw a NotAllowedError DOMException.
        if self.disallow_modification() {
            return Err(Error::NotAllowed);
        }

        self.rulelist(can_gc)
            .insert_rule(&rule, index, CssRuleTypes::default(), None, can_gc)
    }

    /// <https://drafts.csswg.org/cssom/#dom-cssstylesheet-deleterule>
    fn DeleteRule(&self, index: u32, can_gc: CanGc) -> ErrorResult {
        // Step 1. If the origin-clean flag is unset, throw a SecurityError exception.
        if !self.origin_clean.get() {
            return Err(Error::Security);
        }

        // Step 2. If the disallow modification flag is set, throw a NotAllowedError DOMException.
        if self.disallow_modification() {
            return Err(Error::NotAllowed);
        }
        self.rulelist(can_gc).remove_rule(index)
    }

    /// <https://drafts.csswg.org/cssom/#dom-cssstylesheet-rules>
    fn GetRules(&self, can_gc: CanGc) -> Fallible<DomRoot<CSSRuleList>> {
        self.GetCssRules(can_gc)
    }

    /// <https://drafts.csswg.org/cssom/#dom-cssstylesheet-removerule>
    fn RemoveRule(&self, index: u32, can_gc: CanGc) -> ErrorResult {
        self.DeleteRule(index, can_gc)
    }

    /// <https://drafts.csswg.org/cssom/#dom-cssstylesheet-addrule>
    fn AddRule(
        &self,
        selector: DOMString,
        block: DOMString,
        optional_index: Option<u32>,
        can_gc: CanGc,
    ) -> Fallible<i32> {
        // > 1. Let *rule* be an empty string.
        // > 2. Append *selector* to *rule*.
        let mut rule = selector;

        // > 3. Append " { " to *rule*.
        // > 4. If *block* is not empty, append *block*, followed by a space, to *rule*.
        // > 5. Append "}" to *rule*.
        if block.is_empty() {
            rule.push_str(" { }");
        } else {
            rule.push_str(" { ");
            rule.push_str(block.str());
            rule.push_str(" }");
        };

        // > 6. Let *index* be *optionalIndex* if provided, or the number of CSS rules in the stylesheet otherwise.
        let index = optional_index.unwrap_or_else(|| self.rulelist(can_gc).Length());

        // > 7. Call `insertRule()`, with *rule* and *index* as arguments.
        self.InsertRule(rule, index, can_gc)?;

        // > 8. Return -1.
        Ok(-1)
    }

    /// <https://drafts.csswg.org/cssom/#dom-cssstylesheet-replace>
    fn Replace(&self, text: USVString, comp: InRealm, can_gc: CanGc) -> Fallible<Rc<Promise>> {
        // Step 1. Let promise be a promise.
        let promise = Promise::new_in_current_realm(comp, can_gc);

        // Step 2. If the constructed flag is not set, or the disallow modification flag is set,
        // reject promise with a NotAllowedError DOMException and return promise.
        if !self.is_constructed() || self.disallow_modification() {
            return Err(Error::NotAllowed);
        }

        // Step 3. Set the disallow modification flag.
        self.disallow_modification.set(true);

        // Step 4. In parallel, do these steps:
        let trusted_sheet = Trusted::new(self);
        let trusted_promise = TrustedPromise::new(promise.clone());

        self.global()
            .task_manager()
            .dom_manipulation_task_source()
            .queue(task!(cssstylesheet_replace: move || {
                let sheet = trusted_sheet.root();

                // Step 4.1. Let rules be the result of running parse a stylesheet’s contents from text.
                // Step 4.2. If rules contains one or more @import rules, remove those rules from rules.
                // We are disallowing import rules in parsing
                let global = sheet.global();
                let window = global.as_window();

                sheet.will_modify();

                #[cfg(feature = "tracing")]
                let _span = tracing::trace_span!("ParseStylesheet", servo_profiling = true).entered();
                StyleStyleSheet::update_from_str(
                    &sheet.style_stylesheet(),
                    &text,
                    UrlExtraData(window.get_url().get_arc()),
                    None,
                    window.css_error_reporter(),
                    AllowImportRules::No,
                );

                // Step 4.3. Set sheet’s CSS rules to rules.
                // We reset our rule list, which will be initialized properly
                // at the next getter access.
                sheet.rulelist.set(None);

                // Notify invalidation to update the styles immediately.
                sheet.notify_invalidations();

                // Step 4.4. Unset sheet’s disallow modification flag.
                sheet.disallow_modification.set(false);

                // Step 4.5. Resolve promise with sheet.
                trusted_promise.root().resolve_native(&sheet, CanGc::note());
            }));

        Ok(promise)
    }

    /// <https://drafts.csswg.org/cssom/#dom-cssstylesheet-replacesync>
    fn ReplaceSync(&self, text: USVString) -> Result<(), Error> {
        // Step 1. If the constructed flag is not set, or the disallow modification flag is set,
        // throw a NotAllowedError DOMException.
        if !self.is_constructed() || self.disallow_modification() {
            return Err(Error::NotAllowed);
        }

        // Step 2. Let rules be the result of running parse a stylesheet’s contents from text.
        let global = self.global();
        let window = global.as_window();

        self.will_modify();

        #[cfg(feature = "tracing")]
        let _span = tracing::trace_span!("ParseStylesheet", servo_profiling = true).entered();
        StyleStyleSheet::update_from_str(
            &self.style_stylesheet(),
            &text,
            UrlExtraData(window.get_url().get_arc()),
            None,
            window.css_error_reporter(),
            AllowImportRules::No, // Step 3.If rules contains one or more @import rules, remove those rules from rules.
        );

        // Step 4. Set sheet’s CSS rules to rules.
        // We reset our rule list, which will be initialized properly
        // at the next getter access.
        self.rulelist.set(None);

        // Notify invalidation to update the styles immediately.
        self.notify_invalidations();

        Ok(())
    }
}
