use proc_macro2::{Group, Span, TokenStream, TokenTree};
use std::iter::FromIterator;
use syn::visit_mut::{self, VisitMut};
use syn::{
    Block, ExprPath, Ident, Item, Macro, Pat, PatIdent, PatPath, Path, Receiver, Signature, Token,
    TypePath,
};

pub fn has_self_in_sig(sig: &mut Signature) -> bool {
    let mut visitor = HasSelf(false);
    visitor.visit_signature_mut(sig);
    visitor.0
}

pub fn has_self_in_block(block: &mut Block) -> bool {
    let mut visitor = HasSelf(false);
    visitor.visit_block_mut(block);
    visitor.0
}

fn has_self_in_token_stream(tokens: TokenStream) -> bool {
    tokens.into_iter().any(|tt| match tt {
        TokenTree::Ident(ident) => ident == "Self",
        TokenTree::Group(group) => has_self_in_token_stream(group.stream()),
        _ => false,
    })
}

pub fn mut_pat(pat: &mut Pat) -> Option<Token![mut]> {
    let mut visitor = HasMutPat(None);
    visitor.visit_pat_mut(pat);
    visitor.0
}

fn contains_fn(tokens: TokenStream) -> bool {
    tokens.into_iter().any(|tt| match tt {
        TokenTree::Ident(ident) => ident == "fn",
        TokenTree::Group(group) => contains_fn(group.stream()),
        _ => false,
    })
}

struct HasMutPat(Option<Token![mut]>);

impl VisitMut for HasMutPat {
    fn visit_pat_ident_mut(&mut self, i: &mut PatIdent) {
        if let Some(m) = i.mutability {
            self.0 = Some(m);
        } else {
            visit_mut::visit_pat_ident_mut(self, i);
        }
    }
}

struct HasSelf(bool);

impl VisitMut for HasSelf {
    fn visit_expr_path_mut(&mut self, expr: &mut ExprPath) {
        self.0 |= expr.path.segments[0].ident == "Self";
        visit_mut::visit_expr_path_mut(self, expr);
    }

    fn visit_pat_path_mut(&mut self, pat: &mut PatPath) {
        self.0 |= pat.path.segments[0].ident == "Self";
        visit_mut::visit_pat_path_mut(self, pat);
    }

    fn visit_type_path_mut(&mut self, ty: &mut TypePath) {
        self.0 |= ty.path.segments[0].ident == "Self";
        visit_mut::visit_type_path_mut(self, ty);
    }

    fn visit_receiver_mut(&mut self, _arg: &mut Receiver) {
        self.0 = true;
    }

    fn visit_item_mut(&mut self, _: &mut Item) {
        // Do not recurse into nested items.
    }

    fn visit_macro_mut(&mut self, mac: &mut Macro) {
        if !contains_fn(mac.tokens.clone()) {
            self.0 |= has_self_in_token_stream(mac.tokens.clone());
        }
    }
}

pub struct ReplaceSelf(pub Span);

impl ReplaceSelf {
    #[cfg_attr(not(self_span_hack), allow(clippy::unused_self))]
    fn prepend_underscore_to_self(&self, ident: &mut Ident) -> bool {
        let modified = ident == "self";
        if modified {
            *ident = Ident::new("__self", ident.span());
            #[cfg(self_span_hack)]
            ident.set_span(self.0);
        }
        modified
    }

    fn visit_token_stream(&mut self, tokens: &mut TokenStream) -> bool {
        let mut out = Vec::new();
        let mut modified = false;
        visit_token_stream_impl(self, tokens.clone(), &mut modified, &mut out);
        if modified {
            *tokens = TokenStream::from_iter(out);
        }
        return modified;

        fn visit_token_stream_impl(
            visitor: &mut ReplaceSelf,
            tokens: TokenStream,
            modified: &mut bool,
            out: &mut Vec<TokenTree>,
        ) {
            for tt in tokens {
                match tt {
                    TokenTree::Ident(mut ident) => {
                        *modified |= visitor.prepend_underscore_to_self(&mut ident);
                        out.push(TokenTree::Ident(ident));
                    }
                    TokenTree::Group(group) => {
                        let mut content = group.stream();
                        *modified |= visitor.visit_token_stream(&mut content);
                        let mut new = Group::new(group.delimiter(), content);
                        new.set_span(group.span());
                        out.push(TokenTree::Group(new));
                    }
                    other => out.push(other),
                }
            }
        }
    }
}

impl VisitMut for ReplaceSelf {
    fn visit_ident_mut(&mut self, i: &mut Ident) {
        self.prepend_underscore_to_self(i);
    }

    fn visit_path_mut(&mut self, p: &mut Path) {
        if p.segments.len() == 1 {
            // Replace `self`, but not `self::function`.
            self.visit_ident_mut(&mut p.segments[0].ident);
        }
        for segment in &mut p.segments {
            self.visit_path_arguments_mut(&mut segment.arguments);
        }
    }

    fn visit_item_mut(&mut self, i: &mut Item) {
        // Visit `macro_rules!` because locally defined macros can refer to
        // `self`.
        //
        // Visit `futures::select` and similar select macros, which commonly
        // appear syntactically like an item despite expanding to an expression.
        //
        // Otherwise, do not recurse into nested items.
        if let Item::Macro(i) = i {
            if i.mac.path.is_ident("macro_rules")
                || i.mac.path.segments.last().unwrap().ident == "select"
            {
                self.visit_macro_mut(&mut i.mac);
            }
        }
    }

    fn visit_macro_mut(&mut self, mac: &mut Macro) {
        // We can't tell in general whether `self` inside a macro invocation
        // refers to the self in the argument list or a different self
        // introduced within the macro. Heuristic: if the macro input contains
        // `fn`, then `self` is more likely to refer to something other than the
        // outer function's self argument.
        if !contains_fn(mac.tokens.clone()) {
            self.visit_token_stream(&mut mac.tokens);
        }
    }
}
