/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use std::io::Write;

use syn::ext::IdentExt;

use crate::bindgen::config::{Config, Language};
use crate::bindgen::declarationtyperesolver::DeclarationTypeResolver;
use crate::bindgen::dependencies::Dependencies;
use crate::bindgen::ir::{
    AnnotationSet, AnnotationValue, Cfg, ConditionWrite, DeprecatedNoteKind, Documentation, Field,
    GenericArgument, GenericParams, GenericPath, Item, ItemContainer, Literal, Path, Repr,
    ReprStyle, Struct, ToCondition, Type,
};
use crate::bindgen::language_backend::LanguageBackend;
use crate::bindgen::library::Library;
use crate::bindgen::mangle;
use crate::bindgen::monomorph::Monomorphs;
use crate::bindgen::rename::{IdentifierType, RenameRule};
use crate::bindgen::reserved;
use crate::bindgen::writer::{ListType, SourceWriter};

#[allow(clippy::large_enum_variant)]
#[derive(Debug, Clone)]
pub enum VariantBody {
    Empty(AnnotationSet),
    Body {
        /// The variant field / export name.
        name: String,
        /// The struct with all the items.
        body: Struct,
        /// A separate named struct is not created for this variant,
        /// an unnamed struct is inlined at the point of use instead.
        /// This is a reasonable thing to do only for tuple variants with a single field.
        inline: bool,
        /// Generated cast methods return the variant's only field instead of the variant itself.
        /// For backward compatibility casts are inlined in a slightly
        /// larger set of cases than whole variants.
        inline_casts: bool,
    },
}

impl VariantBody {
    fn empty() -> Self {
        Self::Empty(AnnotationSet::new())
    }

    pub fn annotations(&self) -> &AnnotationSet {
        match *self {
            Self::Empty(ref anno) => anno,
            Self::Body { ref body, .. } => &body.annotations,
        }
    }

    fn is_empty(&self) -> bool {
        match *self {
            Self::Empty(..) => true,
            Self::Body { .. } => false,
        }
    }

    fn specialize(
        &self,
        generic_values: &[GenericArgument],
        mappings: &[(&Path, &GenericArgument)],
        config: &Config,
    ) -> Self {
        match *self {
            Self::Empty(ref annos) => Self::Empty(annos.clone()),
            Self::Body {
                ref name,
                ref body,
                inline,
                inline_casts,
            } => Self::Body {
                name: name.clone(),
                body: body.specialize(generic_values, mappings, config),
                inline,
                inline_casts,
            },
        }
    }
}

#[derive(Debug, Clone)]
pub struct EnumVariant {
    pub name: String,
    pub export_name: String,
    pub discriminant: Option<Literal>,
    pub body: VariantBody,
    pub cfg: Option<Cfg>,
    pub documentation: Documentation,
}

impl EnumVariant {
    fn load(
        inline_tag_field: bool,
        variant: &syn::Variant,
        generic_params: GenericParams,
        mod_cfg: Option<&Cfg>,
        self_path: &Path,
        enum_annotations: &AnnotationSet,
        config: &Config,
    ) -> Result<Self, String> {
        let discriminant = match variant.discriminant {
            Some((_, ref expr)) => Some(Literal::load(expr)?),
            None => None,
        };

        fn parse_fields(
            inline_tag_field: bool,
            fields: &syn::punctuated::Punctuated<syn::Field, syn::token::Comma>,
            self_path: &Path,
            inline_name: Option<&str>,
        ) -> Result<Vec<Field>, String> {
            let mut res = Vec::new();

            if inline_tag_field {
                res.push(Field::from_name_and_type(
                    inline_name.map_or_else(|| "tag".to_string(), |name| format!("{}_tag", name)),
                    Type::Path(GenericPath::new(Path::new("Tag"), vec![])),
                ));
            }

            for (i, field) in fields.iter().enumerate() {
                if let Some(mut ty) = Type::load(&field.ty)? {
                    ty.replace_self_with(self_path);
                    res.push(Field {
                        name: inline_name.map_or_else(
                            || match field.ident {
                                Some(ref ident) => ident.unraw().to_string(),
                                None => i.to_string(),
                            },
                            |name| name.to_string(),
                        ),
                        ty,
                        cfg: Cfg::load(&field.attrs),
                        annotations: AnnotationSet::load(&field.attrs)?,
                        documentation: Documentation::load(&field.attrs),
                    });
                }
            }

            Ok(res)
        }

        let variant_cfg = Cfg::append(mod_cfg, Cfg::load(&variant.attrs));
        let mut annotations = AnnotationSet::load(&variant.attrs)?;
        if let Some(b) = enum_annotations.bool("derive-ostream") {
            annotations.add_default("derive-ostream", AnnotationValue::Bool(b));
        }

        let body_rule = enum_annotations
            .parse_atom::<RenameRule>("rename-variant-name-fields")
            .unwrap_or(config.enumeration.rename_variant_name_fields);

        let body = match variant.fields {
            syn::Fields::Unit => VariantBody::Empty(annotations),
            syn::Fields::Named(ref fields) => {
                let path = Path::new(format!("{}_Body", variant.ident));
                let name = body_rule
                    .apply(
                        &variant.ident.unraw().to_string(),
                        IdentifierType::StructMember,
                    )
                    .into_owned();
                VariantBody::Body {
                    body: Struct::new(
                        path,
                        generic_params,
                        parse_fields(inline_tag_field, &fields.named, self_path, None)?,
                        inline_tag_field,
                        true,
                        None,
                        false,
                        None,
                        annotations,
                        Documentation::none(),
                    ),
                    name,
                    inline: false,
                    inline_casts: false,
                }
            }
            syn::Fields::Unnamed(ref fields) => {
                let path = Path::new(format!("{}_Body", variant.ident));
                let name = body_rule
                    .apply(
                        &variant.ident.unraw().to_string(),
                        IdentifierType::StructMember,
                    )
                    .into_owned();
                let inline_casts = fields.unnamed.len() == 1;
                // In C++ types with destructors cannot be put into unnamed structs like the
                // inlining requires, and it's hard to detect such types.
                // Besides that for C++ we generate casts/getters that can be used instead of
                // direct field accesses and also have a benefit of being checked.
                // As a result we don't currently inline variant definitions in C++ mode at all.
                let inline = inline_casts && config.language != Language::Cxx;
                let inline_name = if inline { Some(&*name) } else { None };
                VariantBody::Body {
                    body: Struct::new(
                        path,
                        generic_params,
                        parse_fields(inline_tag_field, &fields.unnamed, self_path, inline_name)?,
                        inline_tag_field,
                        true,
                        None,
                        false,
                        None,
                        annotations,
                        Documentation::none(),
                    ),
                    name,
                    inline,
                    inline_casts,
                }
            }
        };

        Ok(EnumVariant::new(
            variant.ident.unraw().to_string(),
            discriminant,
            body,
            variant_cfg,
            Documentation::load(&variant.attrs),
        ))
    }

