use crate::syntax::attrs::OtherAttrs;
use crate::syntax::discriminant::DiscriminantSet;
use crate::syntax::file::{Item, ItemForeignMod};
use crate::syntax::report::Errors;
use crate::syntax::Atom::*;
use crate::syntax::{
    attrs, error, Api, Array, Derive, Doc, Enum, EnumRepr, ExternFn, ExternType, ForeignName, Impl,
    Include, IncludeKind, Lang, Lifetimes, NamedType, Namespace, Pair, Ptr, Receiver, Ref,
    Signature, SliceRef, Struct, Ty1, Type, TypeAlias, Var, Variant,
};
use proc_macro2::{Delimiter, Group, Span, TokenStream, TokenTree};
use quote::{format_ident, quote, quote_spanned};
use std::mem;
use syn::parse::{ParseStream, Parser};
use syn::punctuated::Punctuated;
use syn::{
    Abi, Attribute, Error, Expr, Fields, FnArg, ForeignItem, ForeignItemFn, ForeignItemType,
    GenericArgument, GenericParam, Generics, Ident, ItemEnum, ItemImpl, ItemStruct, Lit, LitStr,
    Pat, PathArguments, Result, ReturnType, Signature as RustSignature, Token, TraitBound,
    TraitBoundModifier, Type as RustType, TypeArray, TypeBareFn, TypeParamBound, TypePath, TypePtr,
    TypeReference, Variant as RustVariant, Visibility,
};

pub mod kw {
    syn::custom_keyword!(Pin);
    syn::custom_keyword!(Result);
}

pub fn parse_items(
    cx: &mut Errors,
    items: Vec<Item>,
    trusted: bool,
    namespace: &Namespace,
) -> Vec<Api> {
    let mut apis = Vec::new();
    for item in items {
        match item {
            Item::Struct(item) => match parse_struct(cx, item, namespace) {
                Ok(strct) => apis.push(strct),
                Err(err) => cx.push(err),
            },
            Item::Enum(item) => apis.push(parse_enum(cx, item, namespace)),
            Item::ForeignMod(foreign_mod) => {
                parse_foreign_mod(cx, foreign_mod, &mut apis, trusted, namespace)
            }
            Item::Impl(item) => match parse_impl(item) {
                Ok(imp) => apis.push(imp),
                Err(err) => cx.push(err),
            },
            Item::Use(item) => cx.error(item, error::USE_NOT_ALLOWED),
            Item::Other(item) => cx.error(item, "unsupported item"),
        }
    }
    apis
}

fn parse_struct(cx: &mut Errors, mut item: ItemStruct, namespace: &Namespace) -> Result<Api> {
    let mut doc = Doc::new();
    let mut derives = Vec::new();
    let mut namespace = namespace.clone();
    let mut cxx_name = None;
    let mut rust_name = None;
    let attrs = attrs::parse(
        cx,
        mem::take(&mut item.attrs),
        attrs::Parser {
            doc: Some(&mut doc),
            derives: Some(&mut derives),
            namespace: Some(&mut namespace),
            cxx_name: Some(&mut cxx_name),
            rust_name: Some(&mut rust_name),
            ..Default::default()
        },
    );

    let named_fields = match item.fields {
        Fields::Named(fields) => fields,
        Fields::Unit => return Err(Error::new_spanned(item, "unit structs are not supported")),
        Fields::Unnamed(_) => {
            return Err(Error::new_spanned(item, "tuple structs are not supported"));
        }
    };

    let mut lifetimes = Punctuated::new();
    let mut has_unsupported_generic_param = false;
    for pair in item.generics.params.into_pairs() {
        let (param, punct) = pair.into_tuple();
        match param {
            GenericParam::Lifetime(param) => {
                if !param.bounds.is_empty() && !has_unsupported_generic_param {
                    let msg = "lifetime parameter with bounds is not supported yet";
                    cx.error(&param, msg);
                    has_unsupported_generic_param = true;
                }
                lifetimes.push_value(param.lifetime);
                if let Some(punct) = punct {
                    lifetimes.push_punct(punct);
                }
            }
            GenericParam::Type(param) => {
                if !has_unsupported_generic_param {
                    let msg = "struct with generic type parameter is not supported yet";
                    cx.error(&param, msg);
                    has_unsupported_generic_param = true;
                }
            }
            GenericParam::Const(param) => {
                if !has_unsupported_generic_param {
                    let msg = "struct with const generic parameter is not supported yet";
                    cx.error(&param, msg);
                    has_unsupported_generic_param = true;
                }
            }
        }
    }

    if let Some(where_clause) = &item.generics.where_clause {
        cx.error(
            where_clause,
            "struct with where-clause is not supported yet",
        );
    }

    let mut fields = Vec::new();
    for field in named_fields.named {
        let ident = field.ident.unwrap();
        let mut doc = Doc::new();
        let mut cxx_name = None;
        let mut rust_name = None;
        let attrs = attrs::parse(
            cx,
            field.attrs,
            attrs::Parser {
                doc: Some(&mut doc),
                cxx_name: Some(&mut cxx_name),
                rust_name: Some(&mut rust_name),
                ..Default::default()
            },
        );
        let ty = match parse_type(&field.ty) {
            Ok(ty) => ty,
            Err(err) => {
                cx.push(err);
                continue;
            }
        };
        let visibility = visibility_pub(&field.vis, ident.span());
        let name = pair(Namespace::default(), &ident, cxx_name, rust_name);
        let colon_token = field.colon_token.unwrap();
        fields.push(Var {
            doc,
            attrs,
            visibility,
            name,
            colon_token,
            ty,
        });
    }

    let struct_token = item.struct_token;
    let visibility = visibility_pub(&item.vis, struct_token.span);
    let name = pair(namespace, &item.ident, cxx_name, rust_name);
    let generics = Lifetimes {
        lt_token: item.generics.lt_token,
        lifetimes,
        gt_token: item.generics.gt_token,
    };
    let brace_token = named_fields.brace_token;

    Ok(Api::Struct(Struct {
        doc,
        derives,
        attrs,
        visibility,
        struct_token,
        name,
        generics,
        brace_token,
        fields,
    }))
}

