#![allow(unused)]
// Copyright Two Neutron Stars Incorporated and contributors
// SPDX-License-Identifier: BlueOak-1.0.0
// #![doc = include_str!("../readme.md")]

//! # Bluegum
//!
//! A beautiful tree printer for Rust that renders trees in a single pass with
//! rich formatting and customization options.
//!
//! Initially designed to handle concrete and abstract syntax trees, it excels
//! at complex data structures with nested nodes and fields. The output is
//! designed to be both human-readable and diff-friendly, with consistent
//! formatting and optional line numbers.
//!
//! ## Quick Start
//!
//! ```rust
//! use bluegum::{
//!   Bluegum,
//!   Builder,
//! };
//!
//! // Implement Bluegum for your type
//! struct MyData {
//!   name:  String,
//!   value: i32,
//! }
//!
//! impl Bluegum for MyData {
//!   fn node(&self, b: &mut Builder) {
//!     b.name("MyData")
//!       .field("name", &self.name)
//!       .field("value", &self.value);
//!   }
//! }
//!
//! let data = MyData {
//!   name:  "example".to_string(),
//!   value: 42,
//! };
//!
//! // Print to stdout with colors
//! bluegum::println(&data);
//!
//! // Or render to string without colors
//! let output = bluegum::render(&data);
//! ```
//!
//! ## Output Format
//!
//! Bluegum generates tree-like output with sophisticated formatting:
//! - Line numbers for easy reference
//! - Unicode box-drawing characters for tree structure
//! - Colored output (when supported)
//! - Fields displayed as key-value pairs
//! - **Alternate values** aligned in a separate column
//! - **Debug information** in brackets on the right
//!
//! Example output showing all features:
//! ```text
//! 00│◈─▣ symbol::Ident
//! 01│  │ · modifier: Capitalised                       Sum       [value: Spur(3)]
//! 02│  │ · line: 2                                     actual    [file: main.rs]
//! ```
//!
//! ## Unique Features
//!
//! ### Alternate Values (`alt`)
//!
//! Every field can have an alternate value displayed in a right-aligned column.
//! This is particularly useful for showing original source text alongside
//! structured data:
//!
//! ```rust
//! use bluegum::{
//!   Bluegum,
//!   Builder,
//! };
//!
//! struct Token {
//!   token_type:  String,
//!   source_text: String,
//!   line:        u32,
//! }
//!
//! impl Bluegum for Token {
//!   fn node(&self, b: &mut Builder) {
//!     b.name("Token")
//!       .field("type", &self.token_type)
//!       .alt(&self.source_text)  // Shows the actual source text
//!       .field("line", self.line);
//!   }
//! }
//! ```
//!
//! ### Debug Information (`debug`)
//!
//! Multiple key-value debug pairs can be attached to any field or node,
//! displayed in brackets on the far right:
//!
//! ```rust
//! use bluegum::{
//!   Bluegum,
//!   Builder,
//! };
//!
//! struct Symbol {
//!   name:  String,
//!   id:    u32,
//!   scope: String,
//! }
//!
//! impl Bluegum for Symbol {
//!   fn node(&self, b: &mut Builder) {
//!     b.name("Symbol")
//!       .field("name", &self.name)
//!       .debug("id", self.id)
//!       .debug("scope", &self.scope);
//!   }
//! }
//! ```
//!
//! ### Flexible Tree Structure
//!
//! The tree structure you display doesn't need to match your data structure.
//! This is powerful for:
//! - Reconstructing trees from adjacency lists
//! - Showing logical relationships that differ from memory layout
//! - Creating custom views of complex data structures
//! - Flattening or restructuring for better visualization
//!
//! ```rust
//! use bluegum::{
//!   Bluegum,
//!   Builder,
//! };
//!
//! // Data stored as flat list, but displayed as tree
//! struct FlatData {
//!   items: Vec<(String, Option<usize>)>, // (name, parent_index)
//! }
//!
//! impl Bluegum for FlatData {
//!   fn node(&self, b: &mut Builder) {
//!     b.name("FlatData");
//!
//!     // Create tree structure from flat data
//!     for (i, (name, parent)) in self.items.iter().enumerate() {
//!       if parent.is_none() {
//!         b.field("root", name);
//!       }
//!     }
//!   }
//! }
//! ```
//!
//! ## Key Features
//!
//! - **Single Pass Rendering**: Efficient memory usage with one-pass traversal
//! - **Rich Formatting**: Line numbers, Unicode characters, ANSI colors
//! - **Flexible Node Types**: Regular nodes, fragments, and leaf nodes
//! - **State-Based Rendering**: Support for external context during rendering
//! - **Comprehensive Styling**: Full control over appearance and layout
//! - **Built-in Implementations**: Ready-to-use implementations for common
//!   types
//! - **Extensive Testing**: Comprehensive test suite with edge case coverage
//!
//! ## Core Concepts
//!
//! - **Nodes**: Individual items in the tree, can have fields and child nodes
//! - **Fields**: Key-value pairs displayed within a node
//! - **Builder**: Fluent API for constructing tree representations
//! - **State**: Optional context for rendering nodes that depend on external
//!   data (like symbol tables or type information)
//! - **Styles**: Comprehensive customization of colors, spacing, and layout
//!
//! ## Key Features
//!
//! - **Single Pass Rendering**: Efficient memory usage with one-pass traversal
//! - **Rich Formatting**: Line numbers, Unicode characters, ANSI colors
//! - **Flexible Node Types**: Regular nodes, fragments, and leaf nodes
//! - **State-Based Rendering**: Support for external context during rendering
//! - **Comprehensive Styling**: Full control over appearance and layout
//! - **Built-in Implementations**: Ready-to-use implementations for common
//!   types
//! - **Extensive Testing**: Comprehensive test suite with edge case coverage
//!
//! ## Advanced Usage
//!
//! ### Custom Styling
//!
//! ```rust
//! use {
//!   bluegum::{
//!     Printer,
//!     Styles,
//!   },
//!   owo_colors::Style,
//! };
//!
//! let mut styles = Styles::default();
//! styles.hide_line_numbers = true;
//! styles.type_name = Style::new().red().bold();
//!
//! let mut printer = Printer::new(styles);
//! // Use printer.render() and printer.to_stdout()
//! ```
//!
//! ### State-Based Rendering
//!
//! For trees that need external context (like symbol tables):
//!
//! ```rust
//! use bluegum::{
//!   Bluegum,
//!   BluegumWithState,
//!   Builder,
//! };
//!
//! struct SymbolTable {
//!   names: Vec<String>,
//! }
//! struct Variable {
//!   name_id: usize,
//! }
//!
//! impl Bluegum for Variable {
//!   fn node(&self, b: &mut Builder) {
//!     b.name("Variable").field("name_id", self.name_id);
//!   }
//! }
//!
//! impl BluegumWithState<SymbolTable> for Variable {
//!   fn node_with_state(&self, b: &mut Builder, symbols: &SymbolTable) {
//!     b.name("Variable")
//!       .field("name", &symbols.names[self.name_id])
//!       .alt(format!("id:{}", self.name_id));
//!   }
//! }
//! ```

use std::ops::Deref;

mod builder;
mod impls;
mod nodes;
mod prefix;
mod printer;
mod styles;
mod writer;

pub use {
  builder::Builder,
  impls::Leaf,
  nodes::Nodes,
  owo_colors::Style,
  printer::Printer,
  styles::Styles,
};

/// Implement this trait to render this type and optionally any nodes
/// in a tree-like format.
///
/// The `Bluegum` trait is the core of the library. Types that implement
/// this trait can be rendered as trees using the [`Builder`] API.
///
/// # Examples
///
/// ```rust
/// use bluegum::{
///   Bluegum,
///   Builder,
/// };
///
/// struct Person {
///   name: String,
///   age:  u32,
/// }
///
/// impl Bluegum for Person {
///   fn node(&self, b: &mut Builder) {
///     b.name("Person")
///       .field("name", &self.name)
///       .field("age", &self.age);
///   }
/// }
/// ```
pub trait Bluegum {
  /// Render this type as a tree node using the provided builder.
  ///
  /// This method should call methods on the builder to specify:
  /// - The node's name using [`Builder::name`]
  /// - Any fields using [`Builder::field`] or [`Builder::option_field`]
  /// - Any child nodes using [`Builder::add_node`] or [`Builder::add_nodes`]
  fn node(&self, b: &mut crate::Builder);
}