    pub fn new(
        name: String,
        discriminant: Option<Literal>,
        body: VariantBody,
        cfg: Option<Cfg>,
        documentation: Documentation,
    ) -> Self {
        let export_name = name.clone();
        Self {
            name,
            export_name,
            discriminant,
            body,
            cfg,
            documentation,
        }
    }

    fn simplify_standard_types(&mut self, config: &Config) {
        if let VariantBody::Body { ref mut body, .. } = self.body {
            body.simplify_standard_types(config);
        }
    }

    fn add_dependencies(&self, library: &Library, out: &mut Dependencies) {
        if let VariantBody::Body { ref body, .. } = self.body {
            body.add_dependencies(library, out);
        }
    }

    fn resolve_declaration_types(&mut self, resolver: &DeclarationTypeResolver) {
        if let VariantBody::Body { ref mut body, .. } = self.body {
            body.resolve_declaration_types(resolver);
        }
    }

    fn specialize(
        &self,
        generic_values: &[GenericArgument],
        mappings: &[(&Path, &GenericArgument)],
        config: &Config,
    ) -> Self {
        Self::new(
            mangle::mangle_name(&self.name, generic_values, &config.export.mangle),
            self.discriminant.clone(),
            self.body.specialize(generic_values, mappings, config),
            self.cfg.clone(),
            self.documentation.clone(),
        )
    }

    fn add_monomorphs(&self, library: &Library, out: &mut Monomorphs) {
        if let VariantBody::Body { ref body, .. } = self.body {
            body.add_monomorphs(library, out);
        }
    }

    fn mangle_paths(&mut self, monomorphs: &Monomorphs) {
        if let VariantBody::Body { ref mut body, .. } = self.body {
            body.mangle_paths(monomorphs);
        }
    }
}

#[derive(Debug, Clone)]
pub struct Enum {
    pub path: Path,
    pub export_name: String,
    pub generic_params: GenericParams,
    pub repr: Repr,
    pub variants: Vec<EnumVariant>,
    pub tag: Option<String>,
    pub cfg: Option<Cfg>,
    pub annotations: AnnotationSet,
    pub documentation: Documentation,
}

impl Enum {
    /// Name of the generated tag enum.
    pub(crate) fn tag_name(&self) -> &str {
        self.tag.as_deref().unwrap_or_else(|| self.export_name())
    }

    /// Enum with data turns into a union of structs with each struct having its own tag field.
    pub(crate) fn inline_tag_field(repr: &Repr) -> bool {
        repr.style != ReprStyle::C
    }

    pub fn add_monomorphs(&self, library: &Library, out: &mut Monomorphs) {
        if self.is_generic() {
            return;
        }

        for v in &self.variants {
            v.add_monomorphs(library, out);
        }
    }

    fn can_derive_eq(&self) -> bool {
        if self.tag.is_none() {
            return false;
        }

        self.variants.iter().all(|variant| match variant.body {
            VariantBody::Empty(..) => true,
            VariantBody::Body { ref body, .. } => body.can_derive_eq(),
        })
    }

    pub fn mangle_paths(&mut self, monomorphs: &Monomorphs) {
        for variant in &mut self.variants {
            variant.mangle_paths(monomorphs);
        }
    }

