#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] // hide console window on Windows in release
#![expect(rustdoc::missing_crate_level_docs)] // it's an example

use core::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;

use eframe::egui;

fn main() -> eframe::Result {
    env_logger::init(); // Log to stderr (if you run with `RUST_LOG=debug`).
    let options = eframe::NativeOptions {
        viewport: egui::ViewportBuilder::default().with_inner_size([320.0, 240.0]),
        ..Default::default()
    };
    eframe::run_native(
        "Multiple viewports",
        options,
        Box::new(|_cc| Ok(Box::<MyApp>::default())),
    )
}

#[derive(Default)]
struct MyApp {
    /// Immediate viewports are show immediately, so passing state to/from them is easy.
    /// The downside is that their painting is linked with the parent viewport:
    /// if either needs repainting, they are both repainted.
    show_immediate_viewport: bool,

    /// Deferred viewports run independent of the parent viewport, which can save
    /// CPU if only some of the viewports require repainting.
    /// However, this requires passing state with `Arc` and locks.
    show_deferred_viewport: Arc<AtomicBool>,
}

impl eframe::App for MyApp {
    fn ui(&mut self, ui: &mut egui::Ui, _frame: &mut eframe::Frame) {
        egui::CentralPanel::default().show(ui, |ui| {
            ui.label("Hello from the root viewport");

            ui.checkbox(
                &mut self.show_immediate_viewport,
                "Show immediate child viewport",
            );

            {
                let mut show_deferred_viewport =
                    self.show_deferred_viewport.load(Ordering::Relaxed);
                ui.checkbox(&mut show_deferred_viewport, "Show deferred child viewport");
                self.show_deferred_viewport
                    .store(show_deferred_viewport, Ordering::Relaxed);
            }

            ui.add_space(16.0);
            {
                let mut embedded = ui.embed_viewports();
                ui.checkbox(&mut embedded, "Embed all viewports");
                ui.set_embed_viewports(embedded);
            }
        });

        if self.show_immediate_viewport {
            ui.ctx().show_viewport_immediate(
                egui::ViewportId::from_hash_of("immediate_viewport"),
                egui::ViewportBuilder::default()
                    .with_title("Immediate Viewport")
                    .with_inner_size([200.0, 100.0]),
                |ui, class| {
                    if class == egui::ViewportClass::EmbeddedWindow {
                        ui.label(
                            "This viewport is embedded in the parent window, and cannot be moved outside of it.",
                        );
                    } else {
                        egui::CentralPanel::default().show(ui, |ui| {
                            ui.label("Hello from immediate viewport");

                            if ui.input(|i| i.viewport().close_requested()) {
                                // Tell parent viewport that we should not show next frame:
                                self.show_immediate_viewport = false;
                            }
                        });
                    }
                },
            );
        }

        if self.show_deferred_viewport.load(Ordering::Relaxed) {
            let show_deferred_viewport = Arc::clone(&self.show_deferred_viewport);
            ui.ctx().show_viewport_deferred(
                egui::ViewportId::from_hash_of("deferred_viewport"),
                egui::ViewportBuilder::default()
                    .with_title("Deferred Viewport")
                    .with_inner_size([200.0, 100.0]),
                move |ui, class| {
                    if class == egui::ViewportClass::EmbeddedWindow {
                        ui.label(
                            "This viewport is embedded in the parent window, and cannot be moved outside of it.",
                        );
                    } else {
                        egui::CentralPanel::default().show(ui, |ui| {
                            ui.label("Hello from deferred viewport");

                            if ui.input(|i| i.viewport().close_requested()) {
                                // Tell parent to close us.
                                show_deferred_viewport.store(false, Ordering::Relaxed);
                            }
                        });
                    }
                },
            );
        }
    }
}
