use super::container_manifest::{construct_manif_tokenstream, manifest_tokenstream};
use super::gen_container_factory::factory_tokenstream;
use quote::quote;
use crate::proc_macro::TokenStream;
use syn::{parse_macro_input, ItemFn, Stmt};
use crate::util::{get_body_tokenstream, change_argument_to_capsule_map};
use crate::util::parse_attr;
pub(crate) fn juiz_container_inner(attr: TokenStream, item: TokenStream) -> TokenStream {
let manifest_attr = parse_attr(attr);
let mut ast = parse_macro_input!(item as ItemFn);
let function_name = ast.sig.ident.clone().to_string();
let arg_map = change_argument_to_capsule_map(&mut ast);
let body: TokenStream = get_body_tokenstream(&ast);
ast.block.stmts.clear();
for (type_name, arg_name) in arg_map.iter() {
let set_original_argument_statement: TokenStream = quote!(
let #arg_name : #type_name = __the_only_argument_modified_by_juiz_process_macro__.get(stringify!(#arg_name))?.try_into()?;
).into();
ast.block.stmts.push(parse_macro_input!(set_original_argument_statement as Stmt));
}
ast.block.stmts.push(parse_macro_input!(body as Stmt));
let exit: TokenStream = quote! { { body() } }.into();
ast.block.stmts.push(parse_macro_input!(exit as Stmt));
let manifest2_tokenstream = manifest_tokenstream();
let mut manifest2_item_fn : ItemFn = syn::parse_macro_input!(manifest2_tokenstream as ItemFn);
let return_manifest = construct_manif_tokenstream(function_name, &manifest_attr, &arg_map);
manifest2_item_fn.block.stmts.push(parse_macro_input!(return_manifest as Stmt));
let fts = factory_tokenstream(ast.sig.ident.clone());
let factory_item_fn : ItemFn = syn::parse_macro_input!(fts as ItemFn);
quote! {
#factory_item_fn
#ast
#manifest2_item_fn
}.into()
}