//! Dedicated post-process volume inspector with inherit/override UX.

use bevy::prelude::*;
use bevy_egui::egui;
use egui_phosphor_icons::icons;
use settings::ProjectSettings;
use shared::{ColorDesc, PostProcessVolumeDesc, PostProcessVolumeOverrides, RenderingProfileAsset};
use walkdir::WalkDir;

use crate::history::set_post_process_volume_with_history;
use crate::ui::inspector::{
    apply_component_card_response, component_card, component_card_context, ComponentCardOptions,
};
use crate::ui::inspector::{property_row, text_field_width};
use crate::ui::theme::panel_heading;

pub fn post_process_volume_inspector_ui(world: &mut World, ui: &mut egui::Ui, entity: Entity) {
    let Some(mut volume) = world.get::<PostProcessVolumeDesc>(entity).cloned() else {
        return;
    };
    let project = world.resource::<ProjectSettings>().rendering.clone();
    let original = volume.clone();
    let mut changed = false;

    let card = component_card_context(
        world,
        entity,
        ComponentCardOptions::removable(
            shared::COMPONENT_POST_PROCESS_VOLUME,
            "Post Process Volume",
            icons::APERTURE,
        ),
    );
    let card_response = component_card(ui, &card, |ui| {
        property_row(ui, "Label (HUD)", |ui| {
            let mut label_text = volume.label.clone().unwrap_or_default();
            if ui
                .add_sized(
                    [text_field_width(ui), 20.0],
                    egui::TextEdit::singleline(&mut label_text),
                )
                .changed()
            {
                volume.label = if label_text.is_empty() {
                    None
                } else {
                    Some(label_text)
                };
                changed = true;
            }
        });
        property_row(ui, "Priority", |ui| {
            ui.add(egui::Slider::new(&mut volume.priority, -10..=100));
        });
        property_row(ui, "Blend distance", |ui| {
            ui.add(egui::Slider::new(&mut volume.blend_distance, 0.0..=20.0));
        });
        property_row(ui, "Half X", |ui| {
            ui.add(egui::Slider::new(&mut volume.half_extents.x, 0.5..=50.0));
        });
        property_row(ui, "Half Y", |ui| {
            ui.add(egui::Slider::new(&mut volume.half_extents.y, 0.5..=50.0));
        });
        property_row(ui, "Half Z", |ui| {
            ui.add(egui::Slider::new(&mut volume.half_extents.z, 0.5..=50.0));
        });
        if volume.half_extents != original.half_extents
            || volume.priority != original.priority
            || volume.blend_distance != original.blend_distance
            || volume.label != original.label
        {
            changed = true;
        }

        ui.separator();
        ui.label(panel_heading("Overrides"));
        changed |= override_f32_ui(
            ui,
            "Exposure EV100",
            &mut volume.overrides.exposure_ev100,
            project.exposure_ev100,
        );
        changed |= override_bool_ui(ui, "HDR", &mut volume.overrides.hdr, project.hdr);
        changed |= override_bool_ui(
            ui,
            "Tonemapping ACES",
            &mut volume.overrides.tonemapping_aces,
            project.tonemapping_aces,
        );
        changed |= override_bool_ui(ui, "Bloom", &mut volume.overrides.bloom, project.bloom);
        changed |= override_bool_ui(ui, "TAA", &mut volume.overrides.taa, project.taa);
        changed |= override_bool_ui(ui, "SSAO", &mut volume.overrides.ssao, project.ssao);
        changed |= override_bool_ui(
            ui,
            "Atmosphere",
            &mut volume.overrides.atmosphere,
            project.atmosphere,
        );
        changed |= override_fog_ui(ui, &mut volume.overrides, &project);

        ui.separator();
        ui.label(panel_heading("Fullscreen Effect"));
        let effects = scan_post_fx_assets();
        let current = volume.fullscreen_effect.clone().unwrap_or_default();
        property_row(ui, "Effect", |ui| {
            egui::ComboBox::from_id_salt("post_process_fullscreen_effect")
                .selected_text(if current.is_empty() {
                    "None".to_string()
                } else {
                    current.clone()
                })
                .show_ui(ui, |ui| {
                    if ui
                        .selectable_label(volume.fullscreen_effect.is_none(), "None")
                        .clicked()
                    {
                        volume.fullscreen_effect = None;
                        changed = true;
                    }
                    for path in &effects {
                        if ui
                            .selectable_label(
                                volume.fullscreen_effect.as_deref() == Some(path.as_str()),
                                path,
                            )
                            .clicked()
                        {
                            volume.fullscreen_effect = Some(path.clone());
                            changed = true;
                        }
                    }
                });
        });

        ui.separator();
        ui.label(panel_heading("Preset"));
        let profiles = scan_rendering_profiles();
        property_row(ui, "Profile", |ui| {
            egui::ComboBox::from_id_salt("post_process_profile")
                .selected_text(volume.profile.clone().unwrap_or_else(|| "None".to_string()))
                .show_ui(ui, |ui| {
                    if ui
                        .selectable_label(volume.profile.is_none(), "None")
                        .clicked()
                    {
                        volume.profile = None;
                        changed = true;
                    }
                    for path in &profiles {
                        if ui
                            .selectable_label(
                                volume.profile.as_deref() == Some(path.as_str()),
                                path,
                            )
                            .clicked()
                        {
                            volume.profile = Some(path.clone());
                            changed = true;
                        }
                    }
                });
        });
        ui.horizontal_wrapped(|ui| {
            if ui.button("Apply preset").clicked() {
                if let Some(path) = &volume.profile {
                    if let Ok(preset) = RenderingProfileAsset::load_from_path(path) {
                        volume.overrides = preset.overrides;
                        changed = true;
                    }
                }
            }
            if ui.button("Revert to preset").clicked() {
                if let Some(path) = &volume.profile {
                    if let Ok(preset) = RenderingProfileAsset::load_from_path(path) {
                        volume.overrides = preset.overrides;
                        changed = true;
                    }
                }
            }
        });
    });
    apply_component_card_response(world, entity, card_response);

    if changed {
        set_post_process_volume_with_history(world, entity, volume);
    }
}

