use crate::enums::variant::Variant;
use crate::records::index::Index;
use crate::records::scope::Scope;
use crate::records::subtyping::Subtyping;
use crate::records::subtyping_environment::SubtypingEnvironment;
use crate::records::subtyping_result::SubtypingResult;
use crate::records::type_iterator::TypeIterator;
use crate::records::union_type::UnionType;
use crate::type_aliases::component::Component;
use crate::type_aliases::type_id::TypeId;

impl Subtyping {
    pub fn is_covariant_with_subtyping_environment_union_type_type_id_not_null_scope(
        &mut self,
        env: &mut SubtypingEnvironment,
        sub_union: &UnionType,
        super_ty: TypeId,
        scope: *mut Scope,
    ) -> SubtypingResult {
        let mut result = SubtypingResult {
            is_subtype: true,
            ..Default::default()
        };
        let mut index = 0usize;
        let mut it = TypeIterator::<UnionType>::type_iterator_type(sub_union as *const UnionType);
        let end_it = TypeIterator::<UnionType>::type_iterator_default();
        while it.operator_ne(&end_it) {
            let ty = it.operator_deref();
            it.operator_inc();

            let mut next = self
                .is_covariant_with_subtyping_environment_type_id_type_id_not_null_scope(
                    env, ty, super_ty, scope,
                );
            if next.normalization_too_complex {
                return SubtypingResult {
                    is_subtype: false,
                    normalization_too_complex: true,
                    ..Default::default()
                };
            }
            next.with_sub_component(Component::Index(Index {
                index,
                variant: Variant::Union,
            }));
            result.and_also(
                next,
                crate::enums::subtyping_suppression_policy::SubtypingSuppressionPolicy::Any,
            );
            index += 1;
        }
        result
    }
}