/// A stateful variant of [`Bluegum`] that allows rendering with external
/// context.
///
/// This trait is useful when your tree nodes need to reference external data
/// during rendering, such as symbol tables, type information, or interned
/// strings.
///
/// # Examples
///
/// ```rust
/// use bluegum::{
///   Bluegum,
///   BluegumWithState,
///   Builder,
/// };
///
/// struct SymbolTable {
///   names: Vec<String>,
/// }
///
/// struct Variable {
///   name_id: usize,
/// }
///
/// impl Bluegum for Variable {
///   fn node(&self, b: &mut Builder) {
///     b.name("Variable").field("name_id", self.name_id);
///   }
/// }
///
/// impl BluegumWithState<SymbolTable> for Variable {
///   fn node_with_state(&self, b: &mut Builder, symbols: &SymbolTable) {
///     b.name("Variable")
///       .field("name", &symbols.names[self.name_id])
///       .alt(format!("id:{}", self.name_id));
///   }
/// }
///
/// let symbols = SymbolTable {
///   names: vec!["x".to_string(), "y".to_string()],
/// };
/// let var = Variable { name_id: 0 };
/// let _builder = Builder::render_with_state(&var, &symbols);
/// ```
///
/// ## Features
///
/// - `url`: Enables implementations for `url::Url` types
pub trait BluegumWithState<State: ?Sized>: Bluegum {
  /// Render this type as a tree node using the provided builder and state.
  ///
  /// This method has access to external state that can be used to look up
  /// additional information during rendering.
  fn node_with_state(&self, b: &mut crate::Builder, state: &State) {
    // This is a fallback to the default implementation if this type does not
    // implement `BluegumWithState` for a specific State type.
    crate::Bluegum::node(self, b);
  }
}

/// Print a formatted [`Bluegum`] to stdout with colors.
///
/// This is a convenience function that creates a default [`Printer`],
/// renders the tree, and prints it to stdout.
///
/// # Examples
///
/// ```rust
/// use bluegum::{
///   println,
///   Bluegum,
///   Builder,
/// };
///
/// struct Example;
///
/// impl Bluegum for Example {
///   fn node(&self, b: &mut Builder) {
///     b.name("Example");
///   }
/// }
///
/// let example = Example;
/// println(&example);
/// ```
pub fn println(root: &impl Bluegum) {
  Printer::default().render(root).to_stdout()
}

/// Render a formatted [`Bluegum`] to a string without colors.
///
/// This function creates a default [`Printer`], renders the tree,
/// and returns the result as a string with ANSI color codes stripped.
///
/// # Examples
///
/// ```rust
/// use bluegum::{
///   render,
///   Bluegum,
///   Builder,
/// };
///
/// struct Example;
///
/// impl Bluegum for Example {
///   fn node(&self, b: &mut Builder) {
///     b.name("Example");
///   }
/// }
///
/// let example = Example;
/// let output = render(&example);
/// assert!(output.contains("Example"));
/// ```
pub fn render(root: &impl Bluegum) -> String {
  Printer::default().render(root).strip_color()
}

#[cfg(test)]
mod tests;
