//! Penpot Surface section backed by shared material document values.

use egui;
use material_schema::{MaterialAlphaMode, MaterialInputSet, MaterialRenderState};

use super::inputs::{
    apply_arm_texture_preset, apply_separate_texture_preset, packed_map_mode, PackedMapMode,
};
use super::layout::{ResponsiveMaterialLayout, SurfaceSectionGeometry};
use crate::design_system;

pub fn material_surface_options_ui(
    ui: &mut egui::Ui,
    state: &mut MaterialRenderState,
    packed_inputs: Option<&mut MaterialInputSet>,
) {
    let palette = design_system::palette(ui);
    let width = ui.available_width().max(1.0);
    let height = match ResponsiveMaterialLayout::for_width(width) {
        ResponsiveMaterialLayout::Reference => design_system::SURFACE_SECTION_HEIGHT,
        ResponsiveMaterialLayout::Compact => design_system::COMPACT_SURFACE_SECTION_HEIGHT,
        ResponsiveMaterialLayout::Transient => 100.0,
    };
    let (rect, _) = ui.allocate_exact_size(egui::vec2(width, height), egui::Sense::hover());
    ui.painter().rect(
        rect,
        5.0,
        palette.panel,
        egui::Stroke::new(1.0_f32, palette.border),
        egui::StrokeKind::Inside,
    );
    let geometry = SurfaceSectionGeometry::for_rect(rect);
    ui.painter().text(
        geometry.title.left_center(),
        egui::Align2::LEFT_CENTER,
        "Surface",
        design_system::typography::TypeRole::Section.font(),
        palette.text_primary,
    );
    clipped_rect_ui(ui, geometry.blend, |ui| surface_blend_controls(ui, state));
    if let Some(inputs) = packed_inputs {
        clipped_rect_ui(ui, geometry.packed, |ui| packed_mode_controls(ui, inputs));
    }
    ui.painter().text(
        geometry.double_sided.left_center() + egui::vec2(7.0, 0.0),
        egui::Align2::LEFT_CENTER,
        "Double Sided",
        design_system::typography::TypeRole::Body.font(),
        palette.text_secondary,
    );
    let switch_rect = egui::Rect::from_min_size(
        geometry.double_sided.min + egui::vec2(76.0, 3.0),
        egui::vec2(31.0, 16.0),
    );
    clipped_rect_ui(ui, switch_rect, |ui| {
        design_system::controls::switch(ui, &mut state.double_sided)
            .on_hover_text("Render both sides of the surface");
    });
    // Explicitly placed blend/packing/switch children do not own vertical flow. Reassert the
    // Surface rectangle after they render so the following authored section gap starts at the
    // true 46/100 px boundary.
    ui.advance_cursor_after_rect(rect);
}

fn packed_mode_controls(ui: &mut egui::Ui, inputs: &mut MaterialInputSet) {
    let arm = packed_map_mode(inputs) == PackedMapMode::Arm;
    match design_system::controls::two_option_segmented(ui, "Separate", "ORM", arm) {
        Some(false) => apply_separate_texture_preset(inputs),
        Some(true) => apply_arm_texture_preset(inputs),
        None => {}
    }
}

fn surface_blend_controls(ui: &mut egui::Ui, state: &mut MaterialRenderState) {
    let width = ui.available_width().max(1.0);
    let show_cutoff = state.alpha_mode == MaterialAlphaMode::Cutout;
    let combo_width = if show_cutoff {
        (width - 58.0).max(1.0)
    } else {
        width
    };
    let combo_rect = egui::Rect::from_min_size(ui.min_rect().min, egui::vec2(combo_width, 24.0));
    clipped_rect_ui(ui, combo_rect, |ui| {
        egui::ComboBox::from_id_salt("material_alpha_mode")
            .selected_text(match state.alpha_mode {
                MaterialAlphaMode::Opaque => "Opaque",
                MaterialAlphaMode::Cutout => "Cutout",
            })
            .width(combo_width)
            .show_ui(ui, |ui| {
                ui.selectable_value(&mut state.alpha_mode, MaterialAlphaMode::Opaque, "Opaque");
                ui.selectable_value(&mut state.alpha_mode, MaterialAlphaMode::Cutout, "Cutout");
            });
    });
    if show_cutoff {
        let cutoff_rect = egui::Rect::from_min_size(
            ui.min_rect().min + egui::vec2(combo_width + 4.0, 1.0),
            egui::vec2(54.0_f32.min(width - combo_width - 4.0), 22.0),
        );
        ui.put(
            cutoff_rect,
            egui::DragValue::new(&mut state.alpha_cutoff)
                .range(0.0..=1.0)
                .speed(0.01),
        )
        .on_hover_text("Alpha cutoff");
    }
}

fn clipped_rect_ui<R>(
    ui: &mut egui::Ui,
    rect: egui::Rect,
    add_contents: impl FnOnce(&mut egui::Ui) -> R,
) -> R {
    ui.scope_builder(egui::UiBuilder::new().max_rect(rect), |ui| {
        ui.set_clip_rect(rect.intersect(ui.clip_rect()));
        add_contents(ui)
    })
    .inner
}
