use {
    chumsky::{
        prelude::*, text::*
    },
    std::sync::{Arc, RwLock},

    laddertypes::{TypeDict, BimapTypeDict, parser::*},
    crate::morphism::LdmcPrimCMorphism
};

/* morphism-base text format:
 *     NAME '(' [TYPE-ARG-NAME ':' KIND]  ')'
 *           SRC-TYPE
 *     '-->' DST-TYPE
 *     ```
 *          TEMPLATE-CODE
 *     ```
 */
pub fn morphism_base_parser(
    type_dict: Arc<RwLock< BimapTypeDict >>
) -> impl Parser<char, (String, Vec<LdmcPrimCMorphism>), Error = Simple<char>> {

    just("```")
    .then(take_until(just("```")))
    .map(
        move |(a, (b, c))| {
            b.iter().collect()
        }
    )

    // morph name
    .then(
        ident().padded()

    // type args
    .then(
        ident().padded()
        .then_ignore(just(":").padded())
        .then(none_of(",)").repeated().padded())
        .separated_by(just(",").padded())
        .delimited_by(just("("), just(")"))
    )

    // newline
    .then_ignore(just('\n'))

    // src type
    .then(take_until(just("-->").ignored()))
    // dst_type
    .then(take_until(just("```")))

    // c sourcecode template
    .then(take_until(just("```")))

    .map(
        move |((((symbol, type_args), (src_type, _)), (dst_type, _)), (c_source, _))| {
            let c_source = c_source.iter().collect();
            let mut type_dict = type_dict.write().unwrap();
            let type_args : Vec<_> = type_args.into_iter().map(|(v,k)| (v,k.into_iter().collect())).collect();
            let mut ty_args = Vec::new();
            for (var, kind) in type_args.into_iter() {
                let var_id = type_dict.add_varname(var.clone());
                ty_args.push((var_id, kind));
            }

            let mut src_type = type_dict.parse(&src_type.iter().collect::<String>()).expect("couldnt parse src type");
            let mut dst_type = type_dict.parse(&dst_type.iter().collect::<String>()).expect("couldnt parse dst type");

            LdmcPrimCMorphism {
                symbol,
                type_args: ty_args,
                src_type,
                dst_type,
                c_source
            }
        })
        .separated_by(text::newline())

    )
}