use crate::internals::ast::{Container, Data, Field, Style};
use crate::internals::attr::{Default, Identifier, TagType};
use crate::internals::{ungroup, Ctxt, Derive};
use syn::{Member, Type};

// Cross-cutting checks that require looking at more than a single attrs object.
// Simpler checks should happen when parsing and building the attrs.
pub fn check(cx: &Ctxt, cont: &mut Container, derive: Derive) {
    check_default_on_tuple(cx, cont);
    check_remote_generic(cx, cont);
    check_getter(cx, cont);
    check_flatten(cx, cont);
    check_identifier(cx, cont);
    check_variant_skip_attrs(cx, cont);
    check_internal_tag_field_name_conflict(cx, cont);
    check_adjacent_tag_conflict(cx, cont);
    check_transparent(cx, cont, derive);
    check_from_and_try_from(cx, cont);
}

// If some field of a tuple struct is marked #[serde(default)] then all fields
// after it must also be marked with that attribute, or the struct must have a
// container-level serde(default) attribute. A field's default value is only
// used for tuple fields if the sequence is exhausted at that point; that means
// all subsequent fields will fail to deserialize if they don't have their own
// default.
fn check_default_on_tuple(cx: &Ctxt, cont: &Container) {
    if let Default::None = cont.attrs.default() {
        if let Data::Struct(Style::Tuple, fields) = &cont.data {
            let mut first_default_index = None;
            for (i, field) in fields.iter().enumerate() {
                // Skipped fields automatically get the #[serde(default)]
                // attribute. We are interested only on non-skipped fields here.
                if field.attrs.skip_deserializing() {
                    continue;
                }
                if let Default::None = field.attrs.default() {
                    if let Some(first) = first_default_index {
                        cx.error_spanned_by(
                            field.ty,
                            format!("field must have #[serde(default)] because previous field {} has #[serde(default)]", first),
                        );
                    }
                    continue;
                }
                if first_default_index.is_none() {
                    first_default_index = Some(i);
                }
            }
        }
