use chumsky::{
    primitive::{any, choice, just},
    recursive::recursive,
    IterParser, Parser,
};

use crate::{
    __internal__parser,
    ast::Type,
    parse::{
        map_err_missing_delimiter,
        source_file::{source_file_whitespace_or_comments, template::struct_parameters_common},
        with_span, DelimiterType,
    },
    Span,
};

#[cfg(test)]
mod test;

__internal__parser! {pub ty, Type<'s>, {
    recursive(|ty| {
        choice((
                map_err_missing_delimiter(
                    just('[').to_span(),
                    with_span(ty.clone().map(Box::new).or_not()).padded_by(source_file_whitespace_or_comments()),
                    just(']'),
                    DelimiterType::ArrayType
                ).map(Type::Array),

                map_err_missing_delimiter(
                    just('(').to_span(),
                    with_span(ty.clone())
                        .separated_by(just(',').padded_by(source_file_whitespace_or_comments()))
                        .allow_trailing()
                        .collect::<Vec<(Type<'s>, Span<'s>)>>()
                        .padded_by(source_file_whitespace_or_comments()),
                    just(')'),
                    DelimiterType::TupleType
                ).map(Type::Tuple),

                map_err_missing_delimiter(
                    just('{').to_span(),
                    struct_parameters_common(ty).padded_by(source_file_whitespace_or_comments()),
                    just('}'),
                    DelimiterType::StructType
                ).map(Type::Struct),

                any().filter(|c| char::is_alphanumeric(*c)).repeated().at_least(1).separated_by(just('.')).at_least(1).to_slice().map(Type::Base)
        ))
    })
}}
