//! Dependency trees computed from `Cargo.lock` files.
//!
//! Uses the `petgraph` crate for modeling the dependency structure.

// Includes code from `cargo-tree`, Copyright (c) 2015-2016 Steven Fackler
// Licensed under the same terms as `cargo-audit` (i.e. Apache 2.0 + MIT)

use super::{
    graph::{EdgeDirection, Graph, NodeIndex, Nodes},
    Dependency,
};
use crate::{error::Error, lockfile::Lockfile, Map};
use std::{collections::BTreeSet as Set, io};

/// Dependency tree computed from a `Cargo.lock` file
#[derive(Clone, Debug)]
pub struct Tree {
    /// Dependency graph for a particular package
    graph: Graph,

    /// Package data associated with nodes in the graph
    nodes: Nodes,
}

impl Tree {
    /// Construct a new dependency tree for the given [`Lockfile`].
    pub fn new(lockfile: &Lockfile) -> Result<Self, Error> {
        let mut graph = Graph::new();
        let mut nodes = Map::new();

        // Populate all graph nodes in the first pass
        for package in &lockfile.packages {
            let node_index = graph.add_node(package.clone());
            nodes.insert(Dependency::from(package), node_index);
        }

        // Populate all graph edges in the second pass
        for package in &lockfile.packages {
            let parent_index = nodes[&Dependency::from(package)];

            for dependency in &package.dependencies {
                if let Some(node_index) = nodes.get(dependency) {
                    graph.add_edge(parent_index, *node_index, dependency.clone());
                }
            }
        }

        Ok(Tree { graph, nodes })
    }

    /// Render the dependency graph for the given [`NodeIndex`] using the
    /// default set of [`Symbols`].
    pub fn render(
        &self,
        w: &mut impl io::Write,
        node_index: NodeIndex,
        direction: EdgeDirection,
        exact: bool,
    ) -> io::Result<()> {
        self.render_with_symbols(w, node_index, direction, &Symbols::default(), exact)
    }

    /// Render the dependency graph for the given [`NodeIndex`] using the
    /// provided set of [`Symbols`].
    pub fn render_with_symbols(
        &self,
        w: &mut impl io::Write,
        node_index: NodeIndex,
        direction: EdgeDirection,
        symbols: &Symbols,
        exact: bool,
    ) -> io::Result<()> {
        Presenter::new(&self.graph, symbols).print_node(w, node_index, direction, exact)
    }

    /// Get the indexes of the root packages in the workspace
    /// (i.e. toplevel packages which are not used as dependencies)
    pub fn roots(&self) -> Vec<NodeIndex> {
        self.graph.externals(EdgeDirection::Incoming).collect()
    }

    /// Get the `petgraph` dependency graph.
    pub fn graph(&self) -> &Graph {
        &self.graph
    }

    /// Get the nodes of the `petgraph` dependency graph.
    pub fn nodes(&self) -> &Nodes {
        &self.nodes
    }
}

/// Symbols to use when printing the dependency tree
pub struct Symbols {
    down: &'static str,
    tee: &'static str,
    ell: &'static str,
    right: &'static str,
}

impl Default for Symbols {
    fn default() -> Symbols {
        Self {
            down: "│",
            tee: "├",
            ell: "└",
            right: "─",
        }
    }
}

/// Dependency tree presenter
struct Presenter<'g, 's> {
    /// Dependency graph being displayed
    graph: &'g Graph,

    /// Symbols to use to display graph
    symbols: &'s Symbols,

    /// Are there continuing levels?
    levels_continue: Vec<bool>,

    /// Dependencies we've already visited
    visited: Set<NodeIndex>,
}

impl<'g, 's> Presenter<'g, 's> {
    /// Create a new dependency tree `Presenter`.
    fn new(graph: &'g Graph, symbols: &'s Symbols) -> Self {
        Self {
            graph,
            symbols,
            levels_continue: vec![],
            visited: Set::new(),
        }
    }

    /// Print a node in the dependency tree.
    fn print_node(
        &mut self,
        w: &mut impl io::Write,
        node_index: NodeIndex,
        direction: EdgeDirection,
        exact: bool,
    ) -> io::Result<()> {
        let package = &self.graph[node_index];
        let new = self.visited.insert(node_index);

        if let Some((&last_continues, rest)) = self.levels_continue.split_last() {
            for &continues in rest {
                let c = if continues { self.symbols.down } else { " " };
                write!(w, "{}   ", c)?;
            }

            let c = if last_continues {
                self.symbols.tee
            } else {
                self.symbols.ell
            };

            write!(w, "{0}{1}{1} ", c, self.symbols.right)?;
        }

        if exact {
            let spec = if let Some(checksum) = &package.checksum {
                format!("checksum:{}", checksum)
            } else if let Some(src) = &package.source {
                src.to_string()
            } else {
                "inexact".to_string()
            };
            writeln!(w, "{} {} {}", &package.name, &package.version, spec)?;
        } else {
            writeln!(w, "{} {}", &package.name, &package.version)?;
        }

        if !new {
            return Ok(());
        }

        use petgraph::visit::EdgeRef;
        let dependencies = self
            .graph
            .edges_directed(node_index, direction)
            .map(|edge| match direction {
                EdgeDirection::Incoming => edge.source(),
                EdgeDirection::Outgoing => edge.target(),
            })
            .collect::<Vec<_>>();

        for (i, dependency) in dependencies.iter().enumerate() {
            self.levels_continue.push(i < (dependencies.len() - 1));
            self.print_node(w, *dependency, direction, exact)?;
            self.levels_continue.pop();
        }

        Ok(())
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    /// Load this crate's `Cargo.lock`
    fn load_lockfile() -> Lockfile {
        Lockfile::load("tests/examples/Cargo.lock.v3").unwrap()
    }

    #[test]
    fn compute_tree() {
        // TODO(tarcieri): test dependency tree is computed correctly
        Tree::new(&load_lockfile()).unwrap();
    }

    #[test]
    fn compute_roots() {
        let tree = Tree::new(&load_lockfile()).unwrap();
        let roots = tree.roots();
        assert_eq!(roots.len(), 1);

        let root_package = &tree.graph[roots[0]];
        assert_eq!(root_package.name.as_str(), "cargo-lock");
    }
}
