use crate::{attr, ty};
use proc_macro2::{Span, TokenStream, TokenTree};
use quote::{format_ident, quote, quote_spanned};
use syn::parse::{Error, Parse, ParseStream, Result};
use syn::punctuated::Punctuated;
use syn::{
    braced, parenthesized, parse_quote, Abi, Attribute, BareFnArg, BoundLifetimes, GenericParam,
    Generics, Ident, Path, ReturnType, Token, Type, TypeBareFn, Visibility, WhereClause,
};

pub struct Element {
    attrs: Vec<Attribute>,
    vis: Visibility,
    ident: Ident,
    ty: Type,
    expr: TokenStream,
    orig_item: Option<TokenStream>,
    start_span: Span,
    end_span: Span,
}

impl Parse for Element {
    fn parse(input: ParseStream) -> Result<Self> {
        let attrs = input.call(Attribute::parse_outer)?;
        let item = input.cursor();
        let vis: Visibility = input.parse()?;
        let static_token: Option<Token![static]> = input.parse()?;
        if static_token.is_some() {
            let mut_token: Option<Token![mut]> = input.parse()?;
            if let Some(mut_token) = mut_token {
                return Err(Error::new_spanned(
                    mut_token,
                    "static mut is not supported by distributed_slice",
                ));
            }
            let ident: Ident = input.parse()?;
            input.parse::<Token![:]>()?;
            let start_span = input.span();
            let ty: Type = input.parse()?;
            let end_span = quote!(#ty).into_iter().last().unwrap().span();
            input.parse::<Token![=]>()?;
            let mut expr_semi = Vec::from_iter(input.parse::<TokenStream>()?);
            if let Some(tail) = expr_semi.pop() {
                syn::parse2::<Token![;]>(TokenStream::from(tail))?;
            }
            let expr = TokenStream::from_iter(expr_semi);
            Ok(Element {
                attrs,
                vis,
                ident,
                ty,
                expr,
                orig_item: None,
                start_span,
                end_span,
            })
        } else {
            let constness: Option<Token![const]> = input.parse()?;
            let asyncness: Option<Token![async]> = input.parse()?;
            let unsafety: Option<Token![unsafe]> = input.parse()?;
            let abi: Option<Abi> = input.parse()?;
            let fn_token: Token![fn] = input.parse().map_err(|_| {
                Error::new_spanned(
                    item.token_stream(),
                    "distributed element must be either static or function item",
                )
            })?;
            let ident: Ident = input.parse()?;
            let generics: Generics = input.parse()?;

            let content;
            let paren_token = parenthesized!(content in input);
            let mut inputs = Punctuated::new();
            while !content.is_empty() {
                content.parse::<Option<Token![mut]>>()?;
                let ident = if let Some(wild) = content.parse::<Option<Token![_]>>()? {
                    Ident::from(wild)
                } else {
                    content.parse()?
                };
                let colon_token: Token![:] = content.parse()?;
                let ty: Type = content.parse()?;
                inputs.push_value(BareFnArg {
                    attrs: Vec::new(),
                    name: Some((ident, colon_token)),
                    ty,
                });
                if !content.is_empty() {
                    let comma: Token![,] = content.parse()?;
                    inputs.push_punct(comma);
                }
            }

            let output: ReturnType = input.parse()?;
            let where_clause: Option<WhereClause> = input.parse()?;

            let content;
            braced!(content in input);
            content.parse::<TokenStream>()?;

            if let Some(constness) = constness {
                return Err(Error::new_spanned(
                    constness,
                    "const fn distributed slice element is not supported",
                ));
            }

            if let Some(asyncness) = asyncness {
                return Err(Error::new_spanned(
                    asyncness,
                    "async fn distributed slice element is not supported",
                ));
            }

            let lifetimes = if generics.params.is_empty() {
                None
            } else {
                let mut bound = BoundLifetimes {
                    for_token: Token![for](generics.lt_token.unwrap().span),
                    lt_token: generics.lt_token.unwrap(),
                    lifetimes: Punctuated::new(),
                    gt_token: generics.gt_token.unwrap(),
                };
                for param in generics.params.into_pairs() {
                    let (param, punct) = param.into_tuple();
                    if let GenericParam::Lifetime(_) = param {
                        bound.lifetimes.push_value(param);
                        if let Some(punct) = punct {
                            bound.lifetimes.push_punct(punct);
                        }
                    } else {
                        return Err(Error::new_spanned(
                            param,
                            "cannot have generic parameters on distributed slice element",
                        ));
                    }
                }
                Some(bound)
            };

            if let Some(where_clause) = where_clause {
                return Err(Error::new_spanned(
                    where_clause,
                    "where-clause is not allowed on distributed slice elements",
                ));
            }

            let start_span = item.span();
            let end_span = quote!(#output)
                .into_iter()
                .last()
                .as_ref()
                .map_or(paren_token.span.close(), TokenTree::span);
            let mut original_attrs = attrs;
            let linkme_path = attr::linkme_path(&mut original_attrs)?;

            let attrs = vec![
                parse_quote! {
                    #[allow(non_upper_case_globals)]
                },
                parse_quote! {
                    #[linkme(crate = #linkme_path)]
                },
            ];
            let vis = Visibility::Inherited;
            let expr = parse_quote!(#ident);
            let ty = Type::BareFn(TypeBareFn {
                lifetimes,
                unsafety,
                abi,
                fn_token,
                paren_token,
                inputs,
                variadic: None,
                output,
            });
            let ident = format_ident!("_LINKME_ELEMENT_{}", ident);
            let item = item.token_stream();
            let orig_item = Some(quote!(
                #(#original_attrs)*
                #item
            ));

            Ok(Element {
                attrs,
                vis,
                ident,
                ty,
                expr,
                orig_item,
                start_span,
                end_span,
            })
        }
    }
}

pub fn expand(path: Path, pos: impl Into<Option<usize>>, input: Element) -> TokenStream {
    let pos = pos.into();
    do_expand(path, pos, input)
}

fn do_expand(path: Path, pos: Option<usize>, input: Element) -> TokenStream {
    let mut attrs = input.attrs;
    let vis = input.vis;
    let ident = input.ident;
    let mut ty = input.ty;
    let expr = input.expr;
    let orig_item = input.orig_item;

    ty::populate_static_lifetimes(&mut ty);

    let linkme_path = match attr::linkme_path(&mut attrs) {
        Ok(path) => path,
        Err(err) => return err.to_compile_error(),
    };

    let sort_key = pos.into_iter().map(|pos| format!("{:04}", pos));

    let factory = quote_spanned!(input.start_span=> __new);
    let get = quote_spanned!(input.end_span=> #factory());

    quote! {
        #path ! {
            #(
                #![linkme_macro = #path]
                #![linkme_sort_key = #sort_key]
            )*
            #(#attrs)*
            #vis static #ident : #ty = {
                #[allow(clippy::no_effect_underscore_binding)]
                unsafe fn __typecheck(_: #linkme_path::__private::Void) {
                    #[allow(clippy::ref_option_ref)]
                    let #factory = || -> fn() -> &'static #ty { || &#ident };
                    unsafe {
                        #linkme_path::DistributedSlice::private_typecheck(#path, #get);
                    }
                }

                #expr
            };
        }

        #orig_item
    }
}