fn parse_enum(cx: &mut Errors, item: ItemEnum, namespace: &Namespace) -> Api {
    let mut doc = Doc::new();
    let mut derives = Vec::new();
    let mut repr = None;
    let mut namespace = namespace.clone();
    let mut cxx_name = None;
    let mut rust_name = None;
    let mut variants_from_header = None;
    let attrs = attrs::parse(
        cx,
        item.attrs,
        attrs::Parser {
            doc: Some(&mut doc),
            derives: Some(&mut derives),
            repr: Some(&mut repr),
            namespace: Some(&mut namespace),
            cxx_name: Some(&mut cxx_name),
            rust_name: Some(&mut rust_name),
            variants_from_header: Some(&mut variants_from_header),
            ..Default::default()
        },
    );

    if !item.generics.params.is_empty() {
        let vis = &item.vis;
        let enum_token = item.enum_token;
        let ident = &item.ident;
        let generics = &item.generics;
        let span = quote!(#vis #enum_token #ident #generics);
        cx.error(span, "enum with generic parameters is not supported");
    } else if let Some(where_clause) = &item.generics.where_clause {
        cx.error(where_clause, "enum with where-clause is not supported");
    }

    let mut variants = Vec::new();
    let mut discriminants = DiscriminantSet::new(repr);
    for variant in item.variants {
        match parse_variant(cx, variant, &mut discriminants) {
            Ok(variant) => variants.push(variant),
            Err(err) => cx.push(err),
        }
    }

    let enum_token = item.enum_token;
    let visibility = visibility_pub(&item.vis, enum_token.span);
    let brace_token = item.brace_token;

    let explicit_repr = repr.is_some();
    let mut repr = U8;
    match discriminants.inferred_repr() {
        Ok(inferred) => repr = inferred,
        Err(err) => {
            let span = quote_spanned!(brace_token.span=> #enum_token {});
            cx.error(span, err);
            variants.clear();
        }
    }

    let name = pair(namespace, &item.ident, cxx_name, rust_name);
    let repr_ident = Ident::new(repr.as_ref(), Span::call_site());
    let repr_type = Type::Ident(NamedType::new(repr_ident));
    let repr = EnumRepr::Native {
        atom: repr,
        repr_type,
    };
    let generics = Lifetimes {
        lt_token: None,
        lifetimes: Punctuated::new(),
        gt_token: None,
    };
    let variants_from_header_attr = variants_from_header;
    let variants_from_header = variants_from_header_attr.is_some();

    Api::Enum(Enum {
        doc,
        derives,
        attrs,
        visibility,
        enum_token,
        name,
        generics,
        brace_token,
        variants,
        variants_from_header,
        variants_from_header_attr,
        repr,
        explicit_repr,
    })
}

fn parse_variant(
    cx: &mut Errors,
    mut variant: RustVariant,
    discriminants: &mut DiscriminantSet,
) -> Result<Variant> {
    let mut doc = Doc::new();
    let mut cxx_name = None;
    let mut rust_name = None;
    let attrs = attrs::parse(
        cx,
        mem::take(&mut variant.attrs),
        attrs::Parser {
            doc: Some(&mut doc),
            cxx_name: Some(&mut cxx_name),
            rust_name: Some(&mut rust_name),
            ..Default::default()
        },
    );

    match variant.fields {
        Fields::Unit => {}
        _ => {
            let msg = "enums with data are not supported yet";
            return Err(Error::new_spanned(variant, msg));
        }
    }

    let expr = variant.discriminant.as_ref().map(|(_, expr)| expr);
    let try_discriminant = match &expr {
        Some(lit) => discriminants.insert(lit),
        None => discriminants.insert_next(),
    };
    let discriminant = match try_discriminant {
        Ok(discriminant) => discriminant,
        Err(err) => return Err(Error::new_spanned(variant, err)),
    };

    let name = pair(Namespace::ROOT, &variant.ident, cxx_name, rust_name);
    let expr = variant.discriminant.map(|(_, expr)| expr);

    Ok(Variant {
        doc,
        attrs,
        name,
        discriminant,
        expr,
    })
}

fn parse_foreign_mod(
    cx: &mut Errors,
    foreign_mod: ItemForeignMod,
    out: &mut Vec<Api>,
    trusted: bool,
    namespace: &Namespace,
) {
    let lang = match parse_lang(&foreign_mod.abi) {
        Ok(lang) => lang,
        Err(err) => return cx.push(err),
    };

    match lang {
        Lang::Rust => {
            if foreign_mod.unsafety.is_some() {
                let unsafety = foreign_mod.unsafety;
                let abi = &foreign_mod.abi;
                let span = quote!(#unsafety #abi);
                cx.error(span, "extern \"Rust\" block does not need to be unsafe");
            }
        }
        Lang::Cxx => {}
    }

    let trusted = trusted || foreign_mod.unsafety.is_some();

    let mut namespace = namespace.clone();
    attrs::parse(
        cx,
        foreign_mod.attrs,
        attrs::Parser {
            namespace: Some(&mut namespace),
            ..Default::default()
        },
    );

    let mut items = Vec::new();
    for foreign in foreign_mod.items {
        match foreign {
            ForeignItem::Type(foreign) => {
                let ety = parse_extern_type(cx, foreign, lang, trusted, &namespace);
                items.push(ety);
            }
            ForeignItem::Fn(foreign) => {
                match parse_extern_fn(cx, foreign, lang, trusted, &namespace) {
                    Ok(efn) => items.push(efn),
                    Err(err) => cx.push(err),
                }
            }
            ForeignItem::Macro(foreign) if foreign.mac.path.is_ident("include") => {
                match foreign.mac.parse_body_with(parse_include) {
                    Ok(include) => items.push(Api::Include(include)),
                    Err(err) => cx.push(err),
                }
            }
            ForeignItem::Verbatim(tokens) => {
                match parse_extern_verbatim(cx, tokens, lang, trusted, &namespace) {
                    Ok(api) => items.push(api),
                    Err(err) => cx.push(err),
                }
            }
            _ => cx.error(foreign, "unsupported foreign item"),
        }
    }

    if !trusted
        && items.iter().any(|api| match api {
            Api::CxxFunction(efn) => efn.unsafety.is_none(),
            _ => false,
        })
    {
        cx.error(
            foreign_mod.abi,
            "block must be declared `unsafe extern \"C++\"` if it contains any safe-to-call C++ functions",
        );
    }

    let mut types = items.iter().filter_map(|item| match item {
        Api::CxxType(ety) | Api::RustType(ety) => Some(&ety.name),
        Api::TypeAlias(alias) => Some(&alias.name),
        _ => None,
    });
    if let (Some(single_type), None) = (types.next(), types.next()) {
        let single_type = single_type.clone();
        for item in &mut items {
            if let Api::CxxFunction(efn) | Api::RustFunction(efn) = item {
                if let Some(receiver) = &mut efn.receiver {
                    if receiver.ty.rust == "Self" {
                        receiver.ty.rust = single_type.rust.clone();
                    }
                }
            }
        }
    }

    out.extend(items);
}

fn parse_lang(abi: &Abi) -> Result<Lang> {
    let name = match &abi.name {
        Some(name) => name,
        None => {
            return Err(Error::new_spanned(
                abi,
                "ABI name is required, extern \"C++\" or extern \"Rust\"",
            ));
        }
    };

    match name.value().as_str() {
        "C++" => Ok(Lang::Cxx),
        "Rust" => Ok(Lang::Rust),
        _ => Err(Error::new_spanned(
            abi,
            "unrecognized ABI, requires either \"C++\" or \"Rust\"",
        )),
    }
}

fn parse_extern_type(
    cx: &mut Errors,
    foreign_type: ForeignItemType,
    lang: Lang,
    trusted: bool,
    namespace: &Namespace,
) -> Api {
    let mut doc = Doc::new();
    let mut derives = Vec::new();
    let mut namespace = namespace.clone();
    let mut cxx_name = None;
    let mut rust_name = None;
    let attrs = attrs::parse(
        cx,
        foreign_type.attrs,
        attrs::Parser {
            doc: Some(&mut doc),
            derives: Some(&mut derives),
            namespace: Some(&mut namespace),
            cxx_name: Some(&mut cxx_name),
            rust_name: Some(&mut rust_name),
            ..Default::default()
        },
    );

    let type_token = foreign_type.type_token;
    let visibility = visibility_pub(&foreign_type.vis, type_token.span);
    let name = pair(namespace, &foreign_type.ident, cxx_name, rust_name);
    let generics = Lifetimes {
        lt_token: None,
        lifetimes: Punctuated::new(),
        gt_token: None,
    };
    let colon_token = None;
    let bounds = Vec::new();
    let semi_token = foreign_type.semi_token;

    (match lang {
        Lang::Cxx => Api::CxxType,
        Lang::Rust => Api::RustType,
    })(ExternType {
        lang,
        doc,
        derives,
        attrs,
        visibility,
        type_token,
        name,
        generics,
        colon_token,
        bounds,
        semi_token,
        trusted,
    })
}

fn parse_extern_fn(
    cx: &mut Errors,
    mut foreign_fn: ForeignItemFn,
    lang: Lang,
    trusted: bool,
    namespace: &Namespace,
) -> Result<Api> {
    let mut doc = Doc::new();
    let mut namespace = namespace.clone();
    let mut cxx_name = None;
    let mut rust_name = None;
    let attrs = attrs::parse(
        cx,
        mem::take(&mut foreign_fn.attrs),
        attrs::Parser {
            doc: Some(&mut doc),
            namespace: Some(&mut namespace),
            cxx_name: Some(&mut cxx_name),
            rust_name: Some(&mut rust_name),
            ..Default::default()
        },
    );

    let generics = &foreign_fn.sig.generics;
    if generics.where_clause.is_some()
        || generics.params.iter().any(|param| match param {
            GenericParam::Lifetime(lifetime) => !lifetime.bounds.is_empty(),
            GenericParam::Type(_) | GenericParam::Const(_) => true,
        })
    {
        return Err(Error::new_spanned(
            foreign_fn,
            "extern function with generic parameters is not supported yet",
        ));
    }

    if let Some(variadic) = &foreign_fn.sig.variadic {
        return Err(Error::new_spanned(
            variadic,
            "variadic function is not supported yet",
        ));
    }

    if foreign_fn.sig.asyncness.is_some() {
        return Err(Error::new_spanned(
            foreign_fn,
            "async function is not directly supported yet, but see https://cxx.rs/async.html for a working approach",
        ));
    }

    if foreign_fn.sig.constness.is_some() {
        return Err(Error::new_spanned(
            foreign_fn,
            "const extern function is not supported",
        ));
    }

    if let Some(abi) = &foreign_fn.sig.abi {
        return Err(Error::new_spanned(
            abi,
            "explicit ABI on extern function is not supported",
        ));
    }

    let mut receiver = None;
    let mut args = Punctuated::new();
    for arg in foreign_fn.sig.inputs.pairs() {
        let (arg, comma) = arg.into_tuple();
        match arg {
            FnArg::Receiver(arg) => {
                if let Some((ampersand, lifetime)) = &arg.reference {
                    receiver = Some(Receiver {
                        pinned: false,
                        ampersand: *ampersand,
                        lifetime: lifetime.clone(),
                        mutable: arg.mutability.is_some(),
                        var: arg.self_token,
                        colon_token: Token![:](arg.self_token.span),
                        ty: NamedType::new(Ident::new("Self", arg.self_token.span)),
                        shorthand: true,
                        pin_tokens: None,
                        mutability: arg.mutability,
                    });
                    continue;
                }
                return Err(Error::new_spanned(arg, "unsupported signature"));
            }
            FnArg::Typed(arg) => {
                let ident = match arg.pat.as_ref() {
                    Pat::Ident(pat) => pat.ident.clone(),
                    Pat::Wild(pat) => {
                        Ident::new(&format!("arg{}", args.len()), pat.underscore_token.span)
                    }
                    _ => return Err(Error::new_spanned(arg, "unsupported signature")),
                };
                let ty = parse_type(&arg.ty)?;
                if ident != "self" {
                    let doc = Doc::new();
                    let attrs = OtherAttrs::none();
                    let visibility = Token![pub](ident.span());
                    let name = pair(Namespace::default(), &ident, None, None);
                    let colon_token = arg.colon_token;
                    args.push_value(Var {
                        doc,
                        attrs,
                        visibility,
                        name,
                        colon_token,
                        ty,
                    });
                    if let Some(comma) = comma {
                        args.push_punct(*comma);
                    }
                    continue;
                }
                if let Type::Ref(reference) = ty {
                    if let Type::Ident(ident) = reference.inner {
                        receiver = Some(Receiver {
                            pinned: reference.pinned,
                            ampersand: reference.ampersand,
                            lifetime: reference.lifetime,
                            mutable: reference.mutable,
                            var: Token![self](ident.rust.span()),
                            colon_token: arg.colon_token,
                            ty: ident,
                            shorthand: false,
                            pin_tokens: reference.pin_tokens,
                            mutability: reference.mutability,
                        });
                        continue;
                    }
                }
                return Err(Error::new_spanned(arg, "unsupported method receiver"));
            }
        }
    }

    let mut throws_tokens = None;
    let ret = parse_return_type(&foreign_fn.sig.output, &mut throws_tokens)?;
    let throws = throws_tokens.is_some();
    let unsafety = foreign_fn.sig.unsafety;
    let fn_token = foreign_fn.sig.fn_token;
    let inherited_span = unsafety.map_or(fn_token.span, |unsafety| unsafety.span);
    let visibility = visibility_pub(&foreign_fn.vis, inherited_span);
    let name = pair(namespace, &foreign_fn.sig.ident, cxx_name, rust_name);
    let generics = generics.clone();
    let paren_token = foreign_fn.sig.paren_token;
    let semi_token = foreign_fn.semi_token;

    Ok(match lang {
        Lang::Cxx => Api::CxxFunction,
        Lang::Rust => Api::RustFunction,
    }(ExternFn {
        lang,
        doc,
        attrs,
        visibility,
        name,
        sig: Signature {
            unsafety,
            fn_token,
            generics,
            receiver,
            args,
            ret,
            throws,
            paren_token,
            throws_tokens,
        },
        semi_token,
        trusted,
    }))
}

fn parse_extern_verbatim(
    cx: &mut Errors,
    tokens: TokenStream,
    lang: Lang,
    trusted: bool,
    namespace: &Namespace,
) -> Result<Api> {
    |input: ParseStream| -> Result<Api> {
        let attrs = input.call(Attribute::parse_outer)?;
        let visibility: Visibility = input.parse()?;
        if input.peek(Token![type]) {
            parse_extern_verbatim_type(cx, attrs, visibility, input, lang, trusted, namespace)
        } else if input.peek(Token![fn]) {
            parse_extern_verbatim_fn(input)
        } else {
            let span = input.cursor().token_stream();
            Err(Error::new_spanned(
                span,
                "unsupported foreign item, expected `type` or `fn`",
            ))
        }
    }
    .parse2(tokens)
}

fn parse_extern_verbatim_type(
    cx: &mut Errors,
    attrs: Vec<Attribute>,
    visibility: Visibility,
    input: ParseStream,
    lang: Lang,
    trusted: bool,
    namespace: &Namespace,
) -> Result<Api> {
    let type_token: Token![type] = input.parse()?;
    let ident: Ident = input.parse()?;
    let generics: Generics = input.parse()?;
    let mut lifetimes = Punctuated::new();
    let mut has_unsupported_generic_param = false;
    for pair in generics.params.into_pairs() {
        let (param, punct) = pair.into_tuple();
        match param {
            GenericParam::Lifetime(param) => {
                if !param.bounds.is_empty() && !has_unsupported_generic_param {
                    let msg = "lifetime parameter with bounds is not supported yet";
                    cx.error(&param, msg);
                    has_unsupported_generic_param = true;
                }
                lifetimes.push_value(param.lifetime);
                if let Some(punct) = punct {
                    lifetimes.push_punct(punct);
                }
            }
            GenericParam::Type(param) => {
                if !has_unsupported_generic_param {
                    let msg = "extern type with generic type parameter is not supported yet";
                    cx.error(&param, msg);
                    has_unsupported_generic_param = true;
                }
            }
            GenericParam::Const(param) => {
                if !has_unsupported_generic_param {
                    let msg = "extern type with const generic parameter is not supported yet";
                    cx.error(&param, msg);
                    has_unsupported_generic_param = true;
                }
            }
        }
    }
    let lifetimes = Lifetimes {
        lt_token: generics.lt_token,
        lifetimes,
        gt_token: generics.gt_token,
    };
    let lookahead = input.lookahead1();
    if lookahead.peek(Token![=]) {
        // type Alias = crate::path::to::Type;
        parse_type_alias(
            cx, attrs, visibility, type_token, ident, lifetimes, input, lang, namespace,
        )
    } else if lookahead.peek(Token![:]) || lookahead.peek(Token![;]) {
        // type Opaque: Bound2 + Bound2;
        parse_extern_type_bounded(
            cx, attrs, visibility, type_token, ident, lifetimes, input, lang, trusted, namespace,
        )
    } else {
        Err(lookahead.error())
    }
}

fn parse_extern_verbatim_fn(input: ParseStream) -> Result<Api> {
    input.parse::<RustSignature>()?;
    input.parse::<Token![;]>()?;
    unreachable!()
}

fn parse_type_alias(
    cx: &mut Errors,
    attrs: Vec<Attribute>,
    visibility: Visibility,
    type_token: Token![type],
    ident: Ident,
    generics: Lifetimes,
    input: ParseStream,
    lang: Lang,
    namespace: &Namespace,
) -> Result<Api> {
    let eq_token: Token![=] = input.parse()?;
    let ty: RustType = input.parse()?;
    let semi_token: Token![;] = input.parse()?;

    let mut doc = Doc::new();
    let mut derives = Vec::new();
    let mut namespace = namespace.clone();
    let mut cxx_name = None;
    let mut rust_name = None;
    let attrs = attrs::parse(
        cx,
        attrs,
        attrs::Parser {
            doc: Some(&mut doc),
            derives: Some(&mut derives),
            namespace: Some(&mut namespace),
            cxx_name: Some(&mut cxx_name),
            rust_name: Some(&mut rust_name),
            ..Default::default()
        },
    );

    if lang == Lang::Rust {
        let span = quote!(#type_token #semi_token);
        let msg = "type alias in extern \"Rust\" block is not supported";
        return Err(Error::new_spanned(span, msg));
    }

    let visibility = visibility_pub(&visibility, type_token.span);
    let name = pair(namespace, &ident, cxx_name, rust_name);

    Ok(Api::TypeAlias(TypeAlias {
        doc,
        derives,
        attrs,
        visibility,
        type_token,
        name,
        generics,
        eq_token,
        ty,
        semi_token,
    }))
}

fn parse_extern_type_bounded(
    cx: &mut Errors,
    attrs: Vec<Attribute>,
    visibility: Visibility,
    type_token: Token![type],
    ident: Ident,
    generics: Lifetimes,
    input: ParseStream,
    lang: Lang,
    trusted: bool,
    namespace: &Namespace,
) -> Result<Api> {
    let mut bounds = Vec::new();
    let colon_token: Option<Token![:]> = input.parse()?;
    if colon_token.is_some() {
        loop {
            match input.parse()? {
                TypeParamBound::Trait(TraitBound {
                    paren_token: None,
                    modifier: TraitBoundModifier::None,
                    lifetimes: None,
                    path,
                }) if if let Some(derive) = path.get_ident().and_then(Derive::from) {
                    bounds.push(derive);
                    true
                } else {
                    false
                } => {}
                bound @ TypeParamBound::Trait(_) | bound @ TypeParamBound::Lifetime(_) => {
                    cx.error(bound, "unsupported trait");
                }
            }

            let lookahead = input.lookahead1();
            if lookahead.peek(Token![+]) {
                input.parse::<Token![+]>()?;
            } else if lookahead.peek(Token![;]) {
                break;
            } else {
                return Err(lookahead.error());
            }
        }
    }
    let semi_token: Token![;] = input.parse()?;

    let mut doc = Doc::new();
    let mut derives = Vec::new();
    let mut namespace = namespace.clone();
    let mut cxx_name = None;
    let mut rust_name = None;
    let attrs = attrs::parse(
        cx,
        attrs,
        attrs::Parser {
            doc: Some(&mut doc),
            derives: Some(&mut derives),
            namespace: Some(&mut namespace),
            cxx_name: Some(&mut cxx_name),
            rust_name: Some(&mut rust_name),
            ..Default::default()
        },
    );

    let visibility = visibility_pub(&visibility, type_token.span);
    let name = pair(namespace, &ident, cxx_name, rust_name);

    Ok(match lang {
        Lang::Cxx => Api::CxxType,
        Lang::Rust => Api::RustType,
    }(ExternType {
        lang,
        doc,
        derives,
        attrs,
        visibility,
        type_token,
        name,
        generics,
        colon_token,
        bounds,
        semi_token,
        trusted,
    }))
}

fn parse_impl(imp: ItemImpl) -> Result<Api> {
    let impl_token = imp.impl_token;

    if !imp.items.is_empty() {
        let mut span = Group::new(Delimiter::Brace, TokenStream::new());
        span.set_span(imp.brace_token.span);
        return Err(Error::new_spanned(span, "expected an empty impl block"));
    }

    if let Some((bang, path, for_token)) = &imp.trait_ {
        let self_ty = &imp.self_ty;
        let span = quote!(#bang #path #for_token #self_ty);
        return Err(Error::new_spanned(
            span,
            "unexpected impl, expected something like `impl UniquePtr<T> {}`",
        ));
    }

    if let Some(where_clause) = imp.generics.where_clause {
        return Err(Error::new_spanned(
            where_clause,
            "where-clause on an impl is not supported yet",
        ));
    }
    let mut impl_generics = Lifetimes {
        lt_token: imp.generics.lt_token,
        lifetimes: Punctuated::new(),
        gt_token: imp.generics.gt_token,
    };
    for pair in imp.generics.params.into_pairs() {
        let (param, punct) = pair.into_tuple();
        match param {
            GenericParam::Lifetime(def) if def.bounds.is_empty() => {
                impl_generics.lifetimes.push_value(def.lifetime);
                if let Some(punct) = punct {
                    impl_generics.lifetimes.push_punct(punct);
                }
            }
            _ => {
                let span = quote!(#impl_token #impl_generics);
                return Err(Error::new_spanned(
                    span,
                    "generic parameter on an impl is not supported yet",
                ));
            }
        }
    }

    let mut negative_token = None;
    let mut self_ty = *imp.self_ty;
    if let RustType::Verbatim(ty) = &self_ty {
        let mut iter = ty.clone().into_iter();
        if let Some(TokenTree::Punct(punct)) = iter.next() {
            if punct.as_char() == '!' {
                let ty = iter.collect::<TokenStream>();
                if !ty.is_empty() {
                    negative_token = Some(Token![!](punct.span()));
                    self_ty = syn::parse2(ty)?;
                }
            }
        }
    }

    let ty = parse_type(&self_ty)?;
    let ty_generics = match &ty {
        Type::RustBox(ty)
        | Type::RustVec(ty)
        | Type::UniquePtr(ty)
        | Type::SharedPtr(ty)
        | Type::WeakPtr(ty)
        | Type::CxxVector(ty) => match &ty.inner {
            Type::Ident(ident) => ident.generics.clone(),
            _ => Lifetimes::default(),
        },
        Type::Ident(_)
        | Type::Ref(_)
        | Type::Ptr(_)
        | Type::Str(_)
        | Type::Fn(_)
        | Type::Void(_)
        | Type::SliceRef(_)
        | Type::Array(_) => Lifetimes::default(),
    };

    let negative = negative_token.is_some();
    let brace_token = imp.brace_token;

    Ok(Api::Impl(Impl {
        impl_token,
        impl_generics,
        negative,
        ty,
        ty_generics,
        brace_token,
        negative_token,
    }))
}

fn parse_include(input: ParseStream) -> Result<Include> {
    if input.peek(LitStr) {
        let lit: LitStr = input.parse()?;
        let span = lit.span();
        return Ok(Include {
            path: lit.value(),
            kind: IncludeKind::Quoted,
            begin_span: span,
            end_span: span,
        });
    }

    if input.peek(Token![<]) {
        let mut path = String::new();

        let langle: Token![<] = input.parse()?;
        while !input.is_empty() && !input.peek(Token![>]) {
            let token: TokenTree = input.parse()?;
            match token {
                TokenTree::Ident(token) => path += &token.to_string(),
                TokenTree::Literal(token)
                    if token
                        .to_string()
                        .starts_with(|ch: char| ch.is_ascii_digit()) =>
                {
                    path += &token.to_string();
                }
                TokenTree::Punct(token) => path.push(token.as_char()),
                _ => return Err(Error::new(token.span(), "unexpected token in include path")),
            }
        }
        let rangle: Token![>] = input.parse()?;

        return Ok(Include {
            path,
            kind: IncludeKind::Bracketed,
            begin_span: langle.span,
            end_span: rangle.span,
        });
    }

    Err(input.error("expected \"quoted/path/to\" or <bracketed/path/to>"))
}

fn parse_type(ty: &RustType) -> Result<Type> {
    match ty {
        RustType::Reference(ty) => parse_type_reference(ty),
        RustType::Ptr(ty) => parse_type_ptr(ty),
        RustType::Path(ty) => parse_type_path(ty),
        RustType::Array(ty) => parse_type_array(ty),
        RustType::BareFn(ty) => parse_type_fn(ty),
        RustType::Tuple(ty) if ty.elems.is_empty() => Ok(Type::Void(ty.paren_token.span)),
        _ => Err(Error::new_spanned(ty, "unsupported type")),
    }
}

fn parse_type_reference(ty: &TypeReference) -> Result<Type> {
    let ampersand = ty.and_token;
    let lifetime = ty.lifetime.clone();
    let mutable = ty.mutability.is_some();
    let mutability = ty.mutability;

    if let RustType::Slice(slice) = ty.elem.as_ref() {
        let inner = parse_type(&slice.elem)?;
        let bracket = slice.bracket_token;
        return Ok(Type::SliceRef(Box::new(SliceRef {
            ampersand,
            lifetime,
            mutable,
            bracket,
            inner,
            mutability,
        })));
    }

    let inner = parse_type(&ty.elem)?;
    let pinned = false;
    let pin_tokens = None;

    Ok(match &inner {
        Type::Ident(ident) if ident.rust == "str" => {
            if ty.mutability.is_some() {
                return Err(Error::new_spanned(ty, "unsupported type"));
            } else {
                Type::Str
            }
        }
        _ => Type::Ref,
    }(Box::new(Ref {
        pinned,
        ampersand,
        lifetime,
        mutable,
        inner,
        pin_tokens,
        mutability,
    })))
}

fn parse_type_ptr(ty: &TypePtr) -> Result<Type> {
    let star = ty.star_token;
    let mutable = ty.mutability.is_some();
    let constness = ty.const_token;
    let mutability = ty.mutability;

    let inner = parse_type(&ty.elem)?;

    Ok(Type::Ptr(Box::new(Ptr {
        star,
        mutable,
        inner,
        mutability,
        constness,
    })))
}

fn parse_type_path(ty: &TypePath) -> Result<Type> {
    let path = &ty.path;
    if ty.qself.is_none() && path.leading_colon.is_none() && path.segments.len() == 1 {
        let segment = &path.segments[0];
        let ident = segment.ident.clone();
        match &segment.arguments {
            PathArguments::None => return Ok(Type::Ident(NamedType::new(ident))),
            PathArguments::AngleBracketed(generic) => {
                if ident == "UniquePtr" && generic.args.len() == 1 {
                    if let GenericArgument::Type(arg) = &generic.args[0] {
                        let inner = parse_type(arg)?;
                        return Ok(Type::UniquePtr(Box::new(Ty1 {
                            name: ident,
                            langle: generic.lt_token,
                            inner,
                            rangle: generic.gt_token,
                        })));
                    }
                } else if ident == "SharedPtr" && generic.args.len() == 1 {
                    if let GenericArgument::Type(arg) = &generic.args[0] {
                        let inner = parse_type(arg)?;
                        return Ok(Type::SharedPtr(Box::new(Ty1 {
                            name: ident,
                            langle: generic.lt_token,
                            inner,
                            rangle: generic.gt_token,
                        })));
                    }
                } else if ident == "WeakPtr" && generic.args.len() == 1 {
                    if let GenericArgument::Type(arg) = &generic.args[0] {
                        let inner = parse_type(arg)?;
                        return Ok(Type::WeakPtr(Box::new(Ty1 {
                            name: ident,
                            langle: generic.lt_token,
                            inner,
                            rangle: generic.gt_token,
                        })));
                    }
                } else if ident == "CxxVector" && generic.args.len() == 1 {
                    if let GenericArgument::Type(arg) = &generic.args[0] {
                        let inner = parse_type(arg)?;
                        return Ok(Type::CxxVector(Box::new(Ty1 {
                            name: ident,
                            langle: generic.lt_token,
                            inner,
                            rangle: generic.gt_token,
                        })));
                    }
                } else if ident == "Box" && generic.args.len() == 1 {
                    if let GenericArgument::Type(arg) = &generic.args[0] {
                        let inner = parse_type(arg)?;
                        return Ok(Type::RustBox(Box::new(Ty1 {
                            name: ident,
                            langle: generic.lt_token,
                            inner,
                            rangle: generic.gt_token,
                        })));
                    }
                } else if ident == "Vec" && generic.args.len() == 1 {
                    if let GenericArgument::Type(arg) = &generic.args[0] {
                        let inner = parse_type(arg)?;
                        return Ok(Type::RustVec(Box::new(Ty1 {
                            name: ident,
                            langle: generic.lt_token,
                            inner,
                            rangle: generic.gt_token,
                        })));
                    }
                } else if ident == "Pin" && generic.args.len() == 1 {
                    if let GenericArgument::Type(arg) = &generic.args[0] {
                        let inner = parse_type(arg)?;
                        let pin_token = kw::Pin(ident.span());
                        if let Type::Ref(mut inner) = inner {
                            inner.pinned = true;
                            inner.pin_tokens =
                                Some((pin_token, generic.lt_token, generic.gt_token));
                            return Ok(Type::Ref(inner));
                        }
                    }
                } else {
                    let mut lifetimes = Punctuated::new();
                    let mut only_lifetimes = true;
                    for pair in generic.args.pairs() {
                        let (param, punct) = pair.into_tuple();
                        if let GenericArgument::Lifetime(param) = param {
                            lifetimes.push_value(param.clone());
                            if let Some(punct) = punct {
                                lifetimes.push_punct(*punct);
                            }
                        } else {
                            only_lifetimes = false;
                            break;
                        }
                    }
                    if only_lifetimes {
                        return Ok(Type::Ident(NamedType {
                            rust: ident,
                            generics: Lifetimes {
                                lt_token: Some(generic.lt_token),
                                lifetimes,
                                gt_token: Some(generic.gt_token),
                            },
                        }));
                    }
                }
            }
            PathArguments::Parenthesized(_) => {}
        }
    }

    Err(Error::new_spanned(ty, "unsupported type"))
}

fn parse_type_array(ty: &TypeArray) -> Result<Type> {
    let inner = parse_type(&ty.elem)?;

    let len_expr = if let Expr::Lit(lit) = &ty.len {
        lit
    } else {
        let msg = "unsupported expression, array length must be an integer literal";
        return Err(Error::new_spanned(&ty.len, msg));
    };

    let len_token = if let Lit::Int(int) = &len_expr.lit {
        int.clone()
    } else {
        let msg = "array length must be an integer literal";
        return Err(Error::new_spanned(len_expr, msg));
    };

    let len = len_token.base10_parse::<usize>()?;
    if len == 0 {
        let msg = "array with zero size is not supported";
        return Err(Error::new_spanned(ty, msg));
    }

    let bracket = ty.bracket_token;
    let semi_token = ty.semi_token;

    Ok(Type::Array(Box::new(Array {
        bracket,
        inner,
        semi_token,
        len,
        len_token,
    })))
}

fn parse_type_fn(ty: &TypeBareFn) -> Result<Type> {
    if ty.lifetimes.is_some() {
        return Err(Error::new_spanned(
            ty,
            "function pointer with lifetime parameters is not supported yet",
        ));
    }

    if ty.variadic.is_some() {
        return Err(Error::new_spanned(
            ty,
            "variadic function pointer is not supported yet",
        ));
    }

    let args = ty
        .inputs
        .iter()
        .enumerate()
        .map(|(i, arg)| {
            let (ident, colon_token) = match &arg.name {
                Some((ident, colon_token)) => (ident.clone(), *colon_token),
                None => {
                    let fn_span = ty.paren_token.span;
                    let ident = format_ident!("arg{}", i, span = fn_span);
                    let colon_token = Token![:](fn_span);
                    (ident, colon_token)
                }
            };
            let ty = parse_type(&arg.ty)?;
            let doc = Doc::new();
            let attrs = OtherAttrs::none();
            let visibility = Token![pub](ident.span());
            let name = pair(Namespace::default(), &ident, None, None);
            Ok(Var {
                doc,
                attrs,
                visibility,
                name,
                colon_token,
                ty,
            })
        })
        .collect::<Result<_>>()?;

    let mut throws_tokens = None;
    let ret = parse_return_type(&ty.output, &mut throws_tokens)?;
    let throws = throws_tokens.is_some();

    let unsafety = ty.unsafety;
    let fn_token = ty.fn_token;
    let generics = Generics::default();
    let receiver = None;
    let paren_token = ty.paren_token;

    Ok(Type::Fn(Box::new(Signature {
        unsafety,
        fn_token,
        generics,
        receiver,
        args,
        ret,
        throws,
        paren_token,
        throws_tokens,
    })))
}

fn parse_return_type(
    ty: &ReturnType,
    throws_tokens: &mut Option<(kw::Result, Token![<], Token![>])>,
) -> Result<Option<Type>> {
    let mut ret = match ty {
        ReturnType::Default => return Ok(None),
        ReturnType::Type(_, ret) => ret.as_ref(),
    };

    if let RustType::Path(ty) = ret {
        let path = &ty.path;
        if ty.qself.is_none() && path.leading_colon.is_none() && path.segments.len() == 1 {
            let segment = &path.segments[0];
            let ident = segment.ident.clone();
            if let PathArguments::AngleBracketed(generic) = &segment.arguments {
                if ident == "Result" && generic.args.len() == 1 {
                    if let GenericArgument::Type(arg) = &generic.args[0] {
                        ret = arg;
                        *throws_tokens =
                            Some((kw::Result(ident.span()), generic.lt_token, generic.gt_token));
                    }
                }
            }
        }
    }

    match parse_type(ret)? {
        Type::Void(_) => Ok(None),
        ty => Ok(Some(ty)),
    }
}

fn visibility_pub(vis: &Visibility, inherited: Span) -> Token![pub] {
    Token![pub](match vis {
        Visibility::Public(vis) => vis.pub_token.span,
        Visibility::Crate(vis) => vis.crate_token.span,
        Visibility::Restricted(vis) => vis.pub_token.span,
        Visibility::Inherited => inherited,
    })
}

fn pair(
    namespace: Namespace,
    default: &Ident,
    cxx: Option<ForeignName>,
    rust: Option<Ident>,
) -> Pair {
    Pair {
        namespace,
        cxx: cxx
            .unwrap_or_else(|| ForeignName::parse(&default.to_string(), default.span()).unwrap()),
        rust: rust.unwrap_or_else(|| default.clone()),
    }
}
