use super::NodePrint;
use crate::{DepKind, Krates};
use anyhow::Context;
use krates::{petgraph as pg, Edge, Node};
use std::collections::HashSet;

#[derive(serde::Serialize)]
pub struct GraphNode {
    #[serde(flatten)]
    inner: NodeInner,
    #[serde(skip_serializing_if = "is_false")]
    repeat: bool,
    #[serde(skip_serializing_if = "is_empty")]
    parents: Vec<GraphNode>,
}

#[derive(serde::Serialize)]
pub enum NodeInner {
    Krate {
        name: String,
        version: semver::Version,
        #[serde(skip_serializing_if = "Option::is_none")]
        kind: Option<&'static str>,
    },
    Feature {
        crate_name: String,
        name: String,
    },
}

#[allow(clippy::trivially_copy_pass_by_ref)]
fn is_false(v: &bool) -> bool {
    !v
}

#[allow(clippy::ptr_arg)]
fn is_empty(v: &Vec<GraphNode>) -> bool {
    v.is_empty()
}

/// Provides the `InclusionGrapher::write_graph` method which creates a reverse
/// dependency graph rooted at a specific node
pub struct InclusionGrapher<'a> {
    pub krates: &'a Krates,
}

impl<'a> InclusionGrapher<'a> {
    pub fn new(krates: &'a Krates) -> Self {
        Self { krates }
    }

    /// Creates an inclusion graph rooted at the specified node.
    pub fn build_graph(
        &self,
        id: &super::GraphNode,
        max_feature_depth: usize,
    ) -> anyhow::Result<GraphNode> {
        let mut visited = HashSet::new();

        let (node_id, _node) = self
            .krates
            .get_node(&id.kid, id.feature.as_deref())
            .context("unable to find node")?;

        let np = NodePrint {
            node: node_id,
            edge: None,
        };

        let root = self.append_node(np, 0, max_feature_depth, &mut visited)?;

        // If the graph was rooted on a feature node, we want to use that as the
        // root when building the graph, but want the actual crate the feature
        // belongs to be the root of the graph the user sees
        if id.feature.is_some() {
            let (_id, root_krate) = self.krates.get_node(&id.kid, None).with_context(|| {
                format!(
                    "graph was built but we were unable to find the node for {}",
                    id.kid
                )
            })?;

            let inner = if let Node::Krate { krate, .. } = root_krate {
                NodeInner::Krate {
                    name: krate.name.clone(),
                    version: krate.version.clone(),
                    kind: None,
                }
            } else {
                anyhow::bail!("unable to find crate node for {}", id.kid);
            };

            Ok(GraphNode {
                inner,
                repeat: false,
                parents: vec![root],
            })
        } else {
            Ok(root)
        }
    }

    fn make_node(&self, np: NodePrint) -> NodeInner {
        match &self.krates.graph()[np.node] {
            Node::Krate { krate, .. } => {
                let kind = np.edge.and_then(|eid| match self.krates.graph()[eid] {
                    Edge::Dep { kind, .. } | Edge::DepFeature { kind, .. } => match kind {
                        DepKind::Normal => None,
                        DepKind::Dev => Some("dev"),
                        DepKind::Build => Some("build"),
                    },
                    Edge::Feature => None,
                });

                NodeInner::Krate {
                    name: krate.name.clone(),
                    version: krate.version.clone(),
                    kind,
                }
            }
            Node::Feature { name, krate_index } => {
                let crate_name =
                    if let Node::Krate { krate, .. } = &self.krates.graph()[*krate_index] {
                        krate.name.clone()
                    } else {
                        "".to_owned()
                    };

                NodeInner::Feature {
                    crate_name,
                    name: name.clone(),
                }
            }
        }
    }

    fn append_node(
        &self,
        np: NodePrint,
        depth: usize,
        max_feature_depth: usize,
        visited: &mut HashSet<krates::NodeId>,
    ) -> anyhow::Result<GraphNode> {
        use pg::visit::EdgeRef;

        if !visited.insert(np.node) {
            return Ok(GraphNode {
                inner: self.make_node(np),
                repeat: true,
                parents: Vec::new(),
            });
        }

        let mut node_parents = smallvec::SmallVec::<[NodePrint; 10]>::new();
        let graph = self.krates.graph();

        if depth < max_feature_depth {
            node_parents.extend(graph.edges_directed(np.node, pg::Direction::Incoming).map(
                |edge| NodePrint {
                    node: edge.source(),
                    edge: Some(edge.id()),
                },
            ));
        } else {
            // If we're not adding features we need to walk up any feature edges
            // until we reach an actual crate dependenc

            node_parents.extend(
                self.krates
                    .direct_dependents(np.node)
                    .into_iter()
                    .map(|dd| NodePrint {
                        node: dd.node_id,
                        edge: Some(dd.edge_id),
                    }),
            );
        }

        let parents = if !node_parents.is_empty() {
            // Resolve uses Hash data types internally but we want consistent output ordering
            node_parents.sort_by(|a, b| match (&graph[a.node], &graph[b.node]) {
                (Node::Krate { krate: a, .. }, Node::Krate { krate: b, .. }) => a.id.cmp(&b.id),
                (Node::Krate { .. }, Node::Feature { .. }) => std::cmp::Ordering::Less,
                (Node::Feature { .. }, Node::Krate { .. }) => std::cmp::Ordering::Greater,
                (Node::Feature { name: a, .. }, Node::Feature { name: b, .. }) => a.cmp(b),
            });

            let mut parents = Vec::with_capacity(node_parents.len());

            for parent in node_parents {
                let pnode = self.append_node(parent, depth + 1, max_feature_depth, visited)?;
                parents.push(pnode);
            }

            parents
        } else {
            Vec::new()
        };

        Ok(GraphNode {
            inner: self.make_node(np),
            repeat: false,
            parents,
        })
    }
}

