// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use deriving::path_std;
use deriving::generic::*;
use deriving::generic::ty::*;

use syntax::ast::{self, Expr, Generics, ItemKind, MetaItem, VariantData};
use syntax::ast::GenericArg;
use syntax::attr;
use syntax::ext::base::{Annotatable, ExtCtxt};
use syntax::ext::build::AstBuilder;
use syntax::ptr::P;
use syntax::symbol::{Symbol, keywords};
use syntax_pos::Span;

pub fn expand_deriving_clone(cx: &mut ExtCtxt,
                             span: Span,
                             mitem: &MetaItem,
                             item: &Annotatable,
                             push: &mut dyn FnMut(Annotatable)) {
    // check if we can use a short form
    //
    // the short form is `fn clone(&self) -> Self { *self }`
    //
    // we can use the short form if:
    // - the item is Copy (unfortunately, all we can check is whether it's also deriving Copy)
    // - there are no generic parameters (after specialization this limitation can be removed)
    //      if we used the short form with generics, we'd have to bound the generics with
    //      Clone + Copy, and then there'd be no Clone impl at all if the user fills in something
    //      that is Clone but not Copy. and until specialization we can't write both impls.
    // - the item is a union with Copy fields
    //      Unions with generic parameters still can derive Clone because they require Copy
    //      for deriving, Clone alone is not enough.
    //      Whever Clone is implemented for fields is irrelevant so we don't assert it.
    let bounds;
    let substructure;
    let is_shallow;
    match *item {
        Annotatable::Item(ref annitem) => {
            match annitem.node {
                ItemKind::Struct(_, Generics { ref params, .. }) |
                ItemKind::Enum(_, Generics { ref params, .. }) => {
                    if attr::contains_name(&annitem.attrs, "rustc_copy_clone_marker") &&
                        !params.iter().any(|param| match param.kind {
                            ast::GenericParamKind::Type { .. } => true,
                            _ => false,
                        })
                    {
                        bounds = vec![];
                        is_shallow = true;
                        substructure = combine_substructure(Box::new(|c, s, sub| {
                            cs_clone_shallow("Clone", c, s, sub, false)
                        }));
                    } else {
                        bounds = vec![];
                        is_shallow = false;
                        substructure = combine_substructure(Box::new(|c, s, sub| {
                            cs_clone("Clone", c, s, sub)
                        }));
                    }
                }
                ItemKind::Union(..) => {
                    bounds = vec![Literal(path_std!(cx, marker::Copy))];
                    is_shallow = true;
                    substructure = combine_substructure(Box::new(|c, s, sub| {
                        cs_clone_shallow("Clone", c, s, sub, true)
                    }));
                }
                _ => {
                    bounds = vec![];
                    is_shallow = false;
                    substructure = combine_substructure(Box::new(|c, s, sub| {
                        cs_clone("Clone", c, s, sub)
                    }));
                }
            }
        }

        _ => cx.span_bug(span, "#[derive(Clone)] on trait item or impl item"),
    }

    let inline = cx.meta_word(span, Symbol::intern("inline"));
    let attrs = vec![cx.attribute(span, inline)];
    let trait_def = TraitDef {
        span,
        attributes: Vec::new(),
        path: path_std!(cx, clone::Clone),
        additional_bounds: bounds,
        generics: LifetimeBounds::empty(),
        is_unsafe: false,
        supports_unions: true,
        methods: vec![MethodDef {
                          name: "clone",
                          generics: LifetimeBounds::empty(),
                          explicit_self: borrowed_explicit_self(),
                          args: Vec::new(),
                          ret_ty: Self_,
                          attributes: attrs,
                          is_unsafe: false,
                          unify_fieldless_variants: false,
                          combine_substructure: substructure,
                      }],
        associated_types: Vec::new(),
    };

    trait_def.expand_ext(cx, mitem, item, push, is_shallow)
}