    pub fn load(
        item: &syn::ItemEnum,
        mod_cfg: Option<&Cfg>,
        config: &Config,
    ) -> Result<Enum, String> {
        let repr = Repr::load(&item.attrs)?;
        if repr.style == ReprStyle::Rust && repr.ty.is_none() {
            return Err("Enum is not marked with a valid #[repr(prim)] or #[repr(C)].".to_owned());
        }
        // TODO: Implement translation of aligned enums.
        if repr.align.is_some() {
            return Err("Enum is marked with #[repr(align(...))] or #[repr(packed)].".to_owned());
        }

        let path = Path::new(item.ident.unraw().to_string());
        let generic_params = GenericParams::load(&item.generics)?;

        let mut variants = Vec::new();
        let mut has_data = false;

        let annotations = AnnotationSet::load(&item.attrs)?;

        for variant in item.variants.iter() {
            let variant = EnumVariant::load(
                Self::inline_tag_field(&repr),
                variant,
                generic_params.clone(),
                mod_cfg,
                &path,
                &annotations,
                config,
            )?;
            has_data = has_data || !variant.body.is_empty();
            variants.push(variant);
        }

        if let Some(names) = annotations.list("enum-trailing-values") {
            for name in names {
                variants.push(EnumVariant::new(
                    name,
                    None,
                    VariantBody::empty(),
                    None,
                    Documentation::none(),
                ));
            }
        }

        if config.enumeration.add_sentinel(&annotations) {
            variants.push(EnumVariant::new(
                "Sentinel".to_owned(),
                None,
                VariantBody::empty(),
                None,
                Documentation::simple(" Must be last for serialization purposes"),
            ));
        }

        let tag = if has_data {
            Some("Tag".to_string())
        } else {
            None
        };

        Ok(Enum::new(
            path,
            generic_params,
            repr,
            variants,
            tag,
            Cfg::append(mod_cfg, Cfg::load(&item.attrs)),
            annotations,
            Documentation::load(&item.attrs),
        ))
    }

    #[allow(clippy::too_many_arguments)]
    pub fn new(
        path: Path,
        generic_params: GenericParams,
        repr: Repr,
        variants: Vec<EnumVariant>,
        tag: Option<String>,
        cfg: Option<Cfg>,
        annotations: AnnotationSet,
        documentation: Documentation,
    ) -> Self {
        let export_name = path.name().to_owned();
        Self {
            path,
            export_name,
            generic_params,
            repr,
            variants,
            tag,
            cfg,
            annotations,
            documentation,
        }
    }
}

impl Item for Enum {
    fn path(&self) -> &Path {
        &self.path
    }

    fn export_name(&self) -> &str {
        &self.export_name
    }

    fn cfg(&self) -> Option<&Cfg> {
        self.cfg.as_ref()
    }

    fn annotations(&self) -> &AnnotationSet {
        &self.annotations
    }

    fn annotations_mut(&mut self) -> &mut AnnotationSet {
        &mut self.annotations
    }

    fn documentation(&self) -> &Documentation {
        &self.documentation
    }

    fn container(&self) -> ItemContainer {
        ItemContainer::Enum(self.clone())
    }

    fn collect_declaration_types(&self, resolver: &mut DeclarationTypeResolver) {
        if self.tag.is_some() {
            if self.repr.style == ReprStyle::C {
                resolver.add_struct(&self.path);
            } else {
                resolver.add_union(&self.path);
            }
        } else if self.repr.style == ReprStyle::C {
            resolver.add_enum(&self.path);
        } else {
            // This is important to handle conflicting names with opaque items.
            resolver.add_none(&self.path);
        }
    }

    fn resolve_declaration_types(&mut self, resolver: &DeclarationTypeResolver) {
        for &mut ref mut var in &mut self.variants {
            var.resolve_declaration_types(resolver);
        }
    }

    fn generic_params(&self) -> &GenericParams {
        &self.generic_params
    }

    fn rename_for_config(&mut self, config: &Config) {
        config.export.rename(&mut self.export_name);

        if config.language != Language::Cxx && self.tag.is_some() {
            // it makes sense to always prefix Tag with type name in C
            let new_tag = format!("{}_Tag", self.export_name);
            if self.repr.style == ReprStyle::Rust {
                for variant in &mut self.variants {
                    if let VariantBody::Body { ref mut body, .. } = variant.body {
                        let path = Path::new(new_tag.clone());
                        let generic_path = GenericPath::new(path, vec![]);
                        body.fields[0].ty = Type::Path(generic_path);
                    }
                }
            }
            self.tag = Some(new_tag);
        }

        for variant in &mut self.variants {
            reserved::escape(&mut variant.export_name);
            if let Some(discriminant) = &mut variant.discriminant {
                discriminant.rename_for_config(config);
            }
            if let VariantBody::Body {
                ref mut name,
                ref mut body,
                ..
            } = variant.body
            {
                body.rename_for_config(config);
                reserved::escape(name);
            }
        }

        if config.enumeration.prefix_with_name
            || self.annotations.bool("prefix-with-name").unwrap_or(false)
        {
            let separator = if config.export.mangle.remove_underscores {
                ""
            } else {
                "_"
            };

            for variant in &mut self.variants {
                variant.export_name =
                    format!("{}{}{}", self.export_name, separator, variant.export_name);
                if let VariantBody::Body { ref mut body, .. } = variant.body {
                    body.export_name =
                        format!("{}{}{}", self.export_name, separator, body.export_name());
                }
            }
        }

        let rules = self
            .annotations
            .parse_atom::<RenameRule>("rename-all")
            .unwrap_or(config.enumeration.rename_variants);

        if let Some(r) = rules.not_none() {
            self.variants = self
                .variants
                .iter()
                .map(|variant| {
                    EnumVariant::new(
                        r.apply(
                            &variant.export_name,
                            IdentifierType::EnumVariant {
                                prefix: &self.export_name,
                            },
                        )
                        .into_owned(),
                        variant.discriminant.clone(),
                        match variant.body {
                            VariantBody::Empty(..) => variant.body.clone(),
                            VariantBody::Body {
                                ref name,
                                ref body,
                                inline,
                                inline_casts,
                            } => VariantBody::Body {
                                name: r.apply(name, IdentifierType::StructMember).into_owned(),
                                body: body.clone(),
                                inline,
                                inline_casts,
                            },
                        },
                        variant.cfg.clone(),
                        variant.documentation.clone(),
                    )
                })
                .collect();
        }
    }

