/* 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::collections::HashMap;
use std::rc::Rc;
use std::str;

use base::id::PipelineId;
use devtools_traits::{
    AttrModification, AutoMargins, ComputedNodeLayout, CssDatabaseProperty, EvaluateJSReply,
    NodeInfo, NodeStyle, RuleModification, TimelineMarker, TimelineMarkerType,
};
use html5ever::LocalName;
use ipc_channel::ipc::IpcSender;
use js::conversions::jsstr_to_string;
use js::jsval::UndefinedValue;
use js::rust::ToString;
use servo_config::pref;
use style::attr::AttrValue;
use uuid::Uuid;

use crate::document_collection::DocumentCollection;
use crate::dom::bindings::codegen::Bindings::CSSRuleListBinding::CSSRuleListMethods;
use crate::dom::bindings::codegen::Bindings::CSSStyleDeclarationBinding::CSSStyleDeclarationMethods;
use crate::dom::bindings::codegen::Bindings::CSSStyleRuleBinding::CSSStyleRuleMethods;
use crate::dom::bindings::codegen::Bindings::CSSStyleSheetBinding::CSSStyleSheetMethods;
use crate::dom::bindings::codegen::Bindings::DOMRectBinding::DOMRectMethods;
use crate::dom::bindings::codegen::Bindings::DocumentBinding::DocumentMethods;
use crate::dom::bindings::codegen::Bindings::ElementBinding::ElementMethods;
use crate::dom::bindings::codegen::Bindings::HTMLElementBinding::HTMLElementMethods;
use crate::dom::bindings::codegen::Bindings::NodeBinding::NodeConstants;
use crate::dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
use crate::dom::bindings::conversions::{ConversionResult, FromJSValConvertible};
use crate::dom::bindings::inheritance::Castable;
use crate::dom::bindings::root::DomRoot;
use crate::dom::bindings::str::DOMString;
use crate::dom::cssstyledeclaration::ENABLED_LONGHAND_PROPERTIES;
use crate::dom::cssstylerule::CSSStyleRule;
use crate::dom::document::AnimationFrameCallback;
use crate::dom::element::Element;
use crate::dom::globalscope::GlobalScope;
use crate::dom::html::htmlscriptelement::SourceCode;
use crate::dom::node::{Node, NodeTraits, ShadowIncluding};
use crate::dom::types::HTMLElement;
use crate::realms::enter_realm;
use crate::script_module::ScriptFetchOptions;
use crate::script_runtime::{CanGc, IntroductionType};

#[allow(unsafe_code)]
pub(crate) fn handle_evaluate_js(
    global: &GlobalScope,
    eval: String,
    reply: IpcSender<EvaluateJSReply>,
    can_gc: CanGc,
) {
    // global.get_cx() returns a valid `JSContext` pointer, so this is safe.
    let result = unsafe {
        let cx = GlobalScope::get_cx();
        let _ac = enter_realm(global);
        rooted!(in(*cx) let mut rval = UndefinedValue());
        let source_code = SourceCode::Text(Rc::new(DOMString::from_string(eval)));
        // TODO: run code with SpiderMonkey Debugger API, like Firefox does
        // <https://searchfox.org/mozilla-central/rev/f6a806c38c459e0e0d797d264ca0e8ad46005105/devtools/server/actors/webconsole/eval-with-debugger.js#270>
        _ = global.evaluate_script_on_global_with_result(
            &source_code,
            "<eval>",
            rval.handle_mut(),
            1,
            ScriptFetchOptions::default_classic_script(global),
            global.api_base_url(),
            can_gc,
            Some(IntroductionType::DEBUGGER_EVAL),
        );

        if rval.is_undefined() {
            EvaluateJSReply::VoidValue
        } else if rval.is_boolean() {
            EvaluateJSReply::BooleanValue(rval.to_boolean())
        } else if rval.is_double() || rval.is_int32() {
            EvaluateJSReply::NumberValue(
                match FromJSValConvertible::from_jsval(*cx, rval.handle(), ()) {
                    Ok(ConversionResult::Success(v)) => v,
                    _ => unreachable!(),
                },
            )
        } else if rval.is_string() {
            let jsstr = std::ptr::NonNull::new(rval.to_string()).unwrap();
            EvaluateJSReply::StringValue(jsstr_to_string(*cx, jsstr))
        } else if rval.is_null() {
            EvaluateJSReply::NullValue
        } else {
            assert!(rval.is_object());

            let jsstr = std::ptr::NonNull::new(ToString(*cx, rval.handle())).unwrap();
            let class_name = jsstr_to_string(*cx, jsstr);

            EvaluateJSReply::ActorValue {
                class: class_name,
                uuid: Uuid::new_v4().to_string(),
            }
        }
    };
    reply.send(result).unwrap();
}

pub(crate) fn handle_get_root_node(
    documents: &DocumentCollection,
    pipeline: PipelineId,
    reply: IpcSender<Option<NodeInfo>>,
    can_gc: CanGc,
) {
    let info = documents
        .find_document(pipeline)
        .map(|document| document.upcast::<Node>().summarize(can_gc));
    reply.send(info).unwrap();
}

pub(crate) fn handle_get_document_element(
    documents: &DocumentCollection,
    pipeline: PipelineId,
    reply: IpcSender<Option<NodeInfo>>,
    can_gc: CanGc,
) {
    let info = documents
        .find_document(pipeline)
        .and_then(|document| document.GetDocumentElement())
        .map(|element| element.upcast::<Node>().summarize(can_gc));
    reply.send(info).unwrap();
}

fn find_node_by_unique_id(
    documents: &DocumentCollection,
    pipeline: PipelineId,
    node_id: &str,
) -> Option<DomRoot<Node>> {
    documents.find_document(pipeline).and_then(|document| {
        document
            .upcast::<Node>()
            .traverse_preorder(ShadowIncluding::Yes)
            .find(|candidate| candidate.unique_id(pipeline) == node_id)
    })
}

pub(crate) fn handle_get_children(
    documents: &DocumentCollection,
    pipeline: PipelineId,
    node_id: String,
    reply: IpcSender<Option<Vec<NodeInfo>>>,
    can_gc: CanGc,
) {
    match find_node_by_unique_id(documents, pipeline, &node_id) {
        None => reply.send(None).unwrap(),
        Some(parent) => {
            let is_whitespace = |node: &NodeInfo| {
                node.node_type == NodeConstants::TEXT_NODE &&
                    node.node_value.as_ref().is_none_or(|v| v.trim().is_empty())
            };

            let inline: Vec<_> = parent
                .children()
                .map(|child| {
                    let window = child.owner_window();
                    let Some(elem) = child.downcast::<Element>() else {
                        return false;
                    };
                    let computed_style = window.GetComputedStyle(elem, None);
                    let display = computed_style.Display();
                    display == "inline"
                })
                .collect();

            let mut children = vec![];
            if let Some(shadow_root) = parent.downcast::<Element>().and_then(Element::shadow_root) {
                if !shadow_root.is_user_agent_widget() ||
                    pref!(inspector_show_servo_internal_shadow_roots)
                {
                    children.push(shadow_root.upcast::<Node>().summarize(can_gc));
                }
            }
            let children_iter = parent.children().enumerate().filter_map(|(i, child)| {
                // Filter whitespace only text nodes that are not inline level
                // https://firefox-source-docs.mozilla.org/devtools-user/page_inspector/how_to/examine_and_edit_html/index.html#whitespace-only-text-nodes
                let prev_inline = i > 0 && inline[i - 1];
                let next_inline = i < inline.len() - 1 && inline[i + 1];

                let info = child.summarize(can_gc);
                if !is_whitespace(&info) {
                    return Some(info);
                }

                (prev_inline && next_inline).then_some(info)
            });
            children.extend(children_iter);

            reply.send(Some(children)).unwrap();
        },
    };
}

pub(crate) fn handle_get_attribute_style(
    documents: &DocumentCollection,
    pipeline: PipelineId,
    node_id: String,
    reply: IpcSender<Option<Vec<NodeStyle>>>,
    can_gc: CanGc,
) {
    let node = match find_node_by_unique_id(documents, pipeline, &node_id) {
        None => return reply.send(None).unwrap(),
        Some(found_node) => found_node,
    };

    let Some(elem) = node.downcast::<HTMLElement>() else {
        // the style attribute only works on html elements
        reply.send(None).unwrap();
        return;
    };
    let style = elem.Style(can_gc);

    let msg = (0..style.Length())
        .map(|i| {
            let name = style.Item(i);
            NodeStyle {
                name: name.to_string(),
                value: style.GetPropertyValue(name.clone()).to_string(),
                priority: style.GetPropertyPriority(name).to_string(),
            }
        })
        .collect();

    reply.send(Some(msg)).unwrap();
}

#[cfg_attr(crown, allow(crown::unrooted_must_root))]
pub(crate) fn handle_get_stylesheet_style(
    documents: &DocumentCollection,
    pipeline: PipelineId,
    node_id: String,
    selector: String,
    stylesheet: usize,
    reply: IpcSender<Option<Vec<NodeStyle>>>,
    can_gc: CanGc,
) {
    let msg = (|| {
        let node = find_node_by_unique_id(documents, pipeline, &node_id)?;

        let document = documents.find_document(pipeline)?;
        let _realm = enter_realm(document.window());
        let owner = node.stylesheet_list_owner();

        let stylesheet = owner.stylesheet_at(stylesheet)?;
        let list = stylesheet.GetCssRules(can_gc).ok()?;

        let styles = (0..list.Length())
            .filter_map(move |i| {
                let rule = list.Item(i, can_gc)?;
                let style = rule.downcast::<CSSStyleRule>()?;
                if *selector != *style.SelectorText() {
                    return None;
                };
                Some(style.Style(can_gc))
            })
            .flat_map(|style| {
                (0..style.Length()).map(move |i| {
                    let name = style.Item(i);
                    NodeStyle {
                        name: name.to_string(),
                        value: style.GetPropertyValue(name.clone()).to_string(),
                        priority: style.GetPropertyPriority(name).to_string(),
                    }
                })
            })
            .collect();

        Some(styles)
    })();

    reply.send(msg).unwrap();
}

#[cfg_attr(crown, allow(crown::unrooted_must_root))]
pub(crate) fn handle_get_selectors(
    documents: &DocumentCollection,
    pipeline: PipelineId,
    node_id: String,
    reply: IpcSender<Option<Vec<(String, usize)>>>,
    can_gc: CanGc,
) {
    let msg = (|| {
        let node = find_node_by_unique_id(documents, pipeline, &node_id)?;

        let document = documents.find_document(pipeline)?;
        let _realm = enter_realm(document.window());
        let owner = node.stylesheet_list_owner();

        let rules = (0..owner.stylesheet_count())
            .filter_map(|i| {
                let stylesheet = owner.stylesheet_at(i)?;
                let list = stylesheet.GetCssRules(can_gc).ok()?;
                let elem = node.downcast::<Element>()?;

                Some((0..list.Length()).filter_map(move |j| {
                    let rule = list.Item(j, can_gc)?;
                    let style = rule.downcast::<CSSStyleRule>()?;
                    let selector = style.SelectorText();
                    elem.Matches(selector.clone()).ok()?.then_some(())?;
                    Some((selector.into(), i))
                }))
            })
            .flatten()
            .collect();

        Some(rules)
    })();

    reply.send(msg).unwrap();
}

pub(crate) fn handle_get_computed_style(
    documents: &DocumentCollection,
    pipeline: PipelineId,
    node_id: String,
    reply: IpcSender<Option<Vec<NodeStyle>>>,
) {
    let node = match find_node_by_unique_id(documents, pipeline, &node_id) {
        None => return reply.send(None).unwrap(),
        Some(found_node) => found_node,
    };

    let window = node.owner_window();
    let elem = node
        .downcast::<Element>()
        .expect("This should be an element");
    let computed_style = window.GetComputedStyle(elem, None);

    let msg = (0..computed_style.Length())
        .map(|i| {
            let name = computed_style.Item(i);
            NodeStyle {
                name: name.to_string(),
                value: computed_style.GetPropertyValue(name.clone()).to_string(),
                priority: computed_style.GetPropertyPriority(name).to_string(),
            }
        })
        .collect();

    reply.send(Some(msg)).unwrap();
}

pub(crate) fn handle_get_layout(
    documents: &DocumentCollection,
    pipeline: PipelineId,
    node_id: String,
    reply: IpcSender<Option<ComputedNodeLayout>>,
    can_gc: CanGc,
) {
    let node = match find_node_by_unique_id(documents, pipeline, &node_id) {
        None => return reply.send(None).unwrap(),
        Some(found_node) => found_node,
    };

    let elem = node
        .downcast::<Element>()
        .expect("should be getting layout of element");
    let rect = elem.GetBoundingClientRect(can_gc);
    let width = rect.Width() as f32;
    let height = rect.Height() as f32;

    let window = node.owner_window();
    let elem = node
        .downcast::<Element>()
        .expect("should be getting layout of element");
    let computed_style = window.GetComputedStyle(elem, None);

    reply
        .send(Some(ComputedNodeLayout {
            display: String::from(computed_style.Display()),
            position: String::from(computed_style.Position()),
            z_index: String::from(computed_style.ZIndex()),
            box_sizing: String::from(computed_style.BoxSizing()),
            auto_margins: determine_auto_margins(&node),
            margin_top: String::from(computed_style.MarginTop()),
            margin_right: String::from(computed_style.MarginRight()),
            margin_bottom: String::from(computed_style.MarginBottom()),
            margin_left: String::from(computed_style.MarginLeft()),
            border_top_width: String::from(computed_style.BorderTopWidth()),
            border_right_width: String::from(computed_style.BorderRightWidth()),
            border_bottom_width: String::from(computed_style.BorderBottomWidth()),
            border_left_width: String::from(computed_style.BorderLeftWidth()),
            padding_top: String::from(computed_style.PaddingTop()),
            padding_right: String::from(computed_style.PaddingRight()),
            padding_bottom: String::from(computed_style.PaddingBottom()),
            padding_left: String::from(computed_style.PaddingLeft()),
            width,
            height,
        }))
        .unwrap();
}

fn determine_auto_margins(node: &Node) -> AutoMargins {
    let style = node.style().unwrap();
    let margin = style.get_margin();
    AutoMargins {
        top: margin.margin_top.is_auto(),
        right: margin.margin_right.is_auto(),
        bottom: margin.margin_bottom.is_auto(),
        left: margin.margin_left.is_auto(),
    }
}

pub(crate) fn handle_modify_attribute(
    documents: &DocumentCollection,
    pipeline: PipelineId,
    node_id: String,
    modifications: Vec<AttrModification>,
    can_gc: CanGc,
) {
    let Some(document) = documents.find_document(pipeline) else {
        return warn!("document for pipeline id {} is not found", &pipeline);
    };
    let _realm = enter_realm(document.window());

    let node = match find_node_by_unique_id(documents, pipeline, &node_id) {
        None => {
            return warn!(
                "node id {} for pipeline id {} is not found",
                &node_id, &pipeline
            );
        },
        Some(found_node) => found_node,
    };

    let elem = node
        .downcast::<Element>()
        .expect("should be getting layout of element");

    for modification in modifications {
        match modification.new_value {
            Some(string) => {
                elem.set_attribute(
                    &LocalName::from(modification.attribute_name),
                    AttrValue::String(string),
                    can_gc,
                );
            },
            None => elem.RemoveAttribute(DOMString::from(modification.attribute_name), can_gc),
        }
    }
}

pub(crate) fn handle_modify_rule(
    documents: &DocumentCollection,
    pipeline: PipelineId,
    node_id: String,
    modifications: Vec<RuleModification>,
    can_gc: CanGc,
) {
    let Some(document) = documents.find_document(pipeline) else {
        return warn!("Document for pipeline id {} is not found", &pipeline);
    };
    let _realm = enter_realm(document.window());

    let Some(node) = find_node_by_unique_id(documents, pipeline, &node_id) else {
        return warn!(
            "Node id {} for pipeline id {} is not found",
            &node_id, &pipeline
        );
    };

    let elem = node
        .downcast::<HTMLElement>()
        .expect("This should be an HTMLElement");
    let style = elem.Style(can_gc);

    for modification in modifications {
        let _ = style.SetProperty(
            modification.name.into(),
            modification.value.into(),
            modification.priority.into(),
            can_gc,
        );
    }
}

pub(crate) fn handle_wants_live_notifications(global: &GlobalScope, send_notifications: bool) {
    global.set_devtools_wants_updates(send_notifications);
}

pub(crate) fn handle_set_timeline_markers(
    documents: &DocumentCollection,
    pipeline: PipelineId,
    marker_types: Vec<TimelineMarkerType>,
    reply: IpcSender<Option<TimelineMarker>>,
) {
    match documents.find_window(pipeline) {
        None => reply.send(None).unwrap(),
        Some(window) => window.set_devtools_timeline_markers(marker_types, reply),
    }
}

pub(crate) fn handle_drop_timeline_markers(
    documents: &DocumentCollection,
    pipeline: PipelineId,
    marker_types: Vec<TimelineMarkerType>,
) {
    if let Some(window) = documents.find_window(pipeline) {
        window.drop_devtools_timeline_markers(marker_types);
    }
}

pub(crate) fn handle_request_animation_frame(
    documents: &DocumentCollection,
    id: PipelineId,
    actor_name: String,
) {
    if let Some(doc) = documents.find_document(id) {
        doc.request_animation_frame(AnimationFrameCallback::DevtoolsFramerateTick { actor_name });
    }
}

pub(crate) fn handle_reload(documents: &DocumentCollection, id: PipelineId, can_gc: CanGc) {
    if let Some(win) = documents.find_window(id) {
        win.Location().reload_without_origin_check(can_gc);
    }
}

pub(crate) fn handle_get_css_database(reply: IpcSender<HashMap<String, CssDatabaseProperty>>) {
    let database: HashMap<_, _> = ENABLED_LONGHAND_PROPERTIES
        .iter()
        .map(|l| {
            (
                l.name().into(),
                CssDatabaseProperty {
                    is_inherited: l.inherited(),
                    values: vec![], // TODO: Get allowed values for each property
                    supports: vec![],
                    subproperties: vec![l.name().into()],
                },
            )
        })
        .collect();
    let _ = reply.send(database);
}

pub(crate) fn handle_highlight_dom_node(
    documents: &DocumentCollection,
    id: PipelineId,
    node_id: Option<String>,
) {
    let node = node_id.and_then(|node_id| {
        let node = find_node_by_unique_id(documents, id, &node_id);
        if node.is_none() {
            log::warn!("Node id {node_id} for pipeline id {id} is not found",);
        }
        node
    });

    if let Some(window) = documents.find_window(id) {
        window.Document().highlight_dom_node(node.as_deref());
    }
}
