use granit_parser::{
    parser_stack::ParserStack, Event, Parser, ParserTrait, ScanError, StrInput, Tag,
};

type IncludeStack = ParserStack<'static, core::iter::Empty<char>, StrInput<'static>>;

const ROOT_YAML: &str = r"
root:
  before: &root_anchor from-root
  include: !include something.yaml
  after: &after_anchor after-include
";

fn resolve_include(name: &str) -> Result<String, ScanError> {
    match name {
        "something.yaml" => Ok("included: &included_anchor from-include\n".to_string()),
        _ => Err(ScanError::new_str(
            granit_parser::Marker::new(0, 1, 0),
            "include not found",
        )),
    }
}

fn is_include_tag(tag: &Tag) -> bool {
    tag.parts() == ("!", "include")
}

fn main() -> Result<(), ScanError> {
    let mut stack: IncludeStack = ParserStack::new();
    stack.push_str_parser(Parser::new_from_str(ROOT_YAML), "root.yaml".to_string());
    stack.set_resolver(resolve_include);

    let mut anchored_scalars = Vec::new();

    while let Some(next) = stack.next_event() {
        let (event, _) = next?;

        match event {
            Event::Scalar(include_name, _, _, Some(tag)) if is_include_tag(tag.as_ref()) => {
                stack.push_include(include_name.as_ref())?;
            }
            Event::Scalar(value, _, anchor_id, _) if anchor_id > 0 => {
                anchored_scalars.push((value.into_owned(), anchor_id));
            }
            _ => {}
        }
    }

    assert_eq!(
        anchored_scalars,
        vec![
            ("from-root".to_string(), 1),
            ("from-include".to_string(), 2),
            ("after-include".to_string(), 3),
        ]
    );

    for (value, anchor_id) in anchored_scalars {
        println!("{value}: anchor {anchor_id}");
    }

    Ok(())
}