    fn instantiate_monomorph(
        &self,
        generic_values: &[GenericArgument],
        library: &Library,
        out: &mut Monomorphs,
    ) {
        let mappings = self.generic_params.call(self.path.name(), generic_values);

        for variant in &self.variants {
            if let VariantBody::Body { ref body, .. } = variant.body {
                body.instantiate_monomorph(generic_values, library, out);
            }
        }

        let mangled_path = mangle::mangle_path(
            &self.path,
            generic_values,
            &library.get_config().export.mangle,
        );

        let monomorph = Enum::new(
            mangled_path,
            GenericParams::default(),
            self.repr,
            self.variants
                .iter()
                .map(|v| v.specialize(generic_values, &mappings, library.get_config()))
                .collect(),
            self.tag.clone(),
            self.cfg.clone(),
            self.annotations.clone(),
            self.documentation.clone(),
        );

        out.insert_enum(library, self, monomorph, generic_values.to_owned());
    }

    fn add_dependencies(&self, library: &Library, out: &mut Dependencies) {
        for variant in &self.variants {
            variant.add_dependencies(library, out);
        }
    }
}

impl Enum {
    /// Emit the tag enum and convenience methods for it.
    /// For enums with data this is only a part of the output,
    /// but for enums without data it's the whole output (modulo doc comments etc.).
    pub(crate) fn write_tag_enum<
        F: Write,
        LB: LanguageBackend,
        WV: Fn(&mut LB, &mut SourceWriter<F>, &EnumVariant),
    >(
        &self,
        config: &Config,
        language_backend: &mut LB,
        out: &mut SourceWriter<F>,
        size: Option<&str>,
        write_variant: WV,
    ) {
        let tag_name = self.tag_name();
        // Open the tag enum.
        match config.language {
            Language::C => {
                if let Some(prim) = size {
                    // If we need to specify size, then we have no choice but to create a typedef,
                    // so `config.style` is not respected.
                    write!(out, "enum");
                    if let Some(note) = self
                        .annotations
                        .deprecated_note(config, DeprecatedNoteKind::Enum)
                    {
                        write!(out, " {}", note);
                    }
                    write!(out, " {}", tag_name);

                    if config.cpp_compatible_c() {
                        out.new_line();
                        out.write("#ifdef __cplusplus");
                        out.new_line();
                        write!(out, "  : {}", prim);
                        out.new_line();
                        out.write("#endif // __cplusplus");
                        out.new_line();
                    }
                } else {
                    if config.style.generate_typedef() {
                        out.write("typedef ");
                    }
                    out.write("enum");
                    if let Some(note) = self
                        .annotations
                        .deprecated_note(config, DeprecatedNoteKind::Enum)
                    {
                        write!(out, " {}", note);
                    }
                    if config.style.generate_tag() {
                        write!(out, " {}", tag_name);
                    }
                }
            }
            Language::Cxx => {
                if config.enumeration.enum_class(&self.annotations) {
                    out.write("enum class");
                } else {
                    out.write("enum");
                }

                if self.annotations.must_use(config) {
                    if let Some(ref anno) = config.enumeration.must_use {
                        write!(out, " {}", anno)
                    }
                }

                if let Some(note) = self
                    .annotations
                    .deprecated_note(config, DeprecatedNoteKind::Enum)
                {
                    write!(out, " {}", note);
                }

                write!(out, " {}", tag_name);
                if let Some(prim) = size {
                    write!(out, " : {}", prim);
                }
            }
            Language::Cython => {
                if size.is_some() {
                    // If we need to specify size, then we have no choice but to create a typedef,
                    // so `config.style` is not respected.
                    write!(out, "cdef enum");
                } else {
                    write!(out, "{}enum {}", config.style.cython_def(), tag_name);
                }
            }
        }
        out.open_brace();

        // Emit enumerators for the tag enum.
        for (i, variant) in self.variants.iter().enumerate() {
            if i != 0 {
                out.new_line()
            }
            write_variant(language_backend, out, variant);
        }

        // Close the tag enum.
        if config.language == Language::C && size.is_none() && config.style.generate_typedef() {
            out.close_brace(false);
            write!(out, " {};", tag_name);
        } else {
            out.close_brace(true);
        }

        // Emit typedef specifying the tag enum's size if necessary.
        // In C++ enums can "inherit" from numeric types (`enum E: uint8_t { ... }`),
        // but in C `typedef uint8_t E` is the only way to give a fixed size to `E`.
        if let Some(prim) = size {
            if config.cpp_compatible_c() {
                out.new_line_if_not_start();
                out.write("#ifndef __cplusplus");
            }

            if config.language != Language::Cxx {
                out.new_line();
                write!(out, "{} {} {};", config.language.typedef(), prim, tag_name);
            }

            if config.cpp_compatible_c() {
                out.new_line_if_not_start();
                out.write("#endif // __cplusplus");
            }
        }

        // Emit convenience methods for the tag enum.
        self.write_derived_functions_enum(config, language_backend, out);
    }