fn cs_clone_shallow(name: &str,
                    cx: &mut ExtCtxt,
                    trait_span: Span,
                    substr: &Substructure,
                    is_union: bool)
                    -> P<Expr> {
    fn assert_ty_bounds(cx: &mut ExtCtxt, stmts: &mut Vec<ast::Stmt>,
                        ty: P<ast::Ty>, span: Span, helper_name: &str) {
        // Generate statement `let _: helper_name<ty>;`,
        // set the expn ID so we can use the unstable struct.
        let span = span.with_ctxt(cx.backtrace());
        let assert_path = cx.path_all(span, true,
                                        cx.std_path(&["clone", helper_name]),
                                        vec![GenericArg::Type(ty)], vec![]);
        stmts.push(cx.stmt_let_type_only(span, cx.ty_path(assert_path)));
    }
    fn process_variant(cx: &mut ExtCtxt, stmts: &mut Vec<ast::Stmt>, variant: &VariantData) {
        for field in variant.fields() {
            // let _: AssertParamIsClone<FieldTy>;
            assert_ty_bounds(cx, stmts, field.ty.clone(), field.span, "AssertParamIsClone");
        }
    }

    let mut stmts = Vec::new();
    if is_union {
        // let _: AssertParamIsCopy<Self>;
        let self_ty = cx.ty_path(cx.path_ident(trait_span, keywords::SelfUpper.ident()));
        assert_ty_bounds(cx, &mut stmts, self_ty, trait_span, "AssertParamIsCopy");
    } else {
        match *substr.fields {
            StaticStruct(vdata, ..) => {
                process_variant(cx, &mut stmts, vdata);
            }
            StaticEnum(enum_def, ..) => {
                for variant in &enum_def.variants {
                    process_variant(cx, &mut stmts, &variant.node.data);
                }
            }
            _ => cx.span_bug(trait_span, &format!("unexpected substructure in \
                                                    shallow `derive({})`", name))
        }
    }
    stmts.push(cx.stmt_expr(cx.expr_deref(trait_span, cx.expr_self(trait_span))));
    cx.expr_block(cx.block(trait_span, stmts))
}

fn cs_clone(name: &str,
            cx: &mut ExtCtxt,
            trait_span: Span,
            substr: &Substructure)
            -> P<Expr> {
    let ctor_path;
    let all_fields;
    let fn_path = cx.std_path(&["clone", "Clone", "clone"]);
    let subcall = |cx: &mut ExtCtxt, field: &FieldInfo| {
        let args = vec![cx.expr_addr_of(field.span, field.self_.clone())];
        cx.expr_call_global(field.span, fn_path.clone(), args)
    };

    let vdata;
    match *substr.fields {
        Struct(vdata_, ref af) => {
            ctor_path = cx.path(trait_span, vec![substr.type_ident]);
            all_fields = af;
            vdata = vdata_;
        }
        EnumMatching(.., variant, ref af) => {
            ctor_path = cx.path(trait_span, vec![substr.type_ident, variant.node.ident]);
            all_fields = af;
            vdata = &variant.node.data;
        }
        EnumNonMatchingCollapsed(..) => {
            cx.span_bug(trait_span,
                        &format!("non-matching enum variants in \
                                 `derive({})`",
                                 name))
        }
        StaticEnum(..) | StaticStruct(..) => {
            cx.span_bug(trait_span, &format!("static method in `derive({})`", name))
        }
    }

    match *vdata {
        VariantData::Struct(..) => {
            let fields = all_fields.iter()
                .map(|field| {
                    let ident = match field.name {
                        Some(i) => i,
                        None => {
                            cx.span_bug(trait_span,
                                        &format!("unnamed field in normal struct in \
                                                `derive({})`",
                                                    name))
                        }
                    };
                    let call = subcall(cx, field);
                    cx.field_imm(field.span, ident, call)
                })
                .collect::<Vec<_>>();

            cx.expr_struct(trait_span, ctor_path, fields)
        }
        VariantData::Tuple(..) => {
            let subcalls = all_fields.iter().map(|f| subcall(cx, f)).collect();
            let path = cx.expr_path(ctor_path);
            cx.expr_call(trait_span, path, subcalls)
        }
        VariantData::Unit(..) => cx.expr_path(ctor_path),
    }
}