use super::{Diag, FileId, Files, Severity};

pub type CsDiag = codespan_reporting::diagnostic::Diagnostic<FileId>;

pub fn cs_diag_to_json(diag: CsDiag, files: &Files) -> serde_json::Value {
    let mut val = serde_json::json!({
        "type": "diagnostic",
        "fields": {
            "severity": match diag.severity {
                Severity::Error => "error",
                Severity::Warning => "warning",
                Severity::Note => "note",
                Severity::Help => "help",
                Severity::Bug => "bug",
            },
            "message": diag.message,
        },
    });

    {
        let obj = val.as_object_mut().unwrap();
        let obj = obj.get_mut("fields").unwrap().as_object_mut().unwrap();

        if let Some(code) = diag.code {
            obj.insert("code".to_owned(), serde_json::Value::String(code));
        }

        if !diag.labels.is_empty() {
            let mut labels = Vec::with_capacity(diag.labels.len());

            for label in diag.labels {
                let location = files
                    .location(label.file_id, label.range.start as u32)
                    .unwrap();
                labels.push(serde_json::json!({
                    "message": label.message,
                    "span": files.source(label.file_id)[label.range].trim_matches('"'),
                    "line": location.line.to_usize() + 1,
                    "column": location.column.to_usize() + 1,
                }));
            }

            obj.insert("labels".to_owned(), serde_json::Value::Array(labels));
        }

        if !diag.notes.is_empty() {
            obj.insert(
                "notes".to_owned(),
                serde_json::Value::Array(
                    diag.notes
                        .into_iter()
                        .map(serde_json::Value::String)
                        .collect(),
                ),
            );
        }
    }

    val
}

pub fn diag_to_json(
    diag: Diag,
    files: &Files,
    grapher: Option<&InclusionGrapher<'_>>,
) -> serde_json::Value {
    let mut to_print = cs_diag_to_json(diag.diag, files);

    let obj = to_print.as_object_mut().unwrap();
    let fields = obj.get_mut("fields").unwrap().as_object_mut().unwrap();

    if let Some(grapher) = &grapher {
        let mut graphs = Vec::new();
        for gn in diag.graph_nodes {
            if let Ok(graph) =
                grapher.build_graph(&gn, if diag.with_features { usize::MAX } else { 0 })
            {
                if let Ok(sgraph) = serde_json::value::to_value(graph) {
                    graphs.push(sgraph);
                }
            }
        }

        fields.insert("graphs".to_owned(), serde_json::Value::Array(graphs));
    }

    if let Some((key, val)) = diag.extra {
        fields.insert(key.to_owned(), val);
    }

    to_print
}

pub fn write_graph_as_text(root: &GraphNode) -> String {
    use std::fmt::Write;

    const DWN: char = '│';
    const TEE: char = '├';
    const ELL: char = '└';
    const RGT: char = '─';

    let mut out = String::with_capacity(256);
    let mut levels = smallvec::SmallVec::<[bool; 10]>::new();

    fn write(
        node: &GraphNode,
        out: &mut String,
        levels_continue: &mut smallvec::SmallVec<[bool; 10]>,
    ) {
        let star = if !node.repeat { "" } else { " (*)" };

        if let Some((&last_continues, rest)) = levels_continue.split_last() {
            for &continues in rest {
                let c = if continues { DWN } else { ' ' };
                write!(out, "{c}   ").unwrap();
            }

            let c = if last_continues { TEE } else { ELL };
            write!(out, "{c}{0}{0} ", RGT).unwrap();
        }

        match &node.inner {
            NodeInner::Krate {
                name,
                version,
                kind,
            } => {
                if let Some(kind) = kind {
                    write!(out, "({kind}) ").unwrap();
                }

                writeln!(out, "{name} v{version}{star}").unwrap();
            }
            NodeInner::Feature { crate_name, name } => {
                writeln!(out, "{crate_name} feature '{name}' {star}").unwrap();
            }
        }

        if node.parents.is_empty() {
            return;
        }

        let cont = node.parents.len() - 1;

        for (i, parent) in node.parents.iter().enumerate() {
            levels_continue.push(i < cont);
            write(parent, out, levels_continue);
            levels_continue.pop();
        }
    }

    write(root, &mut out, &mut levels);
    out
}
