/* 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 dom_struct::dom_struct;
use servo_arc::Arc;
use style::shared_lock::{Locked, SharedRwLockReadGuard, ToCssWithGuard};
use style::stylesheets::{CssRuleType, NestedDeclarationsRule};

use crate::dom::bindings::codegen::Bindings::CSSNestedDeclarationsBinding::CSSNestedDeclarationsMethods;
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::cssrule::{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 CSSNestedDeclarations {
    cssrule: CSSRule,
    #[ignore_malloc_size_of = "Arc"]
    #[no_trace]
    nesteddeclarationsrule: RefCell<Arc<Locked<NestedDeclarationsRule>>>,
    style_decl: MutNullableDom<CSSStyleDeclaration>,
}

impl CSSNestedDeclarations {
    pub(crate) fn new_inherited(
        parent_stylesheet: &CSSStyleSheet,
        nesteddeclarationsrule: Arc<Locked<NestedDeclarationsRule>>,
    ) -> Self {
        Self {
            cssrule: CSSRule::new_inherited(parent_stylesheet),
            nesteddeclarationsrule: RefCell::new(nesteddeclarationsrule),
            style_decl: Default::default(),
        }
    }

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

    pub(crate) fn update_rule(
        &self,
        nesteddeclarationsrule: Arc<Locked<NestedDeclarationsRule>>,
        guard: &SharedRwLockReadGuard,
    ) {
        if let Some(ref style_decl) = self.style_decl.get() {
            style_decl
                .update_property_declaration_block(&nesteddeclarationsrule.read_with(guard).block);
        }
        *self.nesteddeclarationsrule.borrow_mut() = nesteddeclarationsrule;
    }
}

impl SpecificCSSRule for CSSNestedDeclarations {
    fn ty(&self) -> CssRuleType {
        CssRuleType::NestedDeclarations
    }

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

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