//! Example for how to use `VisitMut` to iterate over a table.

use std::collections::BTreeSet;
use toml_edit::visit::*;
use toml_edit::visit_mut::*;
use toml_edit::{Array, Document, InlineTable, Item, KeyMut, Table, Value};

/// This models the visit state for dependency keys in a `Cargo.toml`.
///
/// Dependencies can be specified as:
///
/// ```toml
/// [dependencies]
/// dep1 = "0.2"
///
/// [build-dependencies]
/// dep2 = "0.3"
///
/// [dev-dependencies]
/// dep3 = "0.4"
///
/// [target.'cfg(windows)'.dependencies]
/// dep4 = "0.5"
///
/// # and target build- and dev-dependencies
/// ```
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
enum VisitState {
    /// Represents the root of the table.
    Root,
    /// Represents "dependencies", "build-dependencies" or "dev-dependencies", or the target
    /// forms of these.
    Dependencies,
    /// A table within dependencies.
    SubDependencies,
    /// Represents "target".
    Target,
    /// "target.[TARGET]".
    TargetWithSpec,
    /// Represents some other state.
    Other,
}

impl VisitState {
    /// Figures out the next visit state, given the current state and the given key.
    fn descend(self, key: &str) -> Self {
        match (self, key) {
            (
                VisitState::Root | VisitState::TargetWithSpec,
                "dependencies" | "build-dependencies" | "dev-dependencies",
            ) => VisitState::Dependencies,
            (VisitState::Root, "target") => VisitState::Target,
            (VisitState::Root | VisitState::TargetWithSpec, _) => VisitState::Other,
            (VisitState::Target, _) => VisitState::TargetWithSpec,
            (VisitState::Dependencies, _) => VisitState::SubDependencies,
            (VisitState::SubDependencies, _) => VisitState::SubDependencies,
            (VisitState::Other, _) => VisitState::Other,
        }
    }
}

/// Collect the names of every dependency key.
#[derive(Debug)]
struct DependencyNameVisitor<'doc> {
    state: VisitState,
    names: BTreeSet<&'doc str>,
}

impl<'doc> Visit<'doc> for DependencyNameVisitor<'doc> {
    fn visit_table_like_kv(&mut self, key: &'doc str, node: &'doc Item) {
        if self.state == VisitState::Dependencies {
            self.names.insert(key);
        } else {
            // Since we're only interested in collecting the top-level keys right under
            // [dependencies], don't recurse unconditionally.

            let old_state = self.state;

            // Figure out the next state given the key.
            self.state = self.state.descend(key);

            // Recurse further into the document tree.
            visit_table_like_kv(self, key, node);

            // Restore the old state after it's done.
            self.state = old_state;
        }
    }
}

/// Normalize all dependency tables into the format:
///
/// ```toml
/// [dependencies]
/// dep = { version = "1.0", features = ["foo", "bar"], ... }
/// ```
///
/// leaving other tables untouched.
#[derive(Debug)]
struct NormalizeDependencyTablesVisitor {
    state: VisitState,
}

impl VisitMut for NormalizeDependencyTablesVisitor {
    fn visit_table_mut(&mut self, node: &mut Table) {
        visit_table_mut(self, node);

        // The conversion from regular tables into inline ones might leave some explicit parent
        // tables hanging, so convert them to implicit.
        if matches!(self.state, VisitState::Target | VisitState::TargetWithSpec) {
            node.set_implicit(true);
        }
    }

