//! The compiler code necessary for `#[derive(RustcDecodable)]`. See encodable.rs for more.

use crate::deriving::pathvec_std;
use crate::deriving::generic::*;
use crate::deriving::generic::ty::*;

use syntax::ast;
use syntax::ast::{Expr, MetaItem, Mutability};
use syntax_expand::base::{Annotatable, ExtCtxt};
use syntax::ptr::P;
use syntax::symbol::Symbol;
use syntax_pos::Span;

pub fn expand_deriving_rustc_decodable(cx: &mut ExtCtxt<'_>,
                                       span: Span,
                                       mitem: &MetaItem,
                                       item: &Annotatable,
                                       push: &mut dyn FnMut(Annotatable)) {
    let krate = "rustc_serialize";
    let typaram = "__D";

    let trait_def = TraitDef {
        span,
        attributes: Vec::new(),
        path: Path::new_(vec![krate, "Decodable"], None, vec![], PathKind::Global),
        additional_bounds: Vec::new(),
        generics: LifetimeBounds::empty(),
        is_unsafe: false,
        supports_unions: false,
        methods: vec![MethodDef {
                          name: "decode",
                          generics: LifetimeBounds {
                              lifetimes: Vec::new(),
                              bounds: vec![(typaram,
                                            vec![Path::new_(vec![krate, "Decoder"],
                                                            None,
                                                            vec![],
                                                            PathKind::Global)])],
                          },
                          explicit_self: None,
                          args: vec![(Ptr(Box::new(Literal(Path::new_local(typaram))),
                                         Borrowed(None, Mutability::Mutable)), "d")],
                          ret_ty:
                              Literal(Path::new_(pathvec_std!(cx, result::Result),
                                                 None,
                                                 vec![Box::new(Self_), Box::new(Literal(Path::new_(
                        vec![typaram, "Error"], None, vec![], PathKind::Local
                    )))],
                                                 PathKind::Std)),
                          attributes: Vec::new(),
                          is_unsafe: false,
                          unify_fieldless_variants: false,
                          combine_substructure: combine_substructure(Box::new(|a, b, c| {
                              decodable_substructure(a, b, c, krate)
                          })),
                      }],
        associated_types: Vec::new(),
    };

    trait_def.expand(cx, mitem, item, push)
}

fn decodable_substructure(cx: &mut ExtCtxt<'_>,
                          trait_span: Span,
                          substr: &Substructure<'_>,
                          krate: &str)
                          -> P<Expr> {
    let decoder = substr.nonself_args[0].clone();
    let recurse = vec![
        cx.ident_of(krate, trait_span),
        cx.ident_of("Decodable", trait_span),
        cx.ident_of("decode", trait_span),
    ];
    let exprdecode = cx.expr_path(cx.path_global(trait_span, recurse));
    // throw an underscore in front to suppress unused variable warnings
    let blkarg = cx.ident_of("_d", trait_span);
    let blkdecoder = cx.expr_ident(trait_span, blkarg);

    return match *substr.fields {
        StaticStruct(_, ref summary) => {
            let nfields = match *summary {
                Unnamed(ref fields, _) => fields.len(),
                Named(ref fields) => fields.len(),
            };
            let read_struct_field = cx.ident_of("read_struct_field", trait_span);

            let path = cx.path_ident(trait_span, substr.type_ident);
            let result =
                decode_static_fields(cx, trait_span, path, summary, |cx, span, name, field| {
                    cx.expr_try(span,
                                cx.expr_method_call(span,
                                                    blkdecoder.clone(),
                                                    read_struct_field,
                                                    vec![cx.expr_str(span, name),
                                                         cx.expr_usize(span, field),
                                                         exprdecode.clone()]))
                });
            let result = cx.expr_ok(trait_span, result);
            cx.expr_method_call(trait_span,
                                decoder,
                                cx.ident_of("read_struct", trait_span),
                                vec![cx.expr_str(trait_span, substr.type_ident.name),
                                     cx.expr_usize(trait_span, nfields),
                                     cx.lambda1(trait_span, result, blkarg)])
        }
        StaticEnum(_, ref fields) => {
            let variant = cx.ident_of("i", trait_span);

            let mut arms = Vec::with_capacity(fields.len() + 1);
            let mut variants = Vec::with_capacity(fields.len());
            let rvariant_arg = cx.ident_of("read_enum_variant_arg", trait_span);

            for (i, &(ident, v_span, ref parts)) in fields.iter().enumerate() {
                variants.push(cx.expr_str(v_span, ident.name));

                let path = cx.path(trait_span, vec![substr.type_ident, ident]);
                let decoded = decode_static_fields(cx, v_span, path, parts, |cx, span, _, field| {
                    let idx = cx.expr_usize(span, field);
                    cx.expr_try(span,
                                cx.expr_method_call(span,
                                                    blkdecoder.clone(),
                                                    rvariant_arg,
                                                    vec![idx, exprdecode.clone()]))
                });

                arms.push(cx.arm(v_span, cx.pat_lit(v_span, cx.expr_usize(v_span, i)), decoded));
            }

            arms.push(cx.arm_unreachable(trait_span));

            let result =
                cx.expr_ok(trait_span,
                           cx.expr_match(trait_span, cx.expr_ident(trait_span, variant), arms));
            let lambda = cx.lambda(trait_span, vec![blkarg, variant], result);
            let variant_vec = cx.expr_vec(trait_span, variants);
            let variant_vec = cx.expr_addr_of(trait_span, variant_vec);
            let result = cx.expr_method_call(trait_span,
                                             blkdecoder,
                                             cx.ident_of("read_enum_variant", trait_span),
                                             vec![variant_vec, lambda]);
            cx.expr_method_call(trait_span,
                                decoder,
                                cx.ident_of("read_enum", trait_span),
                                vec![cx.expr_str(trait_span, substr.type_ident.name),
                                     cx.lambda1(trait_span, result, blkarg)])
        }
        _ => cx.bug("expected StaticEnum or StaticStruct in derive(Decodable)"),
    };
}

/// Creates a decoder for a single enum variant/struct:
/// - `outer_pat_path` is the path to this enum variant/struct
/// - `getarg` should retrieve the `usize`-th field with name `@str`.
fn decode_static_fields<F>(cx: &mut ExtCtxt<'_>,
                           trait_span: Span,
                           outer_pat_path: ast::Path,
                           fields: &StaticFields,
                           mut getarg: F)
                           -> P<Expr>
    where F: FnMut(&mut ExtCtxt<'_>, Span, Symbol, usize) -> P<Expr>
{
    match *fields {
        Unnamed(ref fields, is_tuple) => {
            let path_expr = cx.expr_path(outer_pat_path);
            if !is_tuple {
                path_expr
            } else {
                let fields = fields.iter()
                    .enumerate()
                    .map(|(i, &span)| {
                        getarg(cx, span, Symbol::intern(&format!("_field{}", i)), i)
                    })
                    .collect();

                cx.expr_call(trait_span, path_expr, fields)
            }
        }
        Named(ref fields) => {
            // use the field's span to get nicer error messages.
            let fields = fields.iter()
                .enumerate()
                .map(|(i, &(ident, span))| {
                    let arg = getarg(cx, span, ident.name, i);
                    cx.field_imm(span, ident, arg)
                })
                .collect();
            cx.expr_struct(trait_span, outer_pat_path, fields)
        }
    }
}
