/* 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;

use dom_struct::dom_struct;
use html5ever::{LocalName, Prefix, local_name, ns};
use js::rust::HandleObject;
use style::attr::{AttrValue, LengthOrPercentageOrAuto, parse_unsigned_integer};
use style::color::AbsoluteColor;

use crate::dom::attr::Attr;
use crate::dom::bindings::codegen::Bindings::HTMLCollectionBinding::HTMLCollectionMethods;
use crate::dom::bindings::codegen::Bindings::HTMLTableElementBinding::HTMLTableElementMethods;
use crate::dom::bindings::codegen::Bindings::NodeBinding::NodeMethods;
use crate::dom::bindings::error::{Error, ErrorResult, Fallible};
use crate::dom::bindings::inheritance::Castable;
use crate::dom::bindings::root::{Dom, DomRoot, LayoutDom, MutNullableDom};
use crate::dom::bindings::str::DOMString;
use crate::dom::document::Document;
use crate::dom::element::{AttributeMutation, Element, LayoutElementHelpers};
use crate::dom::html::htmlcollection::{CollectionFilter, HTMLCollection};
use crate::dom::html::htmlelement::HTMLElement;
use crate::dom::html::htmltablecaptionelement::HTMLTableCaptionElement;
use crate::dom::html::htmltablecolelement::HTMLTableColElement;
use crate::dom::html::htmltablerowelement::HTMLTableRowElement;
use crate::dom::html::htmltablesectionelement::HTMLTableSectionElement;
use crate::dom::node::{Node, NodeTraits};
use crate::dom::virtualmethods::VirtualMethods;
use crate::script_runtime::CanGc;

#[dom_struct]
pub(crate) struct HTMLTableElement {
    htmlelement: HTMLElement,
    border: Cell<Option<u32>>,
    cellpadding: Cell<Option<u32>>,
    cellspacing: Cell<Option<u32>>,
    tbodies: MutNullableDom<HTMLCollection>,
}

#[cfg_attr(crown, allow(crown::unrooted_must_root))]
#[derive(JSTraceable, MallocSizeOf)]
struct TableRowFilter {
    sections: Vec<Dom<Node>>,
}

impl CollectionFilter for TableRowFilter {
    fn filter(&self, elem: &Element, root: &Node) -> bool {
        elem.is::<HTMLTableRowElement>() &&
            (root.is_parent_of(elem.upcast()) ||
                self.sections
                    .iter()
                    .any(|section| section.is_parent_of(elem.upcast())))
    }
}

impl HTMLTableElement {
    fn new_inherited(
        local_name: LocalName,
        prefix: Option<Prefix>,
        document: &Document,
    ) -> HTMLTableElement {
        HTMLTableElement {
            htmlelement: HTMLElement::new_inherited(local_name, prefix, document),
            border: Cell::new(None),
            cellpadding: Cell::new(None),
            cellspacing: Cell::new(None),
            tbodies: Default::default(),
        }
    }

    #[cfg_attr(crown, allow(crown::unrooted_must_root))]
    pub(crate) fn new(
        local_name: LocalName,
        prefix: Option<Prefix>,
        document: &Document,
        proto: Option<HandleObject>,
        can_gc: CanGc,
    ) -> DomRoot<HTMLTableElement> {
        let n = Node::reflect_node_with_proto(
            Box::new(HTMLTableElement::new_inherited(
                local_name, prefix, document,
            )),
            document,
            proto,
            can_gc,
        );

        n.upcast::<Node>().set_weird_parser_insertion_mode();
        n
    }

    pub(crate) fn get_border(&self) -> Option<u32> {
        self.border.get()
    }

    // https://html.spec.whatwg.org/multipage/#dom-table-thead
    // https://html.spec.whatwg.org/multipage/#dom-table-tfoot
    fn get_first_section_of_type(
        &self,
        atom: &LocalName,
    ) -> Option<DomRoot<HTMLTableSectionElement>> {
        self.upcast::<Node>()
            .child_elements()
            .find(|n| n.is::<HTMLTableSectionElement>() && n.local_name() == atom)
            .and_then(|n| n.downcast().map(DomRoot::from_ref))
    }

    // https://html.spec.whatwg.org/multipage/#dom-table-thead
    // https://html.spec.whatwg.org/multipage/#dom-table-tfoot
    fn set_first_section_of_type<P>(
        &self,
        atom: &LocalName,
        section: Option<&HTMLTableSectionElement>,
        reference_predicate: P,
        can_gc: CanGc,
    ) -> ErrorResult
    where
        P: FnMut(&DomRoot<Element>) -> bool,
    {
        if let Some(e) = section {
            if e.upcast::<Element>().local_name() != atom {
                return Err(Error::HierarchyRequest);
            }
        }

        self.delete_first_section_of_type(atom, can_gc);

        let node = self.upcast::<Node>();

        if let Some(section) = section {
            let reference_element = node.child_elements().find(reference_predicate);
            let reference_node = reference_element.as_ref().map(|e| e.upcast());

            node.InsertBefore(section.upcast(), reference_node, can_gc)?;
        }

        Ok(())
    }

    // https://html.spec.whatwg.org/multipage/#dom-table-createthead
    // https://html.spec.whatwg.org/multipage/#dom-table-createtfoot
    fn create_section_of_type(
        &self,
        atom: &LocalName,
        can_gc: CanGc,
    ) -> DomRoot<HTMLTableSectionElement> {
        if let Some(section) = self.get_first_section_of_type(atom) {
            return section;
        }

        let section =
            HTMLTableSectionElement::new(atom.clone(), None, &self.owner_document(), None, can_gc);
        match *atom {
            local_name!("thead") => self.SetTHead(Some(&section)),
            local_name!("tfoot") => self.SetTFoot(Some(&section)),
            _ => unreachable!("unexpected section type"),
        }
        .expect("unexpected section type");

        section
    }

    // https://html.spec.whatwg.org/multipage/#dom-table-deletethead
    // https://html.spec.whatwg.org/multipage/#dom-table-deletetfoot
    fn delete_first_section_of_type(&self, atom: &LocalName, can_gc: CanGc) {
        if let Some(thead) = self.get_first_section_of_type(atom) {
            thead.upcast::<Node>().remove_self(can_gc);
        }
    }

    fn get_rows(&self) -> TableRowFilter {
        TableRowFilter {
            sections: self
                .upcast::<Node>()
                .children()
                .filter_map(|ref node| {
                    node.downcast::<HTMLTableSectionElement>()
                        .map(|_| Dom::from_ref(&**node))
                })
                .collect(),
        }
    }
}

impl HTMLTableElementMethods<crate::DomTypeHolder> for HTMLTableElement {
    // https://html.spec.whatwg.org/multipage/#dom-table-rows
    fn Rows(&self) -> DomRoot<HTMLCollection> {
        let filter = self.get_rows();
        HTMLCollection::new(
            &self.owner_window(),
            self.upcast(),
            Box::new(filter),
            CanGc::note(),
        )
    }

    // https://html.spec.whatwg.org/multipage/#dom-table-caption
    fn GetCaption(&self) -> Option<DomRoot<HTMLTableCaptionElement>> {
        self.upcast::<Node>()
            .children()
            .filter_map(DomRoot::downcast)
            .next()
    }

    // https://html.spec.whatwg.org/multipage/#dom-table-caption
    fn SetCaption(&self, new_caption: Option<&HTMLTableCaptionElement>) -> Fallible<()> {
        if let Some(ref caption) = self.GetCaption() {
            caption.upcast::<Node>().remove_self(CanGc::note());
        }

        if let Some(caption) = new_caption {
            let node = self.upcast::<Node>();
            node.InsertBefore(
                caption.upcast(),
                node.GetFirstChild().as_deref(),
                CanGc::note(),
            )?;
        }

        Ok(())
    }

    // https://html.spec.whatwg.org/multipage/#dom-table-createcaption
    fn CreateCaption(&self, can_gc: CanGc) -> DomRoot<HTMLTableCaptionElement> {
        match self.GetCaption() {
            Some(caption) => caption,
            None => {
                let caption = HTMLTableCaptionElement::new(
                    local_name!("caption"),
                    None,
                    &self.owner_document(),
                    None,
                    can_gc,
                );
                self.SetCaption(Some(&caption))
                    .expect("Generated caption is invalid");
                caption
            },
        }
    }

    // https://html.spec.whatwg.org/multipage/#dom-table-deletecaption
    fn DeleteCaption(&self) {
        if let Some(caption) = self.GetCaption() {
            caption.upcast::<Node>().remove_self(CanGc::note());
        }
    }

    // https://html.spec.whatwg.org/multipage/#dom-table-thead
    fn GetTHead(&self) -> Option<DomRoot<HTMLTableSectionElement>> {
        self.get_first_section_of_type(&local_name!("thead"))
    }

    // https://html.spec.whatwg.org/multipage/#dom-table-thead
    fn SetTHead(&self, thead: Option<&HTMLTableSectionElement>) -> ErrorResult {
        self.set_first_section_of_type(
            &local_name!("thead"),
            thead,
            |n| !n.is::<HTMLTableCaptionElement>() && !n.is::<HTMLTableColElement>(),
            CanGc::note(),
        )
    }

    // https://html.spec.whatwg.org/multipage/#dom-table-createthead
    fn CreateTHead(&self, can_gc: CanGc) -> DomRoot<HTMLTableSectionElement> {
        self.create_section_of_type(&local_name!("thead"), can_gc)
    }

    // https://html.spec.whatwg.org/multipage/#dom-table-deletethead
    fn DeleteTHead(&self) {
        self.delete_first_section_of_type(&local_name!("thead"), CanGc::note())
    }

    // https://html.spec.whatwg.org/multipage/#dom-table-tfoot
    fn GetTFoot(&self) -> Option<DomRoot<HTMLTableSectionElement>> {
        self.get_first_section_of_type(&local_name!("tfoot"))
    }

    // https://html.spec.whatwg.org/multipage/#dom-table-tfoot
    fn SetTFoot(&self, tfoot: Option<&HTMLTableSectionElement>) -> ErrorResult {
        self.set_first_section_of_type(
            &local_name!("tfoot"),
            tfoot,
            |n| {
                if n.is::<HTMLTableCaptionElement>() || n.is::<HTMLTableColElement>() {
                    return false;
                }

                if n.is::<HTMLTableSectionElement>() {
                    let name = n.local_name();
                    if name == &local_name!("thead") || name == &local_name!("tbody") {
                        return false;
                    }
                }

                true
            },
            CanGc::note(),
        )
    }

    // https://html.spec.whatwg.org/multipage/#dom-table-createtfoot
    fn CreateTFoot(&self, can_gc: CanGc) -> DomRoot<HTMLTableSectionElement> {
        self.create_section_of_type(&local_name!("tfoot"), can_gc)
    }

    // https://html.spec.whatwg.org/multipage/#dom-table-deletetfoot
    fn DeleteTFoot(&self) {
        self.delete_first_section_of_type(&local_name!("tfoot"), CanGc::note())
    }

    // https://html.spec.whatwg.org/multipage/#dom-table-tbodies
    fn TBodies(&self) -> DomRoot<HTMLCollection> {
        self.tbodies.or_init(|| {
            HTMLCollection::new_with_filter_fn(
                &self.owner_window(),
                self.upcast(),
                |element, root| {
                    element.is::<HTMLTableSectionElement>() &&
                        element.local_name() == &local_name!("tbody") &&
                        element.upcast::<Node>().GetParentNode().as_deref() == Some(root)
                },
                CanGc::note(),
            )
        })
    }

    // https://html.spec.whatwg.org/multipage/#dom-table-createtbody
    fn CreateTBody(&self, can_gc: CanGc) -> DomRoot<HTMLTableSectionElement> {
        let tbody = HTMLTableSectionElement::new(
            local_name!("tbody"),
            None,
            &self.owner_document(),
            None,
            can_gc,
        );
        let node = self.upcast::<Node>();
        let last_tbody = node
            .rev_children()
            .filter_map(DomRoot::downcast::<Element>)
            .find(|n| n.is::<HTMLTableSectionElement>() && n.local_name() == &local_name!("tbody"));
        let reference_element = last_tbody.and_then(|t| t.upcast::<Node>().GetNextSibling());

        node.InsertBefore(tbody.upcast(), reference_element.as_deref(), can_gc)
            .expect("Insertion failed");
        tbody
    }

    // https://html.spec.whatwg.org/multipage/#dom-table-insertrow
    fn InsertRow(&self, index: i32, can_gc: CanGc) -> Fallible<DomRoot<HTMLTableRowElement>> {
        let rows = self.Rows();
        let number_of_row_elements = rows.Length();

        if index < -1 || index > number_of_row_elements as i32 {
            return Err(Error::IndexSize);
        }

        let new_row = HTMLTableRowElement::new(
            local_name!("tr"),
            None,
            &self.owner_document(),
            None,
            can_gc,
        );
        let node = self.upcast::<Node>();

        if number_of_row_elements == 0 {
            // append new row to last or new tbody in table
            if let Some(last_tbody) = node
                .rev_children()
                .filter_map(DomRoot::downcast::<Element>)
                .find(|n| {
                    n.is::<HTMLTableSectionElement>() && n.local_name() == &local_name!("tbody")
                })
            {
                last_tbody
                    .upcast::<Node>()
                    .AppendChild(new_row.upcast::<Node>(), can_gc)
                    .expect("InsertRow failed to append first row.");
            } else {
                let tbody = self.CreateTBody(can_gc);
                node.AppendChild(tbody.upcast(), can_gc)
                    .expect("InsertRow failed to append new tbody.");

                tbody
                    .upcast::<Node>()
                    .AppendChild(new_row.upcast::<Node>(), can_gc)
                    .expect("InsertRow failed to append first row.");
            }
        } else if index == number_of_row_elements as i32 || index == -1 {
            // append new row to parent of last row in table
            let last_row = rows
                .Item(number_of_row_elements - 1)
                .expect("InsertRow failed to find last row in table.");

            let last_row_parent = last_row
                .upcast::<Node>()
                .GetParentNode()
                .expect("InsertRow failed to find parent of last row in table.");

            last_row_parent
                .upcast::<Node>()
                .AppendChild(new_row.upcast::<Node>(), can_gc)
                .expect("InsertRow failed to append last row.");
        } else {
            // insert new row before the index-th row in rows using the same parent
            let ith_row = rows
                .Item(index as u32)
                .expect("InsertRow failed to find a row in table.");

            let ith_row_parent = ith_row
                .upcast::<Node>()
                .GetParentNode()
                .expect("InsertRow failed to find parent of a row in table.");

            ith_row_parent
                .upcast::<Node>()
                .InsertBefore(
                    new_row.upcast::<Node>(),
                    Some(ith_row.upcast::<Node>()),
                    can_gc,
                )
                .expect("InsertRow failed to append row");
        }

        Ok(new_row)
    }

    /// <https://html.spec.whatwg.org/multipage/#dom-table-deleterow>
    fn DeleteRow(&self, mut index: i32) -> Fallible<()> {
        let rows = self.Rows();
        let num_rows = rows.Length() as i32;

        // Step 1: If index is less than −1 or greater than or equal to the number of elements
        // in the rows collection, then throw an "IndexSizeError".
        if !(-1..num_rows).contains(&index) {
            return Err(Error::IndexSize);
        }

        let num_rows = rows.Length() as i32;

        // Step 2: If index is −1, then remove the last element in the rows collection from its
        // parent, or do nothing if the rows collection is empty.
        if index == -1 {
            index = num_rows - 1;
        }

        if num_rows == 0 {
            return Ok(());
        }

        // Step 3: Otherwise, remove the indexth element in the rows collection from its parent.
        DomRoot::upcast::<Node>(rows.Item(index as u32).unwrap()).remove_self(CanGc::note());

        Ok(())
    }

    // https://html.spec.whatwg.org/multipage/#dom-table-bgcolor
    make_getter!(BgColor, "bgcolor");

    // https://html.spec.whatwg.org/multipage/#dom-table-bgcolor
    make_legacy_color_setter!(SetBgColor, "bgcolor");

    // https://html.spec.whatwg.org/multipage/#dom-table-width
    make_getter!(Width, "width");

    // https://html.spec.whatwg.org/multipage/#dom-table-width
    make_nonzero_dimension_setter!(SetWidth, "width");
}

pub(crate) trait HTMLTableElementLayoutHelpers {
    fn get_background_color(self) -> Option<AbsoluteColor>;
    fn get_border(self) -> Option<u32>;
    fn get_cellpadding(self) -> Option<u32>;
    fn get_cellspacing(self) -> Option<u32>;
    fn get_width(self) -> LengthOrPercentageOrAuto;
    fn get_height(self) -> LengthOrPercentageOrAuto;
}

impl HTMLTableElementLayoutHelpers for LayoutDom<'_, HTMLTableElement> {
    fn get_background_color(self) -> Option<AbsoluteColor> {
        self.upcast::<Element>()
            .get_attr_for_layout(&ns!(), &local_name!("bgcolor"))
            .and_then(AttrValue::as_color)
            .cloned()
    }

    fn get_border(self) -> Option<u32> {
        (self.unsafe_get()).border.get()
    }

    fn get_cellpadding(self) -> Option<u32> {
        (self.unsafe_get()).cellpadding.get()
    }

    fn get_cellspacing(self) -> Option<u32> {
        (self.unsafe_get()).cellspacing.get()
    }

    fn get_width(self) -> LengthOrPercentageOrAuto {
        self.upcast::<Element>()
            .get_attr_for_layout(&ns!(), &local_name!("width"))
            .map(AttrValue::as_dimension)
            .cloned()
            .unwrap_or(LengthOrPercentageOrAuto::Auto)
    }

    fn get_height(self) -> LengthOrPercentageOrAuto {
        self.upcast::<Element>()
            .get_attr_for_layout(&ns!(), &local_name!("height"))
            .map(AttrValue::as_dimension)
            .cloned()
            .unwrap_or(LengthOrPercentageOrAuto::Auto)
    }
}

impl VirtualMethods for HTMLTableElement {
    fn super_type(&self) -> Option<&dyn VirtualMethods> {
        Some(self.upcast::<HTMLElement>() as &dyn VirtualMethods)
    }

    fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation, can_gc: CanGc) {
        self.super_type()
            .unwrap()
            .attribute_mutated(attr, mutation, can_gc);
        match *attr.local_name() {
            local_name!("border") => {
                // According to HTML5 § 14.3.9, invalid values map to 1px.
                self.border.set(
                    mutation
                        .new_value(attr)
                        .map(|value| parse_unsigned_integer(value.chars()).unwrap_or(1)),
                );
            },
            local_name!("cellpadding") => {
                self.cellpadding.set(
                    mutation
                        .new_value(attr)
                        .and_then(|value| parse_unsigned_integer(value.chars()).ok()),
                );
            },
            local_name!("cellspacing") => {
                self.cellspacing.set(
                    mutation
                        .new_value(attr)
                        .and_then(|value| parse_unsigned_integer(value.chars()).ok()),
                );
            },
            _ => {},
        }
    }

    fn parse_plain_attribute(&self, local_name: &LocalName, value: DOMString) -> AttrValue {
        match *local_name {
            local_name!("border") => AttrValue::from_u32(value.into(), 1),
            local_name!("width") => AttrValue::from_nonzero_dimension(value.into()),
            local_name!("height") => AttrValue::from_dimension(value.into()),
            local_name!("bgcolor") => AttrValue::from_legacy_color(value.into()),
            _ => self
                .super_type()
                .unwrap()
                .parse_plain_attribute(local_name, value),
        }
    }
}
