//! Defines hir-level representation of structs, enums and unions

use base_db::CrateId;
use bitflags::bitflags;
use cfg::CfgOptions;
use either::Either;

use hir_expand::{
    name::{AsName, Name},
    HirFileId, InFile,
};
use intern::Interned;
use la_arena::Arena;
use rustc_abi::{Align, Integer, IntegerType, ReprFlags, ReprOptions};
use syntax::ast::{self, HasName, HasVisibility};
use triomphe::Arc;

use crate::{
    builtin_type::{BuiltinInt, BuiltinUint},
    db::DefDatabase,
    item_tree::{AttrOwner, Field, FieldAstId, Fields, ItemTree, ModItem, RawVisibilityId},
    lang_item::LangItem,
    lower::LowerCtx,
    nameres::diagnostics::{DefDiagnostic, DefDiagnostics},
    trace::Trace,
    tt::{Delimiter, DelimiterKind, Leaf, Subtree, TokenTree},
    type_ref::TypeRef,
    visibility::RawVisibility,
    EnumId, EnumVariantId, LocalFieldId, LocalModuleId, Lookup, StructId, UnionId,
};

/// Note that we use `StructData` for unions as well!
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct StructData {
    pub name: Name,
    pub variant_data: Arc<VariantData>,
    pub repr: Option<ReprOptions>,
    pub visibility: RawVisibility,
    pub flags: StructFlags,
}

