use crate::codegen;
use crate::ir::context::BindgenContext;
use crate::ir::function::ClangAbi;
use proc_macro2::{Ident, TokenStream};

/// Used to build the output tokens for dynamic bindings.
#[derive(Default)]
pub(crate) struct DynamicItems {
    /// Tracks the tokens that will appears inside the library struct -- e.g.:
    /// ```ignore
    /// struct Lib {
    ///    __library: ::libloading::Library,
    ///    pub x: Result<unsafe extern ..., ::libloading::Error>, // <- tracks these
    ///    ...
    /// }
    /// ```
    struct_members: Vec<TokenStream>,

    /// Tracks the tokens that will appear inside the library struct's implementation, e.g.:
    ///
    /// ```ignore
    /// impl Lib {
    ///     ...
    ///     pub unsafe fn foo(&self, ...) { // <- tracks these
    ///         ...
    ///     }
    /// }
    /// ```
    struct_implementation: Vec<TokenStream>,

    /// Tracks the initialization of the fields inside the `::new` constructor of the library
    /// struct, e.g.:
    /// ```ignore
    /// impl Lib {
    ///
    ///     pub unsafe fn new<P>(path: P) -> Result<Self, ::libloading::Error>
    ///     where
    ///         P: AsRef<::std::ffi::OsStr>,
    ///     {
    ///         ...
    ///         let foo = __library.get(...) ...; // <- tracks these
    ///         ...
    ///     }
    ///
    ///     ...
    /// }
    /// ```
    constructor_inits: Vec<TokenStream>,

    /// Tracks the information that is passed to the library struct at the end of the `::new`
    /// constructor, e.g.:
    /// ```ignore
    /// impl LibFoo {
    ///     pub unsafe fn new<P>(path: P) -> Result<Self, ::libloading::Error>
    ///     where
    ///         P: AsRef<::std::ffi::OsStr>,
    ///     {
    ///         ...
    ///         Ok(LibFoo {
    ///             __library: __library,
    ///             foo,
    ///             bar, // <- tracks these
    ///             ...
    ///         })
    ///     }
    /// }
    /// ```
    init_fields: Vec<TokenStream>,
}

impl DynamicItems {
    pub(crate) fn new() -> Self {
        Self::default()
    }

    pub(crate) fn get_tokens(
        &self,
        lib_ident: &Ident,
        ctx: &BindgenContext,
    ) -> TokenStream {
        let struct_members = &self.struct_members;
        let constructor_inits = &self.constructor_inits;
        let init_fields = &self.init_fields;
        let struct_implementation = &self.struct_implementation;

        let library_new = if ctx.options().wrap_unsafe_ops {
            quote!(unsafe { ::libloading::Library::new(path) })
        } else {
            quote!(::libloading::Library::new(path))
        };

        let from_library = if ctx.options().wrap_unsafe_ops {
            quote!(unsafe { Self::from_library(library) })
        } else {
            quote!(Self::from_library(library))
        };

        quote! {
            pub struct #lib_ident {
                __library: ::libloading::Library,
                #(#struct_members)*
            }

            impl #lib_ident {
                pub unsafe fn new<P>(
                    path: P
                ) -> Result<Self, ::libloading::Error>
                where P: AsRef<::std::ffi::OsStr> {
                    let library = #library_new?;
                    #from_library
                }

                pub unsafe fn from_library<L>(
                    library: L
                ) -> Result<Self, ::libloading::Error>
                where L: Into<::libloading::Library> {
                    let __library = library.into();
                    #( #constructor_inits )*
                    Ok(#lib_ident {
                        __library,
                        #( #init_fields ),*
                    })
                }

                #( #struct_implementation )*
            }
        }
    }

    #[allow(clippy::too_many_arguments)]
    pub(crate) fn push_func(
        &mut self,
        ident: &Ident,
        symbol: &str,
        abi: ClangAbi,
        is_variadic: bool,
        is_required: bool,
        args: &[TokenStream],
        args_identifiers: &[TokenStream],
        ret: &TokenStream,
        ret_ty: &TokenStream,
        attributes: &[TokenStream],
        ctx: &BindgenContext,
    ) {
        if !is_variadic {
            assert_eq!(args.len(), args_identifiers.len());
        }

        let signature = quote! { unsafe extern #abi fn ( #( #args),* ) #ret };
        let member = if is_required {
            signature
        } else {
            quote! { Result<#signature, ::libloading::Error> }
        };

        self.struct_members.push(quote! {
            pub #ident: #member,
        });

        // N.B: If the signature was required, it won't be wrapped in a Result<...>
        //      and we can simply call it directly.
        let fn_ = if is_required {
            quote! { self.#ident }
        } else {
            quote! { self.#ident.as_ref().expect("Expected function, got error.") }
        };
        let call_body = if ctx.options().wrap_unsafe_ops {
            quote!(unsafe { (#fn_)(#( #args_identifiers ),*) })
        } else {
            quote!((#fn_)(#( #args_identifiers ),*) )
        };

        // We can't implement variadic functions from C easily, so we allow to
        // access the function pointer so that the user can call it just fine.
        if !is_variadic {
            self.struct_implementation.push(quote! {
                #(#attributes)*
                pub unsafe fn #ident ( &self, #( #args ),* ) #ret_ty {
                    #call_body
                }
            });
        }

        // N.B: Unwrap the signature upon construction if it is required to be resolved.
        let symbol_cstr =
            codegen::helpers::ast_ty::cstr_expr(symbol.to_string());
        let library_get = if ctx.options().wrap_unsafe_ops {
            quote!(unsafe { __library.get(#symbol_cstr) })
        } else {
            quote!(__library.get(#symbol_cstr))
        };

        self.constructor_inits.push(if is_required {
            quote! {
                let #ident = #library_get.map(|sym| *sym)?;
            }
        } else {
            quote! {
                let #ident = #library_get.map(|sym| *sym);
            }
        });

        self.init_fields.push(quote! {
            #ident
        });
    }

    pub fn push_var(
        &mut self,
        ident: &Ident,
        symbol: &str,
        ty: &TokenStream,
        is_required: bool,
        wrap_unsafe_ops: bool,
    ) {
        let member = if is_required {
            quote! { *mut #ty }
        } else {
            quote! { Result<*mut #ty, ::libloading::Error> }
        };

        self.struct_members.push(quote! {
            pub #ident: #member,
        });

        let deref = if is_required {
            quote! { self.#ident }
        } else {
            quote! { *self.#ident.as_ref().expect("Expected variable, got error.") }
        };
        self.struct_implementation.push(quote! {
            pub unsafe fn #ident (&self) -> *mut #ty {
                #deref
            }
        });

        let symbol_cstr =
            codegen::helpers::ast_ty::cstr_expr(symbol.to_string());

        let library_get = if wrap_unsafe_ops {
            quote!(unsafe { __library.get::<*mut #ty>(#symbol_cstr) })
        } else {
            quote!(__library.get::<*mut #ty>(#symbol_cstr))
        };

        let qmark = if is_required { quote!(?) } else { quote!() };

        let var_get = quote! {
            let #ident = #library_get.map(|sym| *sym)#qmark;
        };

        self.constructor_inits.push(var_get);

        self.init_fields.push(quote! {
            #ident
        });
    }
}
