/*
    Appellation: wolfram <example>
    Contrib: @FL03
*/
use eryon_actors::WolframPlant;
use eryon_core::rulemap;
use rstmt::prelude::{LPR, Triad};
use std::collections::HashMap;

fn main() -> anyhow::Result<()> {
    // initialize tracing modules
    tracing_subscriber::fmt()
        .with_ansi(true)
        .with_max_level(tracing::Level::TRACE)
        .with_target(false)
        .init();
    // create a ruleset for the plant
    let ruleset = rulemap! {
        (0, 0) -> Right(0, 4),
        (0, 4) -> Right(1, 7),
        (0, 7) -> Left(0, 0),
        (1, 0) -> Left(1, 7),
        (1, 4) -> Left(0, 11),
        (1, 7) -> Right(1, 4),
        (0, 11) -> Left(1, 7),
        (1, 11) -> Right(0, 0)
    };
    // Create a simple program using our 4 symbols (0, 4, 7, 11)
    let program = [0, 4, 7, 11, 0, 4, 7, 0, 11, 4, 0, 7];

    let mut plant = WolframPlant::from_headspace(Triad::major(0));
    plant.set_ruleset(ruleset.clone());

    tracing::info!("Initial configuration: {}", plant.engine().pretty_print());
    // Run for 100 iterations
    let history = plant.run_for(program.to_vec(), 100)?;

    // Print the execution history
    for (i, snapshot) in history.iter().enumerate() {
        if i < 10 && i > history.len() - 10 {
            tracing::info!("Step {step}: {:?}", snapshot, step = i);
        } else if i % 10 == 0 {
            tracing::info!("Step {step}", step = i);
        }
    }

    tracing::info!("Final state: {}", plant.engine().pretty_print());

    // Analysis of the run
    tracing::info!("Final tape length: {}", plant.tape().len());
    tracing::info!("Final position: {}", plant.position());
    tracing::info!("Final triad: {:?} {:?}", plant.class(), plant.alphabet());

    // Count occurrences of each symbol in the final tape
    let mut symbol_counts = HashMap::new();
    for &symbol in plant.tape() {
        *symbol_counts.entry(symbol).or_insert(0) += 1;
    }
    tracing::info!("- Symbol counts: {:?}", symbol_counts);

    // Detailed information about transformations
    tracing::info!("\nMusical Interpretation:");
    tracing::info!("- Starting with C-Major triad: [0, 4, 7]");
    // Demonstrate a single transformation
    let headspace = Triad::major(0);
    let mut plant = WolframPlant::from_headspace(headspace);
    tracing::info!("- Initial plant: {plant:?}",);

    plant.transform_mut(LPR::Leading);
    tracing::info!("- After δ_L: {:?}", plant);
    assert_eq!(plant.headspace(), Triad::minor(4));

    plant.transform_mut(LPR::Leading);
    assert_eq!(plant.headspace(), headspace, "δ_L^2 should be identity");
    tracing::info!("- After δ_L again: {:?}", plant);
    Ok(())
}