    /// The code here mirrors the beginning of `Struct::write` and `Union::write`.
    pub(crate) fn open_struct_or_union<F: Write>(
        &self,
        config: &Config,
        out: &mut SourceWriter<F>,
        inline_tag_field: bool,
    ) {
        match config.language {
            Language::C if config.style.generate_typedef() => out.write("typedef "),
            Language::C | Language::Cxx => {}
            Language::Cython => out.write(config.style.cython_def()),
        }

        out.write(if inline_tag_field { "union" } else { "struct" });

        if self.annotations.must_use(config) {
            if let Some(ref anno) = config.structure.must_use {
                write!(out, " {}", anno);
            }
        }

        if let Some(note) = self
            .annotations
            .deprecated_note(config, DeprecatedNoteKind::Struct)
        {
            write!(out, " {} ", note);
        }

        if config.language != Language::C || config.style.generate_tag() {
            write!(out, " {}", self.export_name());
        }

        out.open_brace();

        // Emit the pre_body section, if relevant.
        if let Some(body) = config.export.pre_body(&self.path) {
            out.write_raw_block(body);
            out.new_line();
        }
    }

    /// Emit struct definitions for variants having data.
    pub(crate) fn write_variant_defs<F: Write, LB: LanguageBackend>(
        &self,
        config: &Config,
        language_backend: &mut LB, // TODO probably need only one of Config/LanguageBackend
        out: &mut SourceWriter<F>,
    ) {
        for variant in &self.variants {
            if let VariantBody::Body {
                ref body,
                inline: false,
                ..
            } = variant.body
            {
                out.new_line();
                out.new_line();
                let condition = variant.cfg.to_condition(config);
                // Cython doesn't support conditional enum variants.
                if config.language != Language::Cython {
                    condition.write_before(config, out);
                }
                language_backend.write_struct(out, body);
                if config.language != Language::Cython {
                    condition.write_after(config, out);
                }
            }
        }
    }

    /// Emit tag field that is separate from all variants.
    /// For non-inline tag scenario this is *the* tag field, and it does not exist in the variants.
    /// For the inline tag scenario this is just a convenience and another way
    /// to refer to the same tag that exist in all the variants.
    pub(crate) fn write_tag_field<F: Write>(
        &self,
        config: &Config,
        out: &mut SourceWriter<F>,
        size: Option<&str>,
        inline_tag_field: bool,
        tag_name: &str,
    ) {
        // C++ allows accessing only common initial sequence of union
        // fields so we have to wrap the tag field into an anonymous struct.
        let wrap_tag = inline_tag_field && config.language == Language::Cxx;

        if wrap_tag {
            out.write("struct");
            out.open_brace();
        }

        if config.language == Language::C && size.is_none() && !config.style.generate_typedef() {
            out.write("enum ");
        }

        write!(out, "{} tag;", tag_name);

        if wrap_tag {
            out.close_brace(true);
        }
    }

    /// Emit fields for all variants with data.
    pub(crate) fn write_variant_fields<
        F: Write,
        LB: LanguageBackend,
        WF: Fn(&mut LB, &mut SourceWriter<F>, &Field),
    >(
        &self,
        config: &Config,
        language_backend: &mut LB,
        out: &mut SourceWriter<F>,
        inline_tag_field: bool,
        write_field: WF,
    ) {
        let mut first = true;
        for variant in &self.variants {
            if let VariantBody::Body {
                name, body, inline, ..
            } = &variant.body
            {
                if !first {
                    out.new_line();
                }
                first = false;
                let condition = variant.cfg.to_condition(config);
                // Cython doesn't support conditional enum variants.
                if config.language != Language::Cython {
                    condition.write_before(config, out);
                }
                if *inline {
                    // Write definition of an inlined variant with data.
                    // Cython extern declarations don't manage layouts, layouts are defined entierly
                    // by the corresponding C code. So we can inline the unnamed struct and get the
                    // same observable result. Moreother we have to do it because Cython doesn't
                    // support unnamed structs.
                    // For the same reason with Cython we can omit per-variant tags (the first
                    // field) to avoid extra noise, the main `tag` is enough in this case.
                    if config.language != Language::Cython {
                        out.write("struct");
                        out.open_brace();
                    }
                    let start_field =
                        usize::from(inline_tag_field && config.language == Language::Cython);
                    out.write_vertical_source_list(
                        language_backend,
                        &body.fields[start_field..],
                        ListType::Cap(";"),
                        &write_field,
                    );
                    if config.language != Language::Cython {
                        out.close_brace(true);
                    }
                } else if config.style.generate_typedef() || config.language == Language::Cython {
                    write!(out, "{} {};", body.export_name(), name);
                } else {
                    write!(out, "struct {} {};", body.export_name(), name);
                }
                if config.language != Language::Cython {
                    condition.write_after(config, out);
                }
            }
        }
    }