fn override_bool_ui(
    ui: &mut egui::Ui,
    label: &str,
    field: &mut Option<bool>,
    inherited: bool,
) -> bool {
    let mut changed = false;
    property_row(ui, label, |ui| {
        let mut overriding = field.is_some();
        if ui.checkbox(&mut overriding, "Override").changed() {
            *field = if overriding { Some(inherited) } else { None };
            changed = true;
        }
    });
    if let Some(value) = field.as_mut() {
        property_row(ui, "Value", |ui| {
            if ui.checkbox(value, "Enabled").changed() {
                changed = true;
            }
            if ui.small_button("Reset to project").clicked() {
                *value = inherited;
                changed = true;
            }
        });
    } else {
        property_row(ui, "Inherited", |ui| {
            ui.label(if inherited { "on" } else { "off" });
        });
    }
    changed
}

fn override_f32_ui(
    ui: &mut egui::Ui,
    label: &str,
    field: &mut Option<f32>,
    inherited: f32,
) -> bool {
    let mut changed = false;
    property_row(ui, label, |ui| {
        let mut overriding = field.is_some();
        if ui.checkbox(&mut overriding, "Override").changed() {
            *field = if overriding { Some(inherited) } else { None };
            changed = true;
        }
    });
    if let Some(value) = field.as_mut() {
        property_row(ui, "Value", |ui| {
            if ui.add(egui::Slider::new(value, 0.0..=20.0)).changed() {
                changed = true;
            }
            if ui.small_button("Reset to project").clicked() {
                *value = inherited;
                changed = true;
            }
        });
    } else {
        property_row(ui, "Inherited", |ui| {
            ui.label(format!("{inherited:.2}"));
        });
    }
    changed
}

fn override_fog_ui(
    ui: &mut egui::Ui,
    overrides: &mut PostProcessVolumeOverrides,
    project: &settings::RenderingSettings,
) -> bool {
    let mut changed = false;
    property_row(ui, "Fog density", |ui| {
        let mut overriding = overrides.fog_density.is_some();
        if ui.checkbox(&mut overriding, "Override").changed() {
            overrides.fog_density = if overriding {
                Some(project.fog_density)
            } else {
                None
            };
            changed = true;
        }
    });
    if let Some(density) = overrides.fog_density.as_mut() {
        property_row(ui, "Density", |ui| {
            if ui
                .add(egui::Slider::new(density, 0.0..=0.01).logarithmic(true))
                .changed()
            {
                changed = true;
            }
        });
    } else {
        property_row(ui, "Inherited", |ui| {
            ui.label(format!("{:.4}", project.fog_density));
        });
    }

    property_row(ui, "Fog color", |ui| {
        let mut overriding = overrides.fog_color.is_some();
        if ui.checkbox(&mut overriding, "Override").changed() {
            overrides.fog_color = if overriding {
                Some(ColorDesc::srgb(
                    project.fog_color[0],
                    project.fog_color[1],
                    project.fog_color[2],
                ))
            } else {
                None
            };
            changed = true;
        }
    });
    if let Some(color) = overrides.fog_color.as_mut() {
        property_row(ui, "Color", |ui| {
            let mut rgb = [color.r, color.g, color.b];
            if ui.color_edit_button_rgb(&mut rgb).changed() {
                color.r = rgb[0];
                color.g = rgb[1];
                color.b = rgb[2];
                changed = true;
            }
        });
    } else {
        property_row(ui, "Inherited", |ui| {
            ui.label(format!(
                "({:.2}, {:.2}, {:.2})",
                project.fog_color[0], project.fog_color[1], project.fog_color[2]
            ));
        });
    }
    changed
}

fn scan_post_fx_assets() -> Vec<String> {
    scan_ron_dir("assets/post_fx")
}

fn scan_rendering_profiles() -> Vec<String> {
    scan_ron_dir("assets/rendering_profiles")
}

fn scan_ron_dir(root: &str) -> Vec<String> {
    let mut paths = Vec::new();
    for entry in WalkDir::new(root).into_iter().filter_map(Result::ok) {
        if entry.file_type().is_file()
            && entry.path().extension().and_then(|e| e.to_str()) == Some("ron")
        {
            let path = entry.path().to_string_lossy().replace('\\', "/");
            paths.push(path);
        }
    }
    paths.sort();
    paths
}
