//! Objective C types

use super::context::{BindgenContext, ItemId};
use super::function::FunctionSig;
use super::item::Item;
use super::traversal::{Trace, Tracer};
use super::ty::TypeKind;
use crate::clang;
use clang_sys::CXChildVisit_Continue;
use clang_sys::CXCursor_ObjCCategoryDecl;
use clang_sys::CXCursor_ObjCClassMethodDecl;
use clang_sys::CXCursor_ObjCClassRef;
use clang_sys::CXCursor_ObjCInstanceMethodDecl;
use clang_sys::CXCursor_ObjCProtocolDecl;
use clang_sys::CXCursor_ObjCProtocolRef;
use clang_sys::CXCursor_ObjCSuperClassRef;
use clang_sys::CXCursor_TemplateTypeParameter;
use proc_macro2::{Ident, Span, TokenStream};

/// Objective C interface as used in TypeKind
///
/// Also protocols and categories are parsed as this type
#[derive(Debug)]
pub(crate) struct ObjCInterface {
    /// The name
    /// like, NSObject
    name: String,

    category: Option<String>,

    is_protocol: bool,

    /// The list of template names almost always, ObjectType or KeyType
    pub(crate) template_names: Vec<String>,

    /// The list of protocols that this interface conforms to.
    pub(crate) conforms_to: Vec<ItemId>,

    /// The direct parent for this interface.
    pub(crate) parent_class: Option<ItemId>,

    /// List of the methods defined in this interfae
    methods: Vec<ObjCMethod>,

    class_methods: Vec<ObjCMethod>,
}

/// The objective c methods
#[derive(Debug)]
pub(crate) struct ObjCMethod {
    /// The original method selector name
    /// like, dataWithBytes:length:
    name: String,

    /// Method name as converted to rust
    /// like, dataWithBytes_length_
    rust_name: String,

    signature: FunctionSig,

    /// Is class method?
    is_class_method: bool,
}

impl ObjCInterface {
    fn new(name: &str) -> ObjCInterface {
        ObjCInterface {
            name: name.to_owned(),
            category: None,
            is_protocol: false,
            template_names: Vec::new(),
            parent_class: None,
            conforms_to: Vec::new(),
            methods: Vec::new(),
            class_methods: Vec::new(),
        }
    }

    /// The name
    /// like, NSObject
    pub(crate) fn name(&self) -> &str {
        self.name.as_ref()
    }

    /// Formats the name for rust
    /// Can be like NSObject, but with categories might be like NSObject_NSCoderMethods
    /// and protocols are like PNSObject
    pub(crate) fn rust_name(&self) -> String {
        if let Some(ref cat) = self.category {
            format!("{}_{}", self.name(), cat)
        } else if self.is_protocol {
            format!("P{}", self.name())
        } else {
            format!("I{}", self.name().to_owned())
        }
    }

    /// Is this a template interface?
    pub(crate) fn is_template(&self) -> bool {
        !self.template_names.is_empty()
    }

    /// List of the methods defined in this interface
    pub(crate) fn methods(&self) -> &Vec<ObjCMethod> {
        &self.methods
    }

    /// Is this a protocol?
    pub(crate) fn is_protocol(&self) -> bool {
        self.is_protocol
    }

    /// Is this a category?
    pub(crate) fn is_category(&self) -> bool {
        self.category.is_some()
    }

    /// List of the class methods defined in this interface
    pub(crate) fn class_methods(&self) -> &Vec<ObjCMethod> {
        &self.class_methods
    }

    /// Parses the Objective C interface from the cursor
    pub(crate) fn from_ty(
        cursor: &clang::Cursor,
        ctx: &mut BindgenContext,
    ) -> Option<Self> {
        let name = cursor.spelling();
        let mut interface = Self::new(&name);

        if cursor.kind() == CXCursor_ObjCProtocolDecl {
            interface.is_protocol = true;
        }

        cursor.visit(|c| {
            match c.kind() {
                CXCursor_ObjCClassRef => {
                    if cursor.kind() == CXCursor_ObjCCategoryDecl {
                        // We are actually a category extension, and we found the reference
                        // to the original interface, so name this interface approriately
                        interface.name = c.spelling();
                        interface.category = Some(cursor.spelling());
                    }
                }
                CXCursor_ObjCProtocolRef => {
                    // Gather protocols this interface conforms to
                    let needle = format!("P{}", c.spelling());
                    let items_map = ctx.items();
                    debug!(
                        "Interface {} conforms to {}, find the item",
                        interface.name, needle
                    );

                    for (id, item) in items_map {
                        if let Some(ty) = item.as_type() {
                            if let TypeKind::ObjCInterface(ref protocol) =
                                *ty.kind()
                            {
                                if protocol.is_protocol {
                                    debug!(
                                        "Checking protocol {}, ty.name {:?}",
                                        protocol.name,
                                        ty.name()
                                    );
                                    if Some(needle.as_ref()) == ty.name() {
                                        debug!(
                                            "Found conforming protocol {:?}",
                                            item
                                        );
                                        interface.conforms_to.push(id);
                                        break;
                                    }
                                }
                            }
                        }
                    }
                }
                CXCursor_ObjCInstanceMethodDecl |
                CXCursor_ObjCClassMethodDecl => {
                    let name = c.spelling();
                    let signature =
                        FunctionSig::from_ty(&c.cur_type(), &c, ctx)
                            .expect("Invalid function sig");
                    let is_class_method =
                        c.kind() == CXCursor_ObjCClassMethodDecl;
                    let method =
                        ObjCMethod::new(&name, signature, is_class_method);
                    interface.add_method(method);
                }
                CXCursor_TemplateTypeParameter => {
                    let name = c.spelling();
                    interface.template_names.push(name);
                }
                CXCursor_ObjCSuperClassRef => {
                    let item = Item::from_ty_or_ref(c.cur_type(), c, None, ctx);
                    interface.parent_class = Some(item.into());
                }
                _ => {}
            }
            CXChildVisit_Continue
        });
        Some(interface)
    }

    fn add_method(&mut self, method: ObjCMethod) {
        if method.is_class_method {
            self.class_methods.push(method);
        } else {
            self.methods.push(method);
        }
    }
}

impl ObjCMethod {
    fn new(
        name: &str,
        signature: FunctionSig,
        is_class_method: bool,
    ) -> ObjCMethod {
        let split_name: Vec<&str> = name.split(':').collect();

        let rust_name = split_name.join("_");

        ObjCMethod {
            name: name.to_owned(),
            rust_name,
            signature,
            is_class_method,
        }
    }

    /// Method name as converted to rust
    /// like, dataWithBytes_length_
    pub(crate) fn rust_name(&self) -> &str {
        self.rust_name.as_ref()
    }

    /// Returns the methods signature as FunctionSig
    pub(crate) fn signature(&self) -> &FunctionSig {
        &self.signature
    }

    /// Is this a class method?
    pub(crate) fn is_class_method(&self) -> bool {
        self.is_class_method
    }

    /// Formats the method call
    pub(crate) fn format_method_call(
        &self,
        args: &[TokenStream],
    ) -> TokenStream {
        let split_name: Vec<Option<Ident>> = self
            .name
            .split(':')
            .enumerate()
            .map(|(idx, name)| {
                if name.is_empty() {
                    None
                } else if idx == 0 {
                    // Try to parse the method name as an identifier. Having a keyword is ok
                    // unless it is `crate`, `self`, `super` or `Self`, so we try to add the `_`
                    // suffix to it and parse it.
                    if ["crate", "self", "super", "Self"].contains(&name) {
                        Some(Ident::new(
                            &format!("{}_", name),
                            Span::call_site(),
                        ))
                    } else {
                        Some(Ident::new(name, Span::call_site()))
                    }
                } else {
                    // Try to parse the current joining name as an identifier. This might fail if the name
                    // is a keyword, so we try to  "r#" to it and parse again, this could also fail
                    // if the name is `crate`, `self`, `super` or `Self`, so we try to add the `_`
                    // suffix to it and parse again. If this also fails, we panic with the first
                    // error.
                    Some(
                        syn::parse_str::<Ident>(name)
                            .or_else(|err| {
                                syn::parse_str::<Ident>(&format!("r#{}", name))
                                    .map_err(|_| err)
                            })
                            .or_else(|err| {
                                syn::parse_str::<Ident>(&format!("{}_", name))
                                    .map_err(|_| err)
                            })
                            .expect("Invalid identifier"),
                    )
                }
            })
            .collect();

        // No arguments
        if args.is_empty() && split_name.len() == 1 {
            let name = &split_name[0];
            return quote! {
                #name
            };
        }

        // Check right amount of arguments
        assert!(
            args.len() == split_name.len() - 1,
            "Incorrect method name or arguments for objc method, {:?} vs {:?}",
            args,
            split_name
        );

        // Get arguments without type signatures to pass to `msg_send!`
        let mut args_without_types = vec![];
        for arg in args.iter() {
            let arg = arg.to_string();
            let name_and_sig: Vec<&str> = arg.split(' ').collect();
            let name = name_and_sig[0];
            args_without_types.push(Ident::new(name, Span::call_site()))
        }

        let args = split_name.into_iter().zip(args_without_types).map(
            |(arg, arg_val)| {
                if let Some(arg) = arg {
                    quote! { #arg: #arg_val }
                } else {
                    quote! { #arg_val: #arg_val }
                }
            },
        );

        quote! {
            #( #args )*
        }
    }
}

impl Trace for ObjCInterface {
    type Extra = ();

    fn trace<T>(&self, context: &BindgenContext, tracer: &mut T, _: &())
    where
        T: Tracer,
    {
        for method in &self.methods {
            method.signature.trace(context, tracer, &());
        }

        for class_method in &self.class_methods {
            class_method.signature.trace(context, tracer, &());
        }

        for protocol in &self.conforms_to {
            tracer.visit(*protocol);
        }
    }
}
