use chumsky::{
    extra,
    input::MappedSpan,
    primitive::{any, choice, just},
    recursive::recursive,
    text::newline,
    Parser,
};

use crate::{
    __internal__parser,
    parse::{map_err_missing_delimiter, DelimiterType, Error},
    Span,
};

#[cfg(test)]
mod test;

__internal__parser! {source_file_multi_line_comment, (), {
    recursive(|multi_line_comment|
            map_err_missing_delimiter(
                just("/*"),
                choice((
                    multi_line_comment,
                    any()
                        .and_is(just("*/").not())
                        .ignored()
                )).repeated(),
                just("*/"),
                DelimiterType::MultiLineComment
            )
    )
}}

__internal__parser! {source_file_single_line_comment, (), {
        just("//")
            .and_is(just("/*").not())
            .then(any().and_is(newline().not()).repeated())
            .then(newline().or_not())
            .ignored()
}}

__internal__parser! {source_file_single_line_comment_right_delimiter(right_delimiter: impl Parser<'s, MappedSpan<Span<'s>, &'s str, F>, (), extra::Err<Error<'s>>> + Clone + 's), (), {
    just("//")
        .and_is(just("/*").not())
        .then(any().and_is(newline().or(right_delimiter).not()).repeated())
        .then(newline().or_not())
        .ignored()
}}

__internal__parser! {pub source_file_comment, (), {
    source_file_multi_line_comment().or(source_file_single_line_comment())
}}

__internal__parser! {pub source_file_comment_right_delimiter(right_delimiter: impl Parser<'s, MappedSpan<Span<'s>, &'s str, F>, (), extra::Err<Error<'s>>> + Clone + 's), (), {
    source_file_multi_line_comment().or(source_file_single_line_comment_right_delimiter(
        right_delimiter,
    ))
}}