bitflags! {
    #[derive(Debug, Copy, Clone, PartialEq, Eq)]
    pub struct StructFlags: u8 {
        const NO_FLAGS         = 0;
        /// Indicates whether the struct is `PhantomData`.
        const IS_PHANTOM_DATA  = 1 << 2;
        /// Indicates whether the struct has a `#[fundamental]` attribute.
        const IS_FUNDAMENTAL   = 1 << 3;
        // FIXME: should this be a flag?
        /// Indicates whether the struct has a `#[rustc_has_incoherent_inherent_impls]` attribute.
        const IS_RUSTC_HAS_INCOHERENT_INHERENT_IMPL      = 1 << 4;
        /// Indicates whether this struct is `Box`.
        const IS_BOX           = 1 << 5;
        /// Indicates whether this struct is `ManuallyDrop`.
        const IS_MANUALLY_DROP = 1 << 6;
        /// Indicates whether this struct is `UnsafeCell`.
        const IS_UNSAFE_CELL   = 1 << 7;
    }
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct EnumData {
    pub name: Name,
    pub variants: Box<[(EnumVariantId, Name)]>,
    pub repr: Option<ReprOptions>,
    pub visibility: RawVisibility,
    pub rustc_has_incoherent_inherent_impls: bool,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct EnumVariantData {
    pub name: Name,
    pub variant_data: Arc<VariantData>,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum VariantData {
    Record(Arena<FieldData>),
    Tuple(Arena<FieldData>),
    Unit,
}

/// A single field of an enum variant or struct
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct FieldData {
    pub name: Name,
    pub type_ref: Interned<TypeRef>,
    pub visibility: RawVisibility,
}

fn repr_from_value(
    db: &dyn DefDatabase,
    krate: CrateId,
    item_tree: &ItemTree,
    of: AttrOwner,
) -> Option<ReprOptions> {
    item_tree.attrs(db, krate, of).by_key("repr").tt_values().find_map(parse_repr_tt)
}

fn parse_repr_tt(tt: &Subtree) -> Option<ReprOptions> {
    match tt.delimiter {
        Delimiter { kind: DelimiterKind::Parenthesis, .. } => {}
        _ => return None,
    }

    let mut flags = ReprFlags::empty();
    let mut int = None;
    let mut max_align: Option<Align> = None;
    let mut min_pack: Option<Align> = None;

    let mut tts = tt.token_trees.iter().peekable();
    while let Some(tt) = tts.next() {
        if let TokenTree::Leaf(Leaf::Ident(ident)) = tt {
            flags.insert(match &*ident.text {
                "packed" => {
                    let pack = if let Some(TokenTree::Subtree(tt)) = tts.peek() {
                        tts.next();
                        if let Some(TokenTree::Leaf(Leaf::Literal(lit))) = tt.token_trees.first() {
                            lit.text.parse().unwrap_or_default()
                        } else {
                            0
                        }
                    } else {
                        0
                    };
                    let pack = Align::from_bytes(pack).unwrap_or(Align::ONE);
                    min_pack =
                        Some(if let Some(min_pack) = min_pack { min_pack.min(pack) } else { pack });
                    ReprFlags::empty()
                }
                "align" => {
                    if let Some(TokenTree::Subtree(tt)) = tts.peek() {
                        tts.next();
                        if let Some(TokenTree::Leaf(Leaf::Literal(lit))) = tt.token_trees.first() {
                            if let Ok(align) = lit.text.parse() {
                                let align = Align::from_bytes(align).ok();
                                max_align = max_align.max(align);
                            }
                        }
                    }
                    ReprFlags::empty()
                }
                "C" => ReprFlags::IS_C,
                "transparent" => ReprFlags::IS_TRANSPARENT,
                "simd" => ReprFlags::IS_SIMD,
                repr => {
                    if let Some(builtin) = BuiltinInt::from_suffix(repr)
                        .map(Either::Left)
                        .or_else(|| BuiltinUint::from_suffix(repr).map(Either::Right))
                    {
                        int = Some(match builtin {
                            Either::Left(bi) => match bi {
                                BuiltinInt::Isize => IntegerType::Pointer(true),
                                BuiltinInt::I8 => IntegerType::Fixed(Integer::I8, true),
                                BuiltinInt::I16 => IntegerType::Fixed(Integer::I16, true),
                                BuiltinInt::I32 => IntegerType::Fixed(Integer::I32, true),
                                BuiltinInt::I64 => IntegerType::Fixed(Integer::I64, true),
                                BuiltinInt::I128 => IntegerType::Fixed(Integer::I128, true),
                            },
                            Either::Right(bu) => match bu {
                                BuiltinUint::Usize => IntegerType::Pointer(false),
                                BuiltinUint::U8 => IntegerType::Fixed(Integer::I8, false),
                                BuiltinUint::U16 => IntegerType::Fixed(Integer::I16, false),
                                BuiltinUint::U32 => IntegerType::Fixed(Integer::I32, false),
                                BuiltinUint::U64 => IntegerType::Fixed(Integer::I64, false),
                                BuiltinUint::U128 => IntegerType::Fixed(Integer::I128, false),
                            },
                        });
                    }
                    ReprFlags::empty()
                }
            })
        }
    }

    Some(ReprOptions { int, align: max_align, pack: min_pack, flags, field_shuffle_seed: 0 })
}

impl StructData {
    #[inline]
    pub(crate) fn struct_data_query(db: &dyn DefDatabase, id: StructId) -> Arc<StructData> {
        db.struct_data_with_diagnostics(id).0
    }

    pub(crate) fn struct_data_with_diagnostics_query(
        db: &dyn DefDatabase,
        id: StructId,
    ) -> (Arc<StructData>, DefDiagnostics) {
        let loc = id.lookup(db);
        let krate = loc.container.krate;
        let item_tree = loc.id.item_tree(db);
        let repr = repr_from_value(db, krate, &item_tree, ModItem::from(loc.id.value).into());
        let cfg_options = db.crate_graph()[loc.container.krate].cfg_options.clone();

        let attrs = item_tree.attrs(db, loc.container.krate, ModItem::from(loc.id.value).into());

        let mut flags = StructFlags::NO_FLAGS;
        if attrs.by_key("rustc_has_incoherent_inherent_impls").exists() {
            flags |= StructFlags::IS_RUSTC_HAS_INCOHERENT_INHERENT_IMPL;
        }
        if attrs.by_key("fundamental").exists() {
            flags |= StructFlags::IS_FUNDAMENTAL;
        }
        if let Some(lang) = attrs.lang_item() {
            match lang {
                LangItem::PhantomData => flags |= StructFlags::IS_PHANTOM_DATA,
                LangItem::OwnedBox => flags |= StructFlags::IS_BOX,
                LangItem::ManuallyDrop => flags |= StructFlags::IS_MANUALLY_DROP,
                LangItem::UnsafeCell => flags |= StructFlags::IS_UNSAFE_CELL,
                _ => (),
            }
        }

        let strukt = &item_tree[loc.id.value];
        let (variant_data, diagnostics) = lower_fields(
            db,
            krate,
            loc.id.file_id(),
            loc.container.local_id,
            &item_tree,
            &cfg_options,
            &strukt.fields,
            None,
        );
        (
            Arc::new(StructData {
                name: strukt.name.clone(),
                variant_data: Arc::new(variant_data),
                repr,
                visibility: item_tree[strukt.visibility].clone(),
                flags,
            }),
            DefDiagnostics::new(diagnostics),
        )
    }

    #[inline]
    pub(crate) fn union_data_query(db: &dyn DefDatabase, id: UnionId) -> Arc<StructData> {
        db.union_data_with_diagnostics(id).0
    }

    pub(crate) fn union_data_with_diagnostics_query(
        db: &dyn DefDatabase,
        id: UnionId,
    ) -> (Arc<StructData>, DefDiagnostics) {
        let loc = id.lookup(db);
        let krate = loc.container.krate;
        let item_tree = loc.id.item_tree(db);
        let repr = repr_from_value(db, krate, &item_tree, ModItem::from(loc.id.value).into());
        let cfg_options = db.crate_graph()[loc.container.krate].cfg_options.clone();

        let attrs = item_tree.attrs(db, loc.container.krate, ModItem::from(loc.id.value).into());
        let mut flags = StructFlags::NO_FLAGS;
        if attrs.by_key("rustc_has_incoherent_inherent_impls").exists() {
            flags |= StructFlags::IS_RUSTC_HAS_INCOHERENT_INHERENT_IMPL;
        }
        if attrs.by_key("fundamental").exists() {
            flags |= StructFlags::IS_FUNDAMENTAL;
        }

        let union = &item_tree[loc.id.value];
        let (variant_data, diagnostics) = lower_fields(
            db,
            krate,
            loc.id.file_id(),
            loc.container.local_id,
            &item_tree,
            &cfg_options,
            &union.fields,
            None,
        );
        (
            Arc::new(StructData {
                name: union.name.clone(),
                variant_data: Arc::new(variant_data),
                repr,
                visibility: item_tree[union.visibility].clone(),
                flags,
            }),
            DefDiagnostics::new(diagnostics),
        )
    }
}

impl EnumData {
    pub(crate) fn enum_data_query(db: &dyn DefDatabase, e: EnumId) -> Arc<EnumData> {
        let loc = e.lookup(db);
        let krate = loc.container.krate;
        let item_tree = loc.id.item_tree(db);
        let repr = repr_from_value(db, krate, &item_tree, ModItem::from(loc.id.value).into());
        let rustc_has_incoherent_inherent_impls = item_tree
            .attrs(db, loc.container.krate, ModItem::from(loc.id.value).into())
            .by_key("rustc_has_incoherent_inherent_impls")
            .exists();

        let enum_ = &item_tree[loc.id.value];

        Arc::new(EnumData {
            name: enum_.name.clone(),
            variants: loc.container.def_map(db).enum_definitions[&e]
                .iter()
                .map(|&id| (id, item_tree[id.lookup(db).id.value].name.clone()))
                .collect(),
            repr,
            visibility: item_tree[enum_.visibility].clone(),
            rustc_has_incoherent_inherent_impls,
        })
    }

    pub fn variant(&self, name: &Name) -> Option<EnumVariantId> {
        let &(id, _) = self.variants.iter().find(|(_id, n)| n == name)?;
        Some(id)
    }

    pub fn variant_body_type(&self) -> IntegerType {
        match self.repr {
            Some(ReprOptions { int: Some(builtin), .. }) => builtin,
            _ => IntegerType::Pointer(true),
        }
    }
}

impl EnumVariantData {
    #[inline]
    pub(crate) fn enum_variant_data_query(
        db: &dyn DefDatabase,
        e: EnumVariantId,
    ) -> Arc<EnumVariantData> {
        db.enum_variant_data_with_diagnostics(e).0
    }

    pub(crate) fn enum_variant_data_with_diagnostics_query(
        db: &dyn DefDatabase,
        e: EnumVariantId,
    ) -> (Arc<EnumVariantData>, DefDiagnostics) {
        let loc = e.lookup(db);
        let container = loc.parent.lookup(db).container;
        let krate = container.krate;
        let item_tree = loc.id.item_tree(db);
        let cfg_options = db.crate_graph()[krate].cfg_options.clone();
        let variant = &item_tree[loc.id.value];

        let (var_data, diagnostics) = lower_fields(
            db,
            krate,
            loc.id.file_id(),
            container.local_id,
            &item_tree,
            &cfg_options,
            &variant.fields,
            Some(item_tree[loc.parent.lookup(db).id.value].visibility),
        );

        (
            Arc::new(EnumVariantData {
                name: variant.name.clone(),
                variant_data: Arc::new(var_data),
            }),
            DefDiagnostics::new(diagnostics),
        )
    }
}

impl VariantData {
    pub fn fields(&self) -> &Arena<FieldData> {
        const EMPTY: &Arena<FieldData> = &Arena::new();
        match &self {
            VariantData::Record(fields) | VariantData::Tuple(fields) => fields,
            _ => EMPTY,
        }
    }

    // FIXME: Linear lookup
    pub fn field(&self, name: &Name) -> Option<LocalFieldId> {
        self.fields().iter().find_map(|(id, data)| if &data.name == name { Some(id) } else { None })
    }

    pub fn kind(&self) -> StructKind {
        match self {
            VariantData::Record(_) => StructKind::Record,
            VariantData::Tuple(_) => StructKind::Tuple,
            VariantData::Unit => StructKind::Unit,
        }
    }
}

#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum StructKind {
    Tuple,
    Record,
    Unit,
}

pub(crate) fn lower_struct(
    db: &dyn DefDatabase,
    trace: &mut Trace<FieldData, Either<ast::TupleField, ast::RecordField>>,
    ast: &InFile<ast::StructKind>,
    krate: CrateId,
    item_tree: &ItemTree,
    fields: &Fields,
) -> StructKind {
    let ctx = LowerCtx::new(db, ast.file_id);

    match (&ast.value, fields) {
        (ast::StructKind::Tuple(fl), Fields::Tuple(fields)) => {
            let cfg_options = &db.crate_graph()[krate].cfg_options;
            for ((i, fd), item_tree_id) in fl.fields().enumerate().zip(fields.clone()) {
                if !item_tree.attrs(db, krate, item_tree_id.into()).is_cfg_enabled(cfg_options) {
                    continue;
                }

                trace.alloc(
                    || Either::Left(fd.clone()),
                    || FieldData {
                        name: Name::new_tuple_field(i),
                        type_ref: Interned::new(TypeRef::from_ast_opt(&ctx, fd.ty())),
                        visibility: RawVisibility::from_ast(db, fd.visibility(), &mut |range| {
                            ctx.span_map().span_for_range(range).ctx
                        }),
                    },
                );
            }
            StructKind::Tuple
        }
        (ast::StructKind::Record(fl), Fields::Record(fields)) => {
            let cfg_options = &db.crate_graph()[krate].cfg_options;
            for (fd, item_tree_id) in fl.fields().zip(fields.clone()) {
                if !item_tree.attrs(db, krate, item_tree_id.into()).is_cfg_enabled(cfg_options) {
                    continue;
                }

                trace.alloc(
                    || Either::Right(fd.clone()),
                    || FieldData {
                        name: fd.name().map(|n| n.as_name()).unwrap_or_else(Name::missing),
                        type_ref: Interned::new(TypeRef::from_ast_opt(&ctx, fd.ty())),
                        visibility: RawVisibility::from_ast(db, fd.visibility(), &mut |range| {
                            ctx.span_map().span_for_range(range).ctx
                        }),
                    },
                );
            }
            StructKind::Record
        }
        _ => StructKind::Unit,
    }
}

fn lower_fields(
    db: &dyn DefDatabase,
    krate: CrateId,
    current_file_id: HirFileId,
    container: LocalModuleId,
    item_tree: &ItemTree,
    cfg_options: &CfgOptions,
    fields: &Fields,
    override_visibility: Option<RawVisibilityId>,
) -> (VariantData, Vec<DefDiagnostic>) {
    let mut diagnostics = Vec::new();
    match fields {
        Fields::Record(flds) => {
            let mut arena = Arena::new();
            for field_id in flds.clone() {
                let attrs = item_tree.attrs(db, krate, field_id.into());
                let field = &item_tree[field_id];
                if attrs.is_cfg_enabled(cfg_options) {
                    arena.alloc(lower_field(item_tree, field, override_visibility));
                } else {
                    diagnostics.push(DefDiagnostic::unconfigured_code(
                        container,
                        InFile::new(
                            current_file_id,
                            match field.ast_id {
                                FieldAstId::Record(it) => it.erase(),
                                FieldAstId::Tuple(it) => it.erase(),
                            },
                        ),
                        attrs.cfg().unwrap(),
                        cfg_options.clone(),
                    ))
                }
            }
            (VariantData::Record(arena), diagnostics)
        }
        Fields::Tuple(flds) => {
            let mut arena = Arena::new();
            for field_id in flds.clone() {
                let attrs = item_tree.attrs(db, krate, field_id.into());
                let field = &item_tree[field_id];
                if attrs.is_cfg_enabled(cfg_options) {
                    arena.alloc(lower_field(item_tree, field, override_visibility));
                } else {
                    diagnostics.push(DefDiagnostic::unconfigured_code(
                        container,
                        InFile::new(
                            current_file_id,
                            match field.ast_id {
                                FieldAstId::Record(it) => it.erase(),
                                FieldAstId::Tuple(it) => it.erase(),
                            },
                        ),
                        attrs.cfg().unwrap(),
                        cfg_options.clone(),
                    ))
                }
            }
            (VariantData::Tuple(arena), diagnostics)
        }
        Fields::Unit => (VariantData::Unit, diagnostics),
    }
}

fn lower_field(
    item_tree: &ItemTree,
    field: &Field,
    override_visibility: Option<RawVisibilityId>,
) -> FieldData {
    FieldData {
        name: field.name.clone(),
        type_ref: field.type_ref.clone(),
        visibility: item_tree[override_visibility.unwrap_or(field.visibility)].clone(),
    }
}
