/* 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::cmp::Ordering;
use std::sync::LazyLock;

use dom_struct::dom_struct;
use html5ever::local_name;
use servo_arc::Arc;
use servo_url::ServoUrl;
use style::attr::AttrValue;
use style::properties::{
    Importance, LonghandId, PropertyDeclarationBlock, PropertyId, ShorthandId,
    SourcePropertyDeclaration, parse_one_declaration_into, parse_style_attribute,
};
use style::selector_parser::PseudoElement;
use style::shared_lock::Locked;
use style::stylesheets::{CssRuleType, Origin, UrlExtraData};
use style_traits::ParsingMode;

use crate::dom::bindings::codegen::Bindings::CSSStyleDeclarationBinding::CSSStyleDeclarationMethods;
use crate::dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
use crate::dom::bindings::error::{Error, ErrorResult, Fallible};
use crate::dom::bindings::inheritance::Castable;
use crate::dom::bindings::reflector::{DomGlobal, Reflector, reflect_dom_object};
use crate::dom::bindings::root::{Dom, DomRoot};
use crate::dom::bindings::str::DOMString;
use crate::dom::cssrule::CSSRule;
use crate::dom::element::Element;
use crate::dom::node::{Node, NodeTraits};
use crate::dom::window::Window;
use crate::script_runtime::CanGc;

// http://dev.w3.org/csswg/cssom/#the-cssstyledeclaration-interface
#[dom_struct]
pub(crate) struct CSSStyleDeclaration {
    reflector_: Reflector,
    owner: CSSStyleOwner,
    readonly: bool,
    #[no_trace]
    pseudo: Option<PseudoElement>,
}

#[derive(JSTraceable, MallocSizeOf)]
#[cfg_attr(crown, crown::unrooted_must_root_lint::must_root)]
pub(crate) enum CSSStyleOwner {
    /// Used when calling `getComputedStyle()` with an invalid pseudo-element selector.
    /// See <https://drafts.csswg.org/cssom/#dom-window-getcomputedstyle>
    Null,
    Element(Dom<Element>),
    CSSRule(
        Dom<CSSRule>,
        #[ignore_malloc_size_of = "Arc"]
        #[no_trace]
        RefCell<Arc<Locked<PropertyDeclarationBlock>>>,
    ),
}

impl CSSStyleOwner {
    // Mutate the declaration block associated to this style owner, and
    // optionally indicate if it has changed (assumed to be true).
    fn mutate_associated_block<F, R>(&self, f: F, can_gc: CanGc) -> R
    where
        F: FnOnce(&mut PropertyDeclarationBlock, &mut bool) -> R,
    {
        // TODO(emilio): This has some duplication just to avoid dummy clones.
        //
        // This is somewhat complex but the complexity is encapsulated.
        let mut changed = true;
        match *self {
            CSSStyleOwner::Null => unreachable!(
                "CSSStyleDeclaration should always be read-only when CSSStyleOwner is Null"
            ),
            CSSStyleOwner::Element(ref el) => {
                let document = el.owner_document();
                let shared_lock = document.style_shared_lock();
                let mut attr = el.style_attribute().borrow_mut().take();
                let result = if let Some(lock) = attr.as_ref() {
                    let mut guard = shared_lock.write();
                    let pdb = lock.write_with(&mut guard);
                    f(pdb, &mut changed)
                } else {
                    let mut pdb = PropertyDeclarationBlock::new();
                    let result = f(&mut pdb, &mut changed);

                    // Here `changed` is somewhat silly, because we know the
                    // exact conditions under it changes.
                    changed = !pdb.declarations().is_empty();
                    if changed {
                        attr = Some(Arc::new(shared_lock.wrap(pdb)));
                    }

                    result
                };

                if changed {
                    // Note that there's no need to remove the attribute here if
                    // the declaration block is empty[1], and if `attr` is
                    // `None` it means that it necessarily didn't change, so no
                    // need to go through all the set_attribute machinery.
                    //
                    // [1]: https://github.com/whatwg/html/issues/2306
                    if let Some(pdb) = attr {
                        let guard = shared_lock.read();
                        let mut serialization = String::new();
                        pdb.read_with(&guard).to_css(&mut serialization).unwrap();
                        el.set_attribute(
                            &local_name!("style"),
                            AttrValue::Declaration(serialization, pdb),
                            can_gc,
                        );
                    }
                } else {
                    // Remember to put it back.
                    *el.style_attribute().borrow_mut() = attr;
                }

                result
            },
            CSSStyleOwner::CSSRule(ref rule, ref pdb) => {
                rule.parent_stylesheet().will_modify();
                let result = {
                    let mut guard = rule.shared_lock().write();
                    f(&mut *pdb.borrow().write_with(&mut guard), &mut changed)
                };
                if changed {
                    rule.parent_stylesheet().notify_invalidations();
                }
                result
            },
        }
    }

    fn with_block<F, R>(&self, f: F) -> R
    where
        F: FnOnce(&PropertyDeclarationBlock) -> R,
    {
        match *self {
            CSSStyleOwner::Null => {
                unreachable!("Should never call with_block for CSStyleOwner::Null")
            },
            CSSStyleOwner::Element(ref el) => match *el.style_attribute().borrow() {
                Some(ref pdb) => {
                    let document = el.owner_document();
                    let guard = document.style_shared_lock().read();
                    f(pdb.read_with(&guard))
                },
                None => {
                    let pdb = PropertyDeclarationBlock::new();
                    f(&pdb)
                },
            },
            CSSStyleOwner::CSSRule(ref rule, ref pdb) => {
                let guard = rule.shared_lock().read();
                f(pdb.borrow().read_with(&guard))
            },
        }
    }

    fn window(&self) -> DomRoot<Window> {
        match *self {
            CSSStyleOwner::Null => {
                unreachable!("Should never try to access window of CSStyleOwner::Null")
            },
            CSSStyleOwner::Element(ref el) => el.owner_window(),
            CSSStyleOwner::CSSRule(ref rule, _) => DomRoot::from_ref(rule.global().as_window()),
        }
    }

    fn base_url(&self) -> ServoUrl {
        match *self {
            CSSStyleOwner::Null => {
                unreachable!("Should never try to access base URL of CSStyleOwner::Null")
            },
            CSSStyleOwner::Element(ref el) => el.owner_document().base_url(),
            CSSStyleOwner::CSSRule(ref rule, _) => ServoUrl::from(
                rule.parent_stylesheet()
                    .style_stylesheet()
                    .contents
                    .url_data
                    .read()
                    .0
                    .clone(),
            )
            .clone(),
        }
    }
}

#[derive(MallocSizeOf, PartialEq)]
pub(crate) enum CSSModificationAccess {
    ReadWrite,
    Readonly,
}

macro_rules! css_properties(
    ( $([$getter:ident, $setter:ident, $id:expr],)* ) => (
        $(
            fn $getter(&self) -> DOMString {
                debug_assert!(
                    $id.enabled_for_all_content(),
                    "Someone forgot a #[Pref] annotation"
                );
                self.get_property_value($id)
            }
            fn $setter(&self, value: DOMString) -> ErrorResult {
                debug_assert!(
                    $id.enabled_for_all_content(),
                    "Someone forgot a #[Pref] annotation"
                );
                self.set_property($id, value, DOMString::new(), CanGc::note())
            }
        )*
    );
);

fn remove_property(decls: &mut PropertyDeclarationBlock, id: &PropertyId) -> bool {
    let first_declaration = decls.first_declaration_to_remove(id);
    let first_declaration = match first_declaration {
        Some(i) => i,
        None => return false,
    };
    decls.remove_property(id, first_declaration);
    true
}

impl CSSStyleDeclaration {
    #[cfg_attr(crown, allow(crown::unrooted_must_root))]
    pub(crate) fn new_inherited(
        owner: CSSStyleOwner,
        pseudo: Option<PseudoElement>,
        modification_access: CSSModificationAccess,
    ) -> CSSStyleDeclaration {
        // If creating a CSSStyleDeclaration with CSSSStyleOwner::Null, this should always
        // be in read-only mode.
        assert!(
            !matches!(owner, CSSStyleOwner::Null) ||
                modification_access == CSSModificationAccess::Readonly
        );

        CSSStyleDeclaration {
            reflector_: Reflector::new(),
            owner,
            readonly: modification_access == CSSModificationAccess::Readonly,
            pseudo,
        }
    }

    #[cfg_attr(crown, allow(crown::unrooted_must_root))]
    pub(crate) fn new(
        global: &Window,
        owner: CSSStyleOwner,
        pseudo: Option<PseudoElement>,
        modification_access: CSSModificationAccess,
        can_gc: CanGc,
    ) -> DomRoot<CSSStyleDeclaration> {
        reflect_dom_object(
            Box::new(CSSStyleDeclaration::new_inherited(
                owner,
                pseudo,
                modification_access,
            )),
            global,
            can_gc,
        )
    }

    pub(crate) fn update_property_declaration_block(
        &self,
        pdb: &Arc<Locked<PropertyDeclarationBlock>>,
    ) {
        if let CSSStyleOwner::CSSRule(_, pdb_cell) = &self.owner {
            *pdb_cell.borrow_mut() = pdb.clone();
        } else {
            panic!("update_rule called on CSSStyleDeclaration with a Element owner");
        }
    }

    fn get_computed_style(&self, property: PropertyId) -> DOMString {
        match self.owner {
            CSSStyleOwner::CSSRule(..) => {
                panic!("get_computed_style called on CSSStyleDeclaration with a CSSRule owner")
            },
            CSSStyleOwner::Element(ref el) => {
                let node = el.upcast::<Node>();
                if !node.is_connected() {
                    return DOMString::new();
                }
                let addr = node.to_trusted_node_address();
                node.owner_window()
                    .resolved_style_query(addr, self.pseudo, property)
            },
            CSSStyleOwner::Null => DOMString::new(),
        }
    }

    fn get_property_value(&self, id: PropertyId) -> DOMString {
        if matches!(self.owner, CSSStyleOwner::Null) {
            return DOMString::new();
        }

        if self.readonly {
            // Readonly style declarations are used for getComputedStyle.
            return self.get_computed_style(id);
        }

        let mut string = String::new();

        self.owner.with_block(|pdb| {
            pdb.property_value_to_css(&id, &mut string).unwrap();
        });

        DOMString::from(string)
    }

    /// <https://drafts.csswg.org/cssom/#dom-cssstyledeclaration-setproperty>
    fn set_property(
        &self,
        id: PropertyId,
        value: DOMString,
        priority: DOMString,
        can_gc: CanGc,
    ) -> ErrorResult {
        self.set_property_inner(
            PotentiallyParsedPropertyId::Parsed(id),
            value,
            priority,
            can_gc,
        )
    }

    /// <https://drafts.csswg.org/cssom/#dom-cssstyledeclaration-setproperty>
    ///
    /// This function receives a `PotentiallyParsedPropertyId` instead of a `DOMString` in case
    /// the caller already has a parsed property ID.
    fn set_property_inner(
        &self,
        id: PotentiallyParsedPropertyId,
        value: DOMString,
        priority: DOMString,
        can_gc: CanGc,
    ) -> ErrorResult {
        // Step 1. If the readonly flag is set, then throw a NoModificationAllowedError exception.
        if self.readonly {
            return Err(Error::NoModificationAllowed);
        }

        let id = match id {
            PotentiallyParsedPropertyId::Parsed(id) => {
                if !id.enabled_for_all_content() {
                    return Ok(());
                }

                id
            },
            PotentiallyParsedPropertyId::NotParsed(unparsed) => {
                match PropertyId::parse_enabled_for_all_content(&unparsed) {
                    Ok(id) => id,
                    Err(..) => return Ok(()),
                }
            },
        };

        self.owner.mutate_associated_block(
            |pdb, changed| {
                // Step 3. If value is the empty string, invoke removeProperty()
                // with property as argument and return.
                if value.is_empty() {
                    *changed = remove_property(pdb, &id);
                    return Ok(());
                }

                // Step 4. If priority is not the empty string and is not an ASCII case-insensitive
                // match for the string "important", then return.
                let importance = match &*priority {
                    "" => Importance::Normal,
                    p if p.eq_ignore_ascii_case("important") => Importance::Important,
                    _ => {
                        *changed = false;
                        return Ok(());
                    },
                };

                // Step 5
                let window = self.owner.window();
                let quirks_mode = window.Document().quirks_mode();
                let mut declarations = SourcePropertyDeclaration::default();
                let result = parse_one_declaration_into(
                    &mut declarations,
                    id,
                    &value,
                    Origin::Author,
                    &UrlExtraData(self.owner.base_url().get_arc()),
                    window.css_error_reporter(),
                    ParsingMode::DEFAULT,
                    quirks_mode,
                    CssRuleType::Style,
                );

                // Step 6
                match result {
                    Ok(()) => {},
                    Err(_) => {
                        *changed = false;
                        return Ok(());
                    },
                }

                let mut updates = Default::default();
                *changed = pdb.prepare_for_update(&declarations, importance, &mut updates);

                if !*changed {
                    return Ok(());
                }

                // Step 7
                // Step 8
                pdb.update(declarations.drain(), importance, &mut updates);

                Ok(())
            },
            can_gc,
        )
    }
}

pub(crate) static ENABLED_LONGHAND_PROPERTIES: LazyLock<Vec<LonghandId>> = LazyLock::new(|| {
    // The 'all' shorthand contains all the enabled longhands with 2 exceptions:
    // 'direction' and 'unicode-bidi', so these must be added afterward.
    let mut enabled_longhands: Vec<LonghandId> = ShorthandId::All.longhands().collect();
    if PropertyId::NonCustom(LonghandId::Direction.into()).enabled_for_all_content() {
        enabled_longhands.push(LonghandId::Direction);
    }
    if PropertyId::NonCustom(LonghandId::UnicodeBidi.into()).enabled_for_all_content() {
        enabled_longhands.push(LonghandId::UnicodeBidi);
    }

    // Sort lexicographically, but with vendor-prefixed properties after standard ones.
    enabled_longhands.sort_unstable_by(|a, b| {
        let a = a.name();
        let b = b.name();
        let is_a_vendor_prefixed = a.starts_with('-');
        let is_b_vendor_prefixed = b.starts_with('-');
        if is_a_vendor_prefixed == is_b_vendor_prefixed {
            a.partial_cmp(b).unwrap()
        } else if is_b_vendor_prefixed {
            Ordering::Less
        } else {
            Ordering::Greater
        }
    });
    enabled_longhands
});

enum PotentiallyParsedPropertyId {
    Parsed(PropertyId),
    NotParsed(DOMString),
}

impl CSSStyleDeclarationMethods<crate::DomTypeHolder> for CSSStyleDeclaration {
    // https://dev.w3.org/csswg/cssom/#dom-cssstyledeclaration-length
    fn Length(&self) -> u32 {
        if matches!(self.owner, CSSStyleOwner::Null) {
            return 0;
        }

        if self.readonly {
            // Readonly style declarations are used for getComputedStyle.
            // TODO: include custom properties whose computed value is not the guaranteed-invalid value.
            return ENABLED_LONGHAND_PROPERTIES.len() as u32;
        }
        self.owner.with_block(|pdb| pdb.declarations().len() as u32)
    }

    // https://dev.w3.org/csswg/cssom/#dom-cssstyledeclaration-item
    fn Item(&self, index: u32) -> DOMString {
        self.IndexedGetter(index).unwrap_or_default()
    }

    // https://dev.w3.org/csswg/cssom/#dom-cssstyledeclaration-getpropertyvalue
    fn GetPropertyValue(&self, property: DOMString) -> DOMString {
        let id = match PropertyId::parse_enabled_for_all_content(&property) {
            Ok(id) => id,
            Err(..) => return DOMString::new(),
        };
        self.get_property_value(id)
    }

    // https://dev.w3.org/csswg/cssom/#dom-cssstyledeclaration-getpropertypriority
    fn GetPropertyPriority(&self, property: DOMString) -> DOMString {
        if self.readonly {
            // Readonly style declarations are used for getComputedStyle.
            return DOMString::new();
        }
        let id = match PropertyId::parse_enabled_for_all_content(&property) {
            Ok(id) => id,
            Err(..) => return DOMString::new(),
        };

        self.owner.with_block(|pdb| {
            if pdb.property_priority(&id).important() {
                DOMString::from("important")
            } else {
                // Step 4
                DOMString::new()
            }
        })
    }

    /// <https://dev.w3.org/csswg/cssom/#dom-cssstyledeclaration-setproperty>
    fn SetProperty(
        &self,
        property: DOMString,
        value: DOMString,
        priority: DOMString,
        can_gc: CanGc,
    ) -> ErrorResult {
        self.set_property_inner(
            PotentiallyParsedPropertyId::NotParsed(property),
            value,
            priority,
            can_gc,
        )
    }

    // https://dev.w3.org/csswg/cssom/#dom-cssstyledeclaration-removeproperty
    fn RemoveProperty(&self, property: DOMString, can_gc: CanGc) -> Fallible<DOMString> {
        // Step 1
        if self.readonly {
            return Err(Error::NoModificationAllowed);
        }

        let id = match PropertyId::parse_enabled_for_all_content(&property) {
            Ok(id) => id,
            Err(..) => return Ok(DOMString::new()),
        };

        let mut string = String::new();
        self.owner.mutate_associated_block(
            |pdb, changed| {
                pdb.property_value_to_css(&id, &mut string).unwrap();
                *changed = remove_property(pdb, &id);
            },
            can_gc,
        );

        // Step 6
        Ok(DOMString::from(string))
    }

    /// <https://drafts.csswg.org/cssom/#dom-cssstyleproperties-cssfloat>
    fn CssFloat(&self) -> DOMString {
        self.get_property_value(PropertyId::NonCustom(LonghandId::Float.into()))
    }

    /// <https://drafts.csswg.org/cssom/#dom-cssstyleproperties-cssfloat>
    fn SetCssFloat(&self, value: DOMString, can_gc: CanGc) -> ErrorResult {
        self.set_property(
            PropertyId::NonCustom(LonghandId::Float.into()),
            value,
            DOMString::new(),
            can_gc,
        )
    }

    // https://dev.w3.org/csswg/cssom/#the-cssstyledeclaration-interface
    fn IndexedGetter(&self, index: u32) -> Option<DOMString> {
        if matches!(self.owner, CSSStyleOwner::Null) {
            return None;
        }
        if self.readonly {
            // Readonly style declarations are used for getComputedStyle.
            // TODO: include custom properties whose computed value is not the guaranteed-invalid value.
            let longhand = ENABLED_LONGHAND_PROPERTIES.get(index as usize)?;
            return Some(DOMString::from(longhand.name()));
        }
        self.owner.with_block(|pdb| {
            let declaration = pdb.declarations().get(index as usize)?;
            Some(DOMString::from(declaration.id().name()))
        })
    }

    // https://drafts.csswg.org/cssom/#dom-cssstyledeclaration-csstext
    fn CssText(&self) -> DOMString {
        if self.readonly {
            // Readonly style declarations are used for getComputedStyle.
            return DOMString::new();
        }
        self.owner.with_block(|pdb| {
            let mut serialization = String::new();
            pdb.to_css(&mut serialization).unwrap();
            DOMString::from(serialization)
        })
    }

    // https://drafts.csswg.org/cssom/#dom-cssstyledeclaration-csstext
    fn SetCssText(&self, value: DOMString, can_gc: CanGc) -> ErrorResult {
        let window = self.owner.window();

        // Step 1
        if self.readonly {
            return Err(Error::NoModificationAllowed);
        }

        let quirks_mode = window.Document().quirks_mode();
        self.owner.mutate_associated_block(
            |pdb, _changed| {
                // Step 3
                *pdb = parse_style_attribute(
                    &value,
                    &UrlExtraData(self.owner.base_url().get_arc()),
                    window.css_error_reporter(),
                    quirks_mode,
                    CssRuleType::Style,
                );
            },
            can_gc,
        );

        Ok(())
    }

    // https://drafts.csswg.org/cssom/#dom-cssstyledeclaration-_camel_cased_attribute
    style::css_properties_accessors!(css_properties);
}
