use crate::ir::comp::{BitfieldUnit, CompKind, Field, FieldData, FieldMethods};
use crate::ir::context::BindgenContext;
use crate::ir::item::{HasTypeParamInArray, IsOpaque, Item, ItemCanonicalName};
use crate::ir::ty::{TypeKind, RUST_DERIVE_IN_ARRAY_LIMIT};
use proc_macro2;

pub fn gen_debug_impl(
    ctx: &BindgenContext,
    fields: &[Field],
    item: &Item,
    kind: CompKind,
) -> proc_macro2::TokenStream {
    let struct_name = item.canonical_name(ctx);
    let mut format_string = format!("{} {{{{ ", struct_name);
    let mut tokens = vec![];

    if item.is_opaque(ctx, &()) {
        format_string.push_str("opaque");
    } else {
        match kind {
            CompKind::Union => {
                format_string.push_str("union");
            }
            CompKind::Struct => {
                let processed_fields = fields.iter().filter_map(|f| match f {
                    &Field::DataMember(ref fd) => fd.impl_debug(ctx, ()),
                    &Field::Bitfields(ref bu) => bu.impl_debug(ctx, ()),
                });

                for (i, (fstring, toks)) in processed_fields.enumerate() {
                    if i > 0 {
                        format_string.push_str(", ");
                    }
                    tokens.extend(toks);
                    format_string.push_str(&fstring);
                }
            }
        }
    }

    format_string.push_str(" }}");
    tokens.insert(0, quote! { #format_string });

    let prefix = ctx.trait_prefix();

    quote! {
        fn fmt(&self, f: &mut ::#prefix::fmt::Formatter<'_>) -> ::#prefix ::fmt::Result {
            write!(f, #( #tokens ),*)
        }
    }
}

/// A trait for the things which we can codegen tokens that contribute towards a
/// generated `impl Debug`.
pub trait ImplDebug<'a> {
    /// Any extra parameter required by this a particular `ImplDebug` implementation.
    type Extra;

    /// Generate a format string snippet to be included in the larger `impl Debug`
    /// format string, and the code to get the format string's interpolation values.
    fn impl_debug(
        &self,
        ctx: &BindgenContext,
        extra: Self::Extra,
    ) -> Option<(String, Vec<proc_macro2::TokenStream>)>;
}

impl<'a> ImplDebug<'a> for FieldData {
    type Extra = ();

    fn impl_debug(
        &self,
        ctx: &BindgenContext,
        _: Self::Extra,
    ) -> Option<(String, Vec<proc_macro2::TokenStream>)> {
        if let Some(name) = self.name() {
            ctx.resolve_item(self.ty()).impl_debug(ctx, name)
        } else {
            None
        }
    }
}

impl<'a> ImplDebug<'a> for BitfieldUnit {
    type Extra = ();

    fn impl_debug(
        &self,
        ctx: &BindgenContext,
        _: Self::Extra,
    ) -> Option<(String, Vec<proc_macro2::TokenStream>)> {
        let mut format_string = String::new();
        let mut tokens = vec![];
        for (i, bitfield) in self.bitfields().iter().enumerate() {
            if i > 0 {
                format_string.push_str(", ");
            }

            if let Some(bitfield_name) = bitfield.name() {
                format_string.push_str(&format!("{} : {{:?}}", bitfield_name));
                let getter_name = bitfield.getter_name();
                let name_ident = ctx.rust_ident_raw(getter_name);
                tokens.push(quote! {
                    self.#name_ident ()
                });
            }
        }

        Some((format_string, tokens))
    }
}

impl<'a> ImplDebug<'a> for Item {
    type Extra = &'a str;

    fn impl_debug(
        &self,
        ctx: &BindgenContext,
        name: &str,
    ) -> Option<(String, Vec<proc_macro2::TokenStream>)> {
        let name_ident = ctx.rust_ident(name);

        // We don't know if blocklisted items `impl Debug` or not, so we can't
        // add them to the format string we're building up.
        if !ctx.allowlisted_items().contains(&self.id()) {
            return None;
        }

        let ty = match self.as_type() {
            Some(ty) => ty,
            None => {
                return None;
            }
        };

        fn debug_print(
            name: &str,
            name_ident: proc_macro2::TokenStream,
        ) -> Option<(String, Vec<proc_macro2::TokenStream>)> {
            Some((
                format!("{}: {{:?}}", name),
                vec![quote! {
                    self.#name_ident
                }],
            ))
        }

        match *ty.kind() {
            // Handle the simple cases.
            TypeKind::Void |
            TypeKind::NullPtr |
            TypeKind::Int(..) |
            TypeKind::Float(..) |
            TypeKind::Complex(..) |
            TypeKind::Function(..) |
            TypeKind::Enum(..) |
            TypeKind::Reference(..) |
            TypeKind::UnresolvedTypeRef(..) |
            TypeKind::ObjCInterface(..) |
            TypeKind::ObjCId |
            TypeKind::Comp(..) |
            TypeKind::ObjCSel => debug_print(name, quote! { #name_ident }),

            TypeKind::TemplateInstantiation(ref inst) => {
                if inst.is_opaque(ctx, self) {
                    Some((format!("{}: opaque", name), vec![]))
                } else {
                    debug_print(name, quote! { #name_ident })
                }
            }

            // The generic is not required to implement Debug, so we can not debug print that type
            TypeKind::TypeParam => {
                Some((format!("{}: Non-debuggable generic", name), vec![]))
            }

            TypeKind::Array(_, len) => {
                // Generics are not required to implement Debug
                if self.has_type_param_in_array(ctx) {
                    Some((
                        format!("{}: Array with length {}", name, len),
                        vec![],
                    ))
                } else if len < RUST_DERIVE_IN_ARRAY_LIMIT ||
                    ctx.options().rust_features().larger_arrays
                {
                    // The simple case
                    debug_print(name, quote! { #name_ident })
                } else {
                    if ctx.options().use_core {
                        // There is no String in core; reducing field visibility to avoid breaking
                        // no_std setups.
                        Some((format!("{}: [...]", name), vec![]))
                    } else {
                        // Let's implement our own print function
                        Some((
                            format!("{}: [{{}}]", name),
                            vec![quote! {
                                self.#name_ident
                                    .iter()
                                    .enumerate()
                                    .map(|(i, v)| format!("{}{:?}", if i > 0 { ", " } else { "" }, v))
                                    .collect::<String>()
                            }],
                        ))
                    }
                }
            }
            TypeKind::Vector(_, len) => {
                if ctx.options().use_core {
                    // There is no format! in core; reducing field visibility to avoid breaking
                    // no_std setups.
                    Some((format!("{}(...)", name), vec![]))
                } else {
                    let self_ids = 0..len;
                    Some((
                        format!("{}({{}})", name),
                        vec![quote! {
                            #(format!("{:?}", self.#self_ids)),*
                        }],
                    ))
                }
            }

            TypeKind::ResolvedTypeRef(t) |
            TypeKind::TemplateAlias(t, _) |
            TypeKind::Alias(t) |
            TypeKind::BlockPointer(t) => {
                // We follow the aliases
                ctx.resolve_item(t).impl_debug(ctx, name)
            }

            TypeKind::Pointer(inner) => {
                let inner_type = ctx.resolve_type(inner).canonical_type(ctx);
                match *inner_type.kind() {
                    TypeKind::Function(ref sig)
                        if !sig.function_pointers_can_derive() =>
                    {
                        Some((format!("{}: FunctionPointer", name), vec![]))
                    }
                    _ => debug_print(name, quote! { #name_ident }),
                }
            }

            TypeKind::Opaque => None,
        }
    }
}
