use crate::ecs::ui::immediate::ImmediateTextInstance;
use crate::ecs::world::World;
use crate::render::wgpu::text_mesh::generate_text_mesh;

pub fn sync_text_meshes_system(world: &mut World) {
    let entities: Vec<_> = world.query_entities(crate::ecs::world::TEXT).collect();
    let _span = tracing::info_span!("text_meshes", count = entities.len()).entered();

    for entity in entities {
        let (text_index, font_index, properties, is_dirty) = {
            if let Some(text) = world.get_text(entity) {
                if !text.dirty {
                    continue;
                }
                (
                    text.text_index,
                    text.font_index,
                    text.properties.clone(),
                    text.dirty,
                )
            } else {
                continue;
            }
        };

        if !is_dirty {
            continue;
        }

        let text_content = world.resources.text_cache.get_text(text_index);
        if text_content.is_none() {
            continue;
        }
        let text_content = text_content.unwrap();

        let font = world.resources.text_cache.font_manager.get_font(font_index);
        if font.is_none() {
            continue;
        }
        let font = font.unwrap();

        let mesh = generate_text_mesh(text_content, font, &properties);

        if let Some(text) = world.get_text_mut(entity) {
            text.cached_mesh = Some(mesh);
            text.dirty = false;
        }
    }
}

pub fn sync_hud_text_system(world: &mut World) {
    let entities: Vec<_> = world.query_entities(crate::ecs::world::HUD_TEXT).collect();
    let _span = tracing::info_span!("hud_text", count = entities.len()).entered();

    for entity in entities {
        let (text_index, font_index, properties, is_dirty) = {
            if let Some(hud_text) = world.get_hud_text(entity) {
                if !hud_text.dirty {
                    continue;
                }
                (
                    hud_text.text_index,
                    hud_text.font_index,
                    hud_text.properties.clone(),
                    hud_text.dirty,
                )
            } else {
                continue;
            }
        };

        if !is_dirty {
            continue;
        }

        let text_content = world.resources.text_cache.get_text(text_index);
        if text_content.is_none() {
            continue;
        }
        let text_content = text_content.unwrap();

        let font = world.resources.text_cache.font_manager.get_font(font_index);
        if font.is_none() {
            continue;
        }
        let font = font.unwrap();

        let mesh = generate_text_mesh(text_content, font, &properties);

        if let Some(hud_text) = world.get_hud_text_mut(entity) {
            hud_text.cached_mesh = Some(mesh);
            hud_text.dirty = false;
        }
    }
}

pub fn sync_immediate_ui_text_system(world: &mut World) {
    if !world.resources.immediate_ui.enabled {
        return;
    }

    let widget_count = world.resources.immediate_ui.frame_widgets.len();
    if widget_count == 0 {
        return;
    }

    let _span = tracing::info_span!("immediate_ui_text", count = widget_count).entered();

    let font = world.resources.text_cache.font_manager.get_font(0);
    if font.is_none() {
        return;
    }
    let font = font.unwrap();

    let widgets: Vec<_> = world.resources.immediate_ui.frame_widgets.clone();
    let mut text_meshes = Vec::with_capacity(widgets.len());

    for widget in widgets {
        let mesh = generate_text_mesh(&widget.text, font, &widget.properties);

        text_meshes.push(ImmediateTextInstance {
            mesh,
            position: widget.position,
            color: widget.properties.color,
            outline_color: widget.properties.outline_color,
            outline_width: widget.properties.outline_width,
            font_index: 0,
            clip_rect: widget.clip_rect,
            layer: widget.layer,
            z_index: widget.z_index,
        });
    }

    world.resources.immediate_ui.frame_text_meshes = text_meshes;
}
