/* 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::borrow::ToOwned;
use std::collections::HashSet;
use std::{fmt, string};

use crate::dom::bindings::codegen::Bindings::NodeBinding::Node_Binding::NodeMethods;
use crate::dom::bindings::root::DomRoot;
use crate::dom::node::Node;

/// The primary types of values that an XPath expression returns as a result.
pub(crate) enum Value {
    Boolean(bool),
    /// A IEEE-754 double-precision floating point number
    Number(f64),
    String(String),
    /// A collection of not-necessarily-unique nodes
    Nodeset(Vec<DomRoot<Node>>),
}

impl fmt::Debug for Value {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match *self {
            Value::Boolean(val) => write!(f, "{}", val),
            Value::Number(val) => write!(f, "{}", val),
            Value::String(ref val) => write!(f, "{}", val),
            Value::Nodeset(ref val) => write!(f, "Nodeset({:?})", val),
        }
    }
}

pub(crate) fn str_to_num(s: &str) -> f64 {
    s.trim().parse().unwrap_or(f64::NAN)
}

/// Helper for `PartialEq<Value>` implementations
fn str_vals(nodes: &[DomRoot<Node>]) -> HashSet<String> {
    nodes
        .iter()
        .map(|n| n.GetTextContent().unwrap_or_default().to_string())
        .collect()
}

/// Helper for `PartialEq<Value>` implementations
fn num_vals(nodes: &[DomRoot<Node>]) -> Vec<f64> {
    nodes
        .iter()
        .map(|n| Value::String(n.GetTextContent().unwrap_or_default().into()).number())
        .collect()
}

impl PartialEq<Value> for Value {
    fn eq(&self, other: &Value) -> bool {
        match (self, other) {
            (Value::Nodeset(left_nodes), Value::Nodeset(right_nodes)) => {
                let left_strings = str_vals(left_nodes);
                let right_strings = str_vals(right_nodes);
                !left_strings.is_disjoint(&right_strings)
            },
            (&Value::Nodeset(ref nodes), &Value::Number(val)) |
            (&Value::Number(val), &Value::Nodeset(ref nodes)) => {
                let numbers = num_vals(nodes);
                numbers.contains(&val)
            },
            (&Value::Nodeset(ref nodes), &Value::String(ref val)) |
            (&Value::String(ref val), &Value::Nodeset(ref nodes)) => {
                let strings = str_vals(nodes);
                strings.contains(val)
            },
            (&Value::Boolean(_), _) | (_, &Value::Boolean(_)) => self.boolean() == other.boolean(),
            (&Value::Number(_), _) | (_, &Value::Number(_)) => self.number() == other.number(),
            _ => self.string() == other.string(),
        }
    }
}

impl Value {
    pub(crate) fn boolean(&self) -> bool {
        match *self {
            Value::Boolean(val) => val,
            Value::Number(n) => n != 0.0 && !n.is_nan(),
            Value::String(ref s) => !s.is_empty(),
            Value::Nodeset(ref nodeset) => !nodeset.is_empty(),
        }
    }

    pub(crate) fn into_boolean(self) -> bool {
        self.boolean()
    }

    pub(crate) fn number(&self) -> f64 {
        match *self {
            Value::Boolean(val) => {
                if val {
                    1.0
                } else {
                    0.0
                }
            },
            Value::Number(val) => val,
            Value::String(ref s) => str_to_num(s),
            Value::Nodeset(..) => str_to_num(&self.string()),
        }
    }

    pub(crate) fn into_number(self) -> f64 {
        self.number()
    }

    pub(crate) fn string(&self) -> string::String {
        match *self {
            Value::Boolean(v) => v.to_string(),
            Value::Number(n) => {
                if n.is_infinite() {
                    if n.signum() < 0.0 {
                        "-Infinity".to_owned()
                    } else {
                        "Infinity".to_owned()
                    }
                } else if n == 0.0 {
                    // catches -0.0 also
                    0.0.to_string()
                } else {
                    n.to_string()
                }
            },
            Value::String(ref val) => val.clone(),
            Value::Nodeset(ref nodes) => match nodes.document_order_first() {
                Some(n) => n.GetTextContent().unwrap_or_default().to_string(),
                None => "".to_owned(),
            },
        }
    }

    pub(crate) fn into_string(self) -> string::String {
        match self {
            Value::String(val) => val,
            other => other.string(),
        }
    }
}

macro_rules! from_impl {
    ($raw:ty, $variant:expr) => {
        impl From<$raw> for Value {
            fn from(other: $raw) -> Value {
                $variant(other)
            }
        }
    };
}

from_impl!(bool, Value::Boolean);
from_impl!(f64, Value::Number);
from_impl!(String, Value::String);
impl<'a> From<&'a str> for Value {
    fn from(other: &'a str) -> Value {
        Value::String(other.into())
    }
}
from_impl!(Vec<DomRoot<Node>>, Value::Nodeset);

macro_rules! partial_eq_impl {
    ($raw:ty, $variant:pat => $b:expr) => {
        impl PartialEq<$raw> for Value {
            fn eq(&self, other: &$raw) -> bool {
                match *self {
                    $variant => $b == other,
                    _ => false,
                }
            }
        }

        impl PartialEq<Value> for $raw {
            fn eq(&self, other: &Value) -> bool {
                match *other {
                    $variant => $b == self,
                    _ => false,
                }
            }
        }
    };
}

partial_eq_impl!(bool, Value::Boolean(ref v) => v);
partial_eq_impl!(f64, Value::Number(ref v) => v);
partial_eq_impl!(String, Value::String(ref v) => v);
partial_eq_impl!(&str, Value::String(ref v) => v);
partial_eq_impl!(Vec<DomRoot<Node>>, Value::Nodeset(ref v) => v);

pub(crate) trait NodesetHelpers {
    /// Returns the node that occurs first in [document order]
    ///
    /// [document order]: https://www.w3.org/TR/xpath/#dt-document-order
    fn document_order_first(&self) -> Option<DomRoot<Node>>;
    fn document_order(&self) -> Vec<DomRoot<Node>>;
    fn document_order_unique(&self) -> Vec<DomRoot<Node>>;
}

impl NodesetHelpers for Vec<DomRoot<Node>> {
    fn document_order_first(&self) -> Option<DomRoot<Node>> {
        self.iter()
            .min_by(|a, b| {
                if a == b {
                    std::cmp::Ordering::Equal
                } else if a.is_before(b) {
                    std::cmp::Ordering::Less
                } else {
                    std::cmp::Ordering::Greater
                }
            })
            .cloned()
    }
    fn document_order(&self) -> Vec<DomRoot<Node>> {
        let mut nodes: Vec<DomRoot<Node>> = self.clone();
        if nodes.len() <= 1 {
            return nodes;
        }

        nodes.sort_by(|a, b| {
            if a == b {
                std::cmp::Ordering::Equal
            } else if a.is_before(b) {
                std::cmp::Ordering::Less
            } else {
                std::cmp::Ordering::Greater
            }
        });

        nodes
    }
    fn document_order_unique(&self) -> Vec<DomRoot<Node>> {
        let mut seen = HashSet::new();
        let unique_nodes: Vec<DomRoot<Node>> = self
            .iter()
            .filter(|node| seen.insert(node.to_opaque()))
            .cloned()
            .collect();

        unique_nodes.document_order()
    }
}