    // Emit convenience methods for enums themselves.
    fn write_derived_functions_enum<F: Write, LB: LanguageBackend>(
        &self,
        config: &Config,
        language_backend: &mut LB,
        out: &mut SourceWriter<F>,
    ) {
        let has_data = self.tag.is_some();
        let tag_name = self.tag_name();
        if config.language != Language::Cxx {
            return;
        }

        // Emit an ostream function if required.
        if config.enumeration.derive_ostream(&self.annotations) {
            // For enums without data, this emits the serializer function for the
            // enum. For enums with data, this emits the serializer function for
            // the tag enum. In the latter case we need a couple of minor changes
            // due to the function living inside the top-level struct or enum.
            let stream = config
                .function
                .rename_args
                .apply("stream", IdentifierType::FunctionArg);
            let instance = config
                .function
                .rename_args
                .apply("instance", IdentifierType::FunctionArg);

            out.new_line();
            out.new_line();
            // For enums without data, we mark the function inline because the
            // header might get included into multiple compilation units that
            // get linked together, and not marking it inline would result in
            // multiply-defined symbol errors. For enums with data we don't have
            // the same problem, but mark it as a friend function of the
            // containing union/struct.
            // Note also that for enums with data, the case labels for switch
            // statements apparently need to be qualified to the top-level
            // generated struct or union. This is why the generated case labels
            // below use the A::B::C format for enums with data, with A being
            // self.export_name(). Failure to have that qualification results
            // in a surprising compilation failure for the generated header.
            write!(
                out,
                "{} std::ostream& operator<<(std::ostream& {}, const {}& {})",
                if has_data { "friend" } else { "inline" },
                stream,
                tag_name,
                instance,
            );

            out.open_brace();
            if has_data {
                // C++ name resolution rules are weird.
                write!(
                    out,
                    "using {} = {}::{};",
                    tag_name,
                    self.export_name(),
                    tag_name
                );
                out.new_line();
            }
            write!(out, "switch ({})", instance);
            out.open_brace();
            let vec: Vec<_> = self
                .variants
                .iter()
                .map(|x| {
                    format!(
                        "case {}::{}: {} << \"{}\"; break;",
                        tag_name, x.export_name, stream, x.export_name
                    )
                })
                .collect();
            out.write_vertical_source_list(
                language_backend,
                &vec[..],
                ListType::Join(""),
                |_, out, s| write!(out, "{}", s),
            );
            out.close_brace(false);
            out.new_line();

            write!(out, "return {};", stream);
            out.close_brace(false);

            if has_data {
                // For enums with data, this emits the serializer function for
                // the top-level union or struct.
                out.new_line();
                out.new_line();
                write!(
                    out,
                    "friend std::ostream& operator<<(std::ostream& {}, const {}& {})",
                    stream,
                    self.export_name(),
                    instance,
                );

                out.open_brace();

                // C++ name resolution rules are weird.
                write!(
                    out,
                    "using {} = {}::{};",
                    tag_name,
                    self.export_name(),
                    tag_name
                );
                out.new_line();

                write!(out, "switch ({}.tag)", instance);
                out.open_brace();
                let vec: Vec<_> = self
                    .variants
                    .iter()
                    .map(|x| {
                        let tag_str = format!("\"{}\"", x.export_name);
                        if let VariantBody::Body {
                            ref name, ref body, ..
                        } = x.body
                        {
                            format!(
                                "case {}::{}: {} << {}{}{}.{}; break;",
                                tag_name,
                                x.export_name,
                                stream,
                                if body.has_tag_field { "" } else { &tag_str },
                                if body.has_tag_field { "" } else { " << " },
                                instance,
                                name,
                            )
                        } else {
                            format!(
                                "case {}::{}: {} << {}; break;",
                                tag_name, x.export_name, stream, tag_str,
                            )
                        }
                    })
                    .collect();
                out.write_vertical_source_list(
                    language_backend,
                    &vec[..],
                    ListType::Join(""),
                    |_, out, s| write!(out, "{}", s),
                );
                out.close_brace(false);
                out.new_line();

                write!(out, "return {};", stream);
                out.close_brace(false);
            }
        }
    }

