/* 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::RefCell;
use std::mem;

use cssparser::{Parser as CssParser, ParserInput as CssParserInput, ToCss};
use dom_struct::dom_struct;
use selectors::parser::{ParseRelative, SelectorList};
use servo_arc::Arc;
use style::selector_parser::SelectorParser;
use style::shared_lock::{Locked, SharedRwLockReadGuard, ToCssWithGuard};
use style::stylesheets::{CssRuleType, CssRules, Origin, StyleRule};

use crate::dom::bindings::codegen::Bindings::CSSStyleRuleBinding::CSSStyleRuleMethods;
use crate::dom::bindings::inheritance::Castable;
use crate::dom::bindings::reflector::{DomGlobal, reflect_dom_object};
use crate::dom::bindings::root::{Dom, DomRoot, MutNullableDom};
use crate::dom::bindings::str::DOMString;
use crate::dom::cssgroupingrule::CSSGroupingRule;
use crate::dom::cssrule::SpecificCSSRule;
use crate::dom::cssstyledeclaration::{CSSModificationAccess, CSSStyleDeclaration, CSSStyleOwner};
use crate::dom::cssstylesheet::CSSStyleSheet;
use crate::dom::window::Window;
use crate::script_runtime::CanGc;

#[dom_struct]
pub(crate) struct CSSStyleRule {
    cssgroupingrule: CSSGroupingRule,
    #[ignore_malloc_size_of = "Arc"]
    #[no_trace]
    stylerule: RefCell<Arc<Locked<StyleRule>>>,
    style_decl: MutNullableDom<CSSStyleDeclaration>,
}

impl CSSStyleRule {
    fn new_inherited(
        parent_stylesheet: &CSSStyleSheet,
        stylerule: Arc<Locked<StyleRule>>,
    ) -> CSSStyleRule {
        CSSStyleRule {
            cssgroupingrule: CSSGroupingRule::new_inherited(parent_stylesheet),
            stylerule: RefCell::new(stylerule),
            style_decl: Default::default(),
        }
    }

    #[cfg_attr(crown, allow(crown::unrooted_must_root))]
    pub(crate) fn new(
        window: &Window,
        parent_stylesheet: &CSSStyleSheet,
        stylerule: Arc<Locked<StyleRule>>,
        can_gc: CanGc,
    ) -> DomRoot<CSSStyleRule> {
        reflect_dom_object(
            Box::new(CSSStyleRule::new_inherited(parent_stylesheet, stylerule)),
            window,
            can_gc,
        )
    }

    pub(crate) fn ensure_rules(&self) -> Arc<Locked<CssRules>> {
        let lock = self.cssgroupingrule.shared_lock();
        let mut guard = lock.write();
        self.stylerule
            .borrow()
            .write_with(&mut guard)
            .rules
            .get_or_insert_with(|| CssRules::new(vec![], lock))
            .clone()
    }

    pub(crate) fn update_rule(
        &self,
        stylerule: Arc<Locked<StyleRule>>,
        guard: &SharedRwLockReadGuard,
    ) {
        if let Some(ref rules) = stylerule.read_with(guard).rules {
            self.cssgroupingrule.update_rules(rules, guard);
        }

        if let Some(ref style_decl) = self.style_decl.get() {
            style_decl.update_property_declaration_block(&stylerule.read_with(guard).block);
        }

        *self.stylerule.borrow_mut() = stylerule;
    }
}

impl SpecificCSSRule for CSSStyleRule {
    fn ty(&self) -> CssRuleType {
        CssRuleType::Style
    }

    fn get_css(&self) -> DOMString {
        let guard = self.cssgroupingrule.shared_lock().read();
        self.stylerule
            .borrow()
            .read_with(&guard)
            .to_css_string(&guard)
            .into()
    }
}

impl CSSStyleRuleMethods<crate::DomTypeHolder> for CSSStyleRule {
    // https://drafts.csswg.org/cssom/#dom-cssstylerule-style
    fn Style(&self, can_gc: CanGc) -> DomRoot<CSSStyleDeclaration> {
        self.style_decl.or_init(|| {
            let guard = self.cssgroupingrule.shared_lock().read();
            CSSStyleDeclaration::new(
                self.global().as_window(),
                CSSStyleOwner::CSSRule(
                    Dom::from_ref(self.upcast()),
                    RefCell::new(self.stylerule.borrow().read_with(&guard).block.clone()),
                ),
                None,
                CSSModificationAccess::ReadWrite,
                can_gc,
            )
        })
    }

    // https://drafts.csswg.org/cssom/#dom-cssstylerule-selectortext
    fn SelectorText(&self) -> DOMString {
        let guard = self.cssgroupingrule.shared_lock().read();
        DOMString::from_string(
            self.stylerule
                .borrow()
                .read_with(&guard)
                .selectors
                .to_css_string(),
        )
    }

    // https://drafts.csswg.org/cssom/#dom-cssstylerule-selectortext
    fn SetSelectorText(&self, value: DOMString) {
        let contents = &self
            .cssgroupingrule
            .parent_stylesheet()
            .style_stylesheet()
            .contents
            .clone();
        // It's not clear from the spec if we should use the stylesheet's namespaces.
        // https://github.com/w3c/csswg-drafts/issues/1511
        let namespaces = contents.namespaces.read();
        let url_data = contents.url_data.read();
        let parser = SelectorParser {
            stylesheet_origin: Origin::Author,
            namespaces: &namespaces,
            url_data: &url_data,
            for_supports_rule: false,
        };
        let mut css_parser = CssParserInput::new(&value);
        let mut css_parser = CssParser::new(&mut css_parser);
        // TODO: Maybe allow setting relative selectors from the OM, if we're in a nested style
        // rule?
        if let Ok(mut s) = SelectorList::parse(&parser, &mut css_parser, ParseRelative::No) {
            self.cssgroupingrule.parent_stylesheet().will_modify();
            // This mirrors what we do in CSSStyleOwner::mutate_associated_block.
            let mut guard = self.cssgroupingrule.shared_lock().write();
            mem::swap(
                &mut self.stylerule.borrow().write_with(&mut guard).selectors,
                &mut s,
            );
            self.cssgroupingrule
                .parent_stylesheet()
                .notify_invalidations();
        }
    }
}
