//! This module is only used when the feature `terminfo` is not activated.

use proc_macro::TokenStream;
use proc_macro2::TokenStream as TokenStream2;
use quote::{quote, ToTokens};

use crate::color_context::Context;
use crate::format_args::{get_args_and_format_string, parse_format_string, Node};
use crate::error::SpanError;

/// Common code shared between the three public macros, ANSI implementation.
pub fn get_format_args(input: TokenStream) -> Result<TokenStream2, SpanError> {
    let (format_string_token, args) = get_args_and_format_string(input)?;
    let format_string = format_string_token.value();

    // Split the format string into a list of nodes; each node is either a string literal (text), a
    // placeholder for a `format!`-like macro, or a color code:
    let format_nodes = parse_format_string(&format_string, &format_string_token)?;

    // The final, modified format string which will be given to the `format!`-like macro:
    let mut final_format_string = String::new();

    // Stores which colors and attributes are set while processing the format string:
    let mut color_context = Context::new();

    // Generate the final format string:
    for node in format_nodes {
        match node {
            Node::Text(s) | Node::Placeholder(s) => {
                final_format_string.push_str(s);
            }
            Node::ColorTagGroup(tag_group) => {
                let ansi_string = color_context.ansi_apply_tags(tag_group)?;
                final_format_string.push_str(&ansi_string);
            }
        }
    }

    // Group all the final arguments into a single iterator:
    let final_format_string = quote! { #final_format_string };
    let args = args.iter()
        .map(|arg| arg.to_token_stream())
        .skip(1); // Skip the original format string
    let final_args = std::iter::once(final_format_string).chain(args);

    Ok(quote! { #(#final_args),* }.into())
}