    // Emit convenience methods for structs or unions produced for enums with data.
    pub(crate) fn write_derived_functions_data<
        F: Write,
        LB: LanguageBackend,
        WF: Fn(&mut LB, &mut SourceWriter<F>, &Field),
    >(
        &self,
        config: &Config,
        language_backend: &mut LB,
        out: &mut SourceWriter<F>,
        tag_name: &str,
        write_field: WF,
    ) {
        if config.language != Language::Cxx {
            return;
        }

        if config.enumeration.derive_helper_methods(&self.annotations) {
            for variant in &self.variants {
                out.new_line();
                out.new_line();

                let condition = variant.cfg.to_condition(config);
                condition.write_before(config, out);

                let arg_renamer = |name: &str| {
                    config
                        .function
                        .rename_args
                        .apply(name, IdentifierType::FunctionArg)
                        .into_owned()
                };

                macro_rules! write_attrs {
                    ($op:expr) => {{
                        if let Some(Some(attrs)) =
                            variant
                                .body
                                .annotations()
                                .atom(concat!("variant-", $op, "-attributes"))
                        {
                            write!(out, "{} ", attrs);
                        }
                    }};
                }

                write_attrs!("constructor");
                write!(out, "static {} {}(", self.export_name, variant.export_name);

                if let VariantBody::Body { ref body, .. } = variant.body {
                    let skip_fields = body.has_tag_field as usize;
                    let vec: Vec<_> = body
                        .fields
                        .iter()
                        .skip(skip_fields)
                        .map(|field| {
                            Field::from_name_and_type(
                                // const-ref args to constructor
                                arg_renamer(&field.name),
                                Type::const_ref_to(&field.ty),
                            )
                        })
                        .collect();
                    out.write_vertical_source_list(
                        language_backend,
                        &vec[..],
                        ListType::Join(","),
                        &write_field,
                    );
                }

                write!(out, ")");
                out.open_brace();

                write!(out, "{} result;", self.export_name);

                if let VariantBody::Body {
                    name: ref variant_name,
                    ref body,
                    ..
                } = variant.body
                {
                    let skip_fields = body.has_tag_field as usize;
                    for field in body.fields.iter().skip(skip_fields) {
                        out.new_line();
                        match field.ty {
                            Type::Array(ref ty, ref length) => {
                                // arrays are not assignable in C++ so we
                                // need to manually copy the elements
                                write!(out, "for (int i = 0; i < {}; i++)", length.as_str());
                                out.open_brace();
                                write!(out, "::new (&result.{}.{}[i]) (", variant_name, field.name);
                                language_backend.write_type(out, ty);
                                write!(out, ")({}[i]);", arg_renamer(&field.name));
                                out.close_brace(false);
                            }
                            ref ty => {
                                write!(out, "::new (&result.{}.{}) (", variant_name, field.name);
                                language_backend.write_type(out, ty);
                                write!(out, ")({});", arg_renamer(&field.name));
                            }
                        }
                    }
                }

                out.new_line();
                write!(out, "result.tag = {}::{};", tag_name, variant.export_name);
                out.new_line();
                write!(out, "return result;");
                out.close_brace(false);

                out.new_line();
                out.new_line();

                write_attrs!("is");
                // FIXME: create a config for method case
                write!(out, "bool Is{}() const", variant.export_name);
                out.open_brace();
                write!(out, "return tag == {}::{};", tag_name, variant.export_name);
                out.close_brace(false);

                let assert_name = match config.enumeration.cast_assert_name {
                    Some(ref n) => &**n,
                    None => "assert",
                };

                let mut derive_casts = |const_casts: bool| {
                    let (member_name, body, inline_casts) = match variant.body {
                        VariantBody::Body {
                            ref name,
                            ref body,
                            inline_casts,
                            ..
                        } => (name, body, inline_casts),
                        VariantBody::Empty(..) => return,
                    };

                    let skip_fields = body.has_tag_field as usize;
                    let field_count = body.fields.len() - skip_fields;
                    if field_count == 0 {
                        return;
                    }

                    out.new_line();
                    out.new_line();

                    if const_casts {
                        write_attrs!("const-cast");
                    } else {
                        write_attrs!("mut-cast");
                    }
                    if inline_casts {
                        let field = body.fields.last().unwrap();
                        let return_type = field.ty.clone();
                        let return_type = Type::Ptr {
                            ty: Box::new(return_type),
                            is_const: const_casts,
                            is_ref: true,
                            is_nullable: false,
                        };
                        language_backend.write_type(out, &return_type);
                    } else if const_casts {
                        write!(out, "const {}&", body.export_name());
                    } else {
                        write!(out, "{}&", body.export_name());
                    }

                    write!(out, " As{}()", variant.export_name);
                    if const_casts {
                        write!(out, " const");
                    }
                    out.open_brace();
                    write!(out, "{}(Is{}());", assert_name, variant.export_name);
                    out.new_line();
                    write!(out, "return {}", member_name);
                    if inline_casts {
                        write!(out, "._0");
                    }
                    write!(out, ";");
                    out.close_brace(false);
                };

                if config.enumeration.derive_const_casts(&self.annotations) {
                    derive_casts(true)
                }

                if config.enumeration.derive_mut_casts(&self.annotations) {
                    derive_casts(false)
                }

                condition.write_after(config, out);
            }
        }

        let other = config
            .function
            .rename_args
            .apply("other", IdentifierType::FunctionArg);

        macro_rules! write_attrs {
            ($op:expr) => {{
                if let Some(Some(attrs)) = self.annotations.atom(concat!($op, "-attributes")) {
                    write!(out, "{} ", attrs);
                }
            }};
        }

        if self.can_derive_eq() && config.structure.derive_eq(&self.annotations) {
            out.new_line();
            out.new_line();
            write_attrs!("eq");
            write!(
                out,
                "bool operator==(const {}& {}) const",
                self.export_name, other
            );
            out.open_brace();
            write!(out, "if (tag != {}.tag)", other);
            out.open_brace();
            write!(out, "return false;");
            out.close_brace(false);
            out.new_line();
            write!(out, "switch (tag)");
            out.open_brace();
            let mut exhaustive = true;
            for variant in &self.variants {
                if let VariantBody::Body {
                    name: ref variant_name,
                    ..
                } = variant.body
                {
                    let condition = variant.cfg.to_condition(config);
                    condition.write_before(config, out);
                    write!(
                        out,
                        "case {}::{}: return {} == {}.{};",
                        self.tag.as_ref().unwrap(),
                        variant.export_name,
                        variant_name,
                        other,
                        variant_name
                    );
                    condition.write_after(config, out);
                    out.new_line();
                } else {
                    exhaustive = false;
                }
            }
            if !exhaustive {
                write!(out, "default: break;");
            }
            out.close_brace(false);

            out.new_line();
            write!(out, "return true;");

            out.close_brace(false);

            if config.structure.derive_neq(&self.annotations) {
                out.new_line();
                out.new_line();
                write_attrs!("neq");
                write!(
                    out,
                    "bool operator!=(const {}& {}) const",
                    self.export_name, other
                );
                out.open_brace();
                write!(out, "return !(*this == {});", other);
                out.close_brace(false);
            }
        }

        if config
            .enumeration
            .private_default_tagged_enum_constructor(&self.annotations)
        {
            out.new_line();
            out.new_line();
            write!(out, "private:");
            out.new_line();
            write!(out, "{}()", self.export_name);
            out.open_brace();
            out.close_brace(false);
            out.new_line();
            write!(out, "public:");
            out.new_line();
        }

        if config
            .enumeration
            .derive_tagged_enum_destructor(&self.annotations)
        {
            out.new_line();
            out.new_line();
            write_attrs!("destructor");
            write!(out, "~{}()", self.export_name);
            out.open_brace();
            write!(out, "switch (tag)");
            out.open_brace();
            let mut exhaustive = true;
            for variant in &self.variants {
                if let VariantBody::Body {
                    ref name, ref body, ..
                } = variant.body
                {
                    let condition = variant.cfg.to_condition(config);
                    condition.write_before(config, out);
                    write!(
                        out,
                        "case {}::{}: {}.~{}(); break;",
                        self.tag.as_ref().unwrap(),
                        variant.export_name,
                        name,
                        body.export_name(),
                    );
                    condition.write_after(config, out);
                    out.new_line();
                } else {
                    exhaustive = false;
                }
            }
            if !exhaustive {
                write!(out, "default: break;");
            }
            out.close_brace(false);
            out.close_brace(false);
        }

        if config
            .enumeration
            .derive_tagged_enum_copy_constructor(&self.annotations)
        {
            out.new_line();
            out.new_line();
            write_attrs!("copy-constructor");
            write!(
                out,
                "{}(const {}& {})",
                self.export_name, self.export_name, other
            );
            out.new_line();
            write!(out, " : tag({}.tag)", other);
            out.open_brace();
            write!(out, "switch (tag)");
            out.open_brace();
            let mut exhaustive = true;
            for variant in &self.variants {
                if let VariantBody::Body {
                    ref name, ref body, ..
                } = variant.body
                {
                    let condition = variant.cfg.to_condition(config);
                    condition.write_before(config, out);
                    write!(
                        out,
                        "case {}::{}: ::new (&{}) ({})({}.{}); break;",
                        self.tag.as_ref().unwrap(),
                        variant.export_name,
                        name,
                        body.export_name(),
                        other,
                        name,
                    );
                    condition.write_after(config, out);
                    out.new_line();
                } else {
                    exhaustive = false;
                }
            }
            if !exhaustive {
                write!(out, "default: break;");
            }
            out.close_brace(false);
            out.close_brace(false);

            if config
                .enumeration
                .derive_tagged_enum_copy_assignment(&self.annotations)
            {
                out.new_line();
                write_attrs!("copy-assignment");
                write!(
                    out,
                    "{}& operator=(const {}& {})",
                    self.export_name, self.export_name, other
                );
                out.open_brace();
                write!(out, "if (this != &{})", other);
                out.open_brace();
                write!(out, "this->~{}();", self.export_name);
                out.new_line();
                write!(out, "new (this) {}({});", self.export_name, other);
                out.close_brace(false);
                out.new_line();
                write!(out, "return *this;");
                out.close_brace(false);
            }
        }
    }

    pub fn simplify_standard_types(&mut self, config: &Config) {
        for variant in &mut self.variants {
            variant.simplify_standard_types(config);
        }
    }
}