    fn visit_table_like_kv_mut(&mut self, mut key: KeyMut<'_>, node: &mut Item) {
        let old_state = self.state;

        // Figure out the next state given the key.
        self.state = self.state.descend(key.get());

        match self.state {
            VisitState::Target | VisitState::TargetWithSpec | VisitState::Dependencies => {
                // Top-level dependency row, or above: turn inline tables into regular ones.
                if let Item::Value(Value::InlineTable(inline_table)) = node {
                    let inline_table = std::mem::replace(inline_table, InlineTable::new());
                    let table = inline_table.into_table();
                    key.fmt();
                    *node = Item::Table(table);
                }
            }
            VisitState::SubDependencies => {
                // Individual dependency: turn regular tables into inline ones.
                if let Item::Table(table) = node {
                    // Turn the table into an inline table.
                    let table = std::mem::replace(table, Table::new());
                    let inline_table = table.into_inline_table();
                    key.fmt();
                    *node = Item::Value(Value::InlineTable(inline_table));
                }
            }
            _ => {}
        }

        // Recurse further into the document tree.
        visit_table_like_kv_mut(self, key, node);

        // Restore the old state after it's done.
        self.state = old_state;
    }

    fn visit_array_mut(&mut self, node: &mut Array) {
        // Format any arrays within dependencies to be on the same line.
        if matches!(
            self.state,
            VisitState::Dependencies | VisitState::SubDependencies
        ) {
            node.fmt();
        }
    }
}

/// This is the input provided to visit_mut_example.
static INPUT: &str = r#"
[package]
name = "my-package"

[package.metadata.foo]
bar = 42

[dependencies]
atty = "0.2"
cargo-platform = { path = "crates/cargo-platform", version = "0.1.2" }

[dependencies.pretty_env_logger]
version = "0.4"
optional = true

[target.'cfg(windows)'.dependencies]
fwdansi = "1.1.0"

[target.'cfg(windows)'.dependencies.winapi]
version = "0.3"
features = [
"handleapi",
"jobapi",
]

[target.'cfg(unix)']
dev-dependencies = { miniz_oxide = "0.5" }

[dev-dependencies.cargo-test-macro]
path = "crates/cargo-test-macro"

[build-dependencies.flate2]
version = "0.4"
"#;

/// This is the output produced by visit_mut_example.
#[cfg(test)]
static VISIT_MUT_OUTPUT: &str = r#"
[package]
name = "my-package"

[package.metadata.foo]
bar = 42

[dependencies]
atty = "0.2"
cargo-platform = { path = "crates/cargo-platform", version = "0.1.2" }
pretty_env_logger = { version = "0.4", optional = true }

[target.'cfg(windows)'.dependencies]
fwdansi = "1.1.0"
winapi = { version = "0.3", features = ["handleapi", "jobapi"] }

[target.'cfg(unix)'.dev-dependencies]
miniz_oxide = "0.5"

[dev-dependencies]
cargo-test-macro = { path = "crates/cargo-test-macro" }

[build-dependencies]
flate2 = { version = "0.4" }
"#;

fn visit_example(document: &Document) -> BTreeSet<&str> {
    let mut visitor = DependencyNameVisitor {
        state: VisitState::Root,
        names: BTreeSet::new(),
    };

    visitor.visit_document(document);

    visitor.names
}

fn visit_mut_example(document: &mut Document) {
    let mut visitor = NormalizeDependencyTablesVisitor {
        state: VisitState::Root,
    };

    visitor.visit_document_mut(document);
}

fn main() {
    let mut document: Document = INPUT.parse().expect("input is valid TOML");

    println!("** visit example");
    println!("{:?}", visit_example(&document));

    println!("** visit_mut example");
    visit_mut_example(&mut document);
    println!("{}", document);
}

#[cfg(test)]
#[test]
fn visit_correct() {
    let document: Document = INPUT.parse().expect("input is valid TOML");

    let names = visit_example(&document);
    let expected = vec![
        "atty",
        "cargo-platform",
        "pretty_env_logger",
        "fwdansi",
        "winapi",
        "miniz_oxide",
        "cargo-test-macro",
        "flate2",
    ]
    .into_iter()
    .collect();
    assert_eq!(names, expected);
}

#[cfg(test)]
#[test]
fn visit_mut_correct() {
    let mut document: Document = INPUT.parse().expect("input is valid TOML");

    visit_mut_example(&mut document);
    assert_eq!(format!("{}", document), VISIT_MUT_OUTPUT);
}
