// Copyright 2022 the Vello Authors
// SPDX-License-Identifier: Apache-2.0 OR MIT

// This is not a published crate, so we don't need to understand our public API
#![allow(unreachable_pub)]

use std::collections::HashSet;
use std::num::NonZeroUsize;
use std::sync::Arc;

#[cfg(not(target_arch = "wasm32"))]
use std::time::Instant;
#[cfg(target_arch = "wasm32")]
use web_time::Instant;
use winit::application::ApplicationHandler;
use winit::event::*;
use winit::event_loop::ControlFlow;
use winit::keyboard::*;

#[cfg(all(feature = "wgpu-profiler", not(target_arch = "wasm32")))]
use std::time::Duration;
#[cfg(all(feature = "wgpu-profiler", target_arch = "wasm32"))]
use web_time::Duration;

use clap::Parser;
use scenes::{ExampleScene, ImageCache, SceneParams, SceneSet, SimpleText};
use vello::kurbo::{Affine, Vec2};
use vello::peniko::Color;
use vello::util::{RenderContext, RenderSurface};
use vello::{AaConfig, BumpAllocators, Renderer, RendererOptions, Scene};

use winit::dpi::LogicalSize;
use winit::event_loop::EventLoop;
use winit::window::{Window, WindowAttributes};

use vello::wgpu;

#[cfg(not(any(target_arch = "wasm32", target_os = "android")))]
mod hot_reload;
mod multi_touch;
mod stats;

#[derive(Parser, Debug)]
#[command(about, long_about = None, bin_name="cargo run -p with_winit --")]
struct Args {
    /// Which scene (index) to start on
    /// Switch between scenes with left and right arrow keys
    #[arg(long)]
    scene: Option<i32>,
    #[command(flatten)]
    args: scenes::Arguments,
    #[arg(long)]
    /// Whether to use CPU shaders
    use_cpu: bool,
    /// Used to disable vsync at startup. Can be toggled with the "V" key.
    ///
    /// This setting is useful for Android, where it might be harder to press this key
    #[arg(long)]
    startup_vsync_off: bool,
    /// Used to enable gpu profiling at startup. Can be toggled with the "G" key
    ///
    /// It is off by default because it has adverse performance characteristics
    #[arg(long)]
    #[cfg(feature = "wgpu-profiler")]
    startup_gpu_profiling_on: bool,
    /// Whether to force initialising the shaders serially (rather than spawning threads)
    /// This has no effect on wasm, and defaults to 1 on macOS for performance reasons
    ///
    /// Use `0` for an automatic choice
    #[arg(long, default_value_t=default_threads())]
    num_init_threads: usize,
    /// Use the asynchronous pipeline (if available) for rendering
    ///
    /// The asynchronous pipeline is one approach for robust memory - see
    /// <https://github.com/linebender/vello/issues/366>
    ///
    /// However, it also has potential latency issues, especially for
    /// accessibility technology, as it (currently) blocks the main thread for
    /// extended periods
    #[arg(long)]
    async_pipeline: bool,
}

fn default_threads() -> usize {
    #[cfg(target_os = "macos")]
    return 1;
    #[cfg(not(target_os = "macos"))]
    return 0;
}

struct RenderState<'s> {
    // SAFETY: We MUST drop the surface before the `window`, so the fields
    // must be in this order
    surface: RenderSurface<'s>,
    window: Arc<Window>,
}

#[cfg(not(target_os = "android"))]
// TODO: Make this set configurable through the command line
// Alternatively, load anti-aliasing shaders on demand/asynchronously
const AA_CONFIGS: [AaConfig; 3] = [AaConfig::Area, AaConfig::Msaa8, AaConfig::Msaa16];

#[cfg(target_os = "android")]
// Hard code to only one on Android whilst we are working on startup speed
const AA_CONFIGS: [AaConfig; 1] = [AaConfig::Area];

struct VelloApp<'s> {
    context: RenderContext,
    renderers: Vec<Option<Renderer>>,
    state: Option<RenderState<'s>>,
    // Whilst suspended, we drop `render_state`, but need to keep the same window.
    // If render_state exists, we must store the window in it, to maintain drop order
    #[cfg(not(target_arch = "wasm32"))]
    cached_window: Option<Arc<Window>>,

    #[cfg(not(target_arch = "wasm32"))]
    use_cpu: bool,
    #[cfg(not(target_arch = "wasm32"))]
    num_init_threads: usize,

    scenes: Vec<ExampleScene>,
    scene: Scene,
    fragment: Scene,
    simple_text: SimpleText,
    images: ImageCache,
    stats: stats::Stats,
    stats_shown: bool,

    base_color: Option<Color>,
    async_pipeline: bool,

    // Currently not updated in wasm builds
    #[allow(unused_mut)]
    scene_complexity: Option<BumpAllocators>,

    complexity_shown: bool,
    vsync_on: bool,

    #[cfg(feature = "wgpu-profiler")]
    gpu_profiling_on: bool,
    #[cfg(feature = "wgpu-profiler")]
    profile_stored: Option<Vec<wgpu_profiler::GpuTimerQueryResult>>,
    #[cfg(feature = "wgpu-profiler")]
    profile_taken: Instant,

    // We allow cycling through AA configs in either direction, so use a signed index
    aa_config_ix: i32,

    frame_start_time: Instant,
    start: Instant,

    touch_state: multi_touch::TouchState,
    // navigation_fingers are fingers which are used in the navigation 'zone' at the bottom
    // of the screen. This ensures that one press on the screen doesn't have multiple actions
    navigation_fingers: HashSet<u64>,
    transform: Affine,
    mouse_down: bool,
    prior_position: Option<Vec2>,
    // We allow looping left and right through the scenes, so use a signed index
    scene_ix: i32,
    complexity: usize,

    prev_scene_ix: i32,
    modifiers: ModifiersState,
}

impl<'s> ApplicationHandler<UserEvent> for VelloApp<'s> {
    #[cfg(target_arch = "wasm32")]
    fn resumed(&mut self, _event_loop: &winit::event_loop::ActiveEventLoop) {}

    #[cfg(not(target_arch = "wasm32"))]
    fn resumed(&mut self, event_loop: &winit::event_loop::ActiveEventLoop) {
        let Option::None = self.state else {
            return;
        };
        let window = self
            .cached_window
            .take()
            .unwrap_or_else(|| Arc::new(event_loop.create_window(window_attributes()).unwrap()));
        let size = window.inner_size();
        let present_mode = if self.vsync_on {
            wgpu::PresentMode::AutoVsync
        } else {
            wgpu::PresentMode::AutoNoVsync
        };
        let surface_future =
            self.context
                .create_surface(window.clone(), size.width, size.height, present_mode);
        // We need to block here, in case a Suspended event appeared
        let surface = pollster::block_on(surface_future).expect("Error creating surface");
        self.state = {
            let render_state = RenderState { window, surface };
            self.renderers
                .resize_with(self.context.devices.len(), || None);
            let id = render_state.surface.dev_id;
            self.renderers[id].get_or_insert_with(|| {
                let start = Instant::now();
                #[allow(unused_mut)]
                let mut renderer = Renderer::new(
                    &self.context.devices[id].device,
                    RendererOptions {
                        surface_format: Some(render_state.surface.format),
                        use_cpu: self.use_cpu,
                        antialiasing_support: AA_CONFIGS.iter().copied().collect(),
                        num_init_threads: NonZeroUsize::new(self.num_init_threads),
                    },
                )
                .map_err(|e| {
                    // Pretty-print any renderer creation error using Display formatting before unwrapping.
                    anyhow::format_err!("{e}")
                })
                .expect("Failed to create renderer");
                log::info!("Creating renderer {id} took {:?}", start.elapsed());
                #[cfg(feature = "wgpu-profiler")]
                renderer
                    .profiler
                    .change_settings(wgpu_profiler::GpuProfilerSettings {
                        enable_timer_queries: self.gpu_profiling_on,
                        enable_debug_groups: self.gpu_profiling_on,
                        ..Default::default()
                    })
                    .expect("Not setting max_num_pending_frames");
                renderer
            });
            Some(render_state)
        };
        event_loop.set_control_flow(ControlFlow::Poll);
    }

    fn window_event(
        &mut self,
        event_loop: &winit::event_loop::ActiveEventLoop,
        window_id: winit::window::WindowId,
        event: winit::event::WindowEvent,
    ) {
        let Some(render_state) = &mut self.state else {
            return;
        };
        if render_state.window.id() != window_id {
            return;
        }
        let _span = if !matches!(event, WindowEvent::RedrawRequested) {
            Some(tracing::trace_span!("Handling window event", ?event).entered())
        } else {
            None
        };
        match event {
            WindowEvent::CloseRequested => event_loop.exit(),
            WindowEvent::ModifiersChanged(m) => self.modifiers = m.state(),
            WindowEvent::KeyboardInput { event, .. } => {
                if event.state == ElementState::Pressed {
                    match event.logical_key.as_ref() {
                        Key::Named(NamedKey::ArrowLeft) => {
                            self.scene_ix = self.scene_ix.saturating_sub(1);
                        }
                        Key::Named(NamedKey::ArrowRight) => {
                            self.scene_ix = self.scene_ix.saturating_add(1);
                        }
                        Key::Named(NamedKey::ArrowUp) => self.complexity += 1,
                        Key::Named(NamedKey::ArrowDown) => {
                            self.complexity = self.complexity.saturating_sub(1);
                        }
                        Key::Named(NamedKey::Space) => {
                            self.transform = Affine::IDENTITY;
                        }
                        Key::Character(char) => {
                            // TODO: Have a more principled way of handling modifiers on keypress
                            // see e.g. https://xi.zulipchat.com/#narrow/stream/351333-glazier/topic/Keyboard.20shortcuts
                            let char = char.to_lowercase();
                            match char.as_str() {
                                "q" | "e" => {
                                    if let Some(prior_position) = self.prior_position {
                                        let is_clockwise = char == "e";
                                        let angle = if is_clockwise { -0.05 } else { 0.05 };
                                        self.transform = Affine::translate(prior_position)
                                            * Affine::rotate(angle)
                                            * Affine::translate(-prior_position)
                                            * self.transform;
                                    }
                                }
                                "s" => {
                                    self.stats_shown = !self.stats_shown;
                                }
                                "d" => {
                                    self.complexity_shown = !self.complexity_shown;
                                }
                                "c" => {
                                    self.stats.clear_min_and_max();
                                }
                                "m" => {
                                    self.aa_config_ix = if self.modifiers.shift_key() {
                                        self.aa_config_ix.saturating_sub(1)
                                    } else {
                                        self.aa_config_ix.saturating_add(1)
                                    };
                                }
                                #[cfg(feature = "wgpu-profiler")]
                                "p" => {
                                    if let Some(renderer) =
                                        &self.renderers[render_state.surface.dev_id]
                                    {
                                        store_profiling(renderer, &self.profile_stored);
                                    }
                                }
                                #[cfg(feature = "wgpu-profiler")]
                                "g" => {
                                    self.gpu_profiling_on = !self.gpu_profiling_on;
                                    if let Some(renderer) =
                                        &mut self.renderers[render_state.surface.dev_id]
                                    {
                                        renderer
                                            .profiler
                                            .change_settings(wgpu_profiler::GpuProfilerSettings {
                                                enable_timer_queries: self.gpu_profiling_on,
                                                enable_debug_groups: self.gpu_profiling_on,
                                                ..Default::default()
                                            })
                                            .expect("Not setting max_num_pending_frames");
                                    }
                                }
                                "v" => {
                                    self.vsync_on = !self.vsync_on;
                                    self.context.set_present_mode(
                                        &mut render_state.surface,
                                        if self.vsync_on {
                                            wgpu::PresentMode::AutoVsync
                                        } else {
                                            wgpu::PresentMode::AutoNoVsync
                                        },
                                    );
                                }
                                _ => {}
                            }
                        }
                        Key::Named(NamedKey::Escape) => event_loop.exit(),
                        _ => {}
                    }
                }
            }
            WindowEvent::Touch(touch) => {
                match touch.phase {
                    TouchPhase::Started => {
                        // We reserve the bottom third of the screen for navigation
                        // This also prevents strange effects whilst using the navigation gestures on Android
                        // TODO: How do we know what the client area is? Winit seems to just give us the
                        // full screen
                        // TODO: Render a display of the navigation regions. We don't do
                        // this currently because we haven't researched how to determine when we're
                        // in a touch context (i.e. Windows/Linux/MacOS with a touch screen could
                        // also be using mouse/keyboard controls)
                        // Note that winit's rendering is y-down
                        if let Some(RenderState { surface, .. }) = &self.state {
                            if touch.location.y > surface.config.height as f64 * 2. / 3. {
                                self.navigation_fingers.insert(touch.id);
                                // The left third of the navigation zone navigates backwards
                                if touch.location.x < surface.config.width as f64 / 3. {
                                    self.scene_ix = self.scene_ix.saturating_sub(1);
                                } else if touch.location.x > 2. * surface.config.width as f64 / 3. {
                                    self.scene_ix = self.scene_ix.saturating_add(1);
                                }
                            }
                        }
                    }
                    TouchPhase::Ended | TouchPhase::Cancelled => {
                        // We intentionally ignore the result here
                        self.navigation_fingers.remove(&touch.id);
                    }
                    TouchPhase::Moved => (),
                }
                // See documentation on navigation_fingers
                if !self.navigation_fingers.contains(&touch.id) {
                    self.touch_state.add_event(&touch);
                }
            }
            WindowEvent::Resized(size) => {
                if let Some(RenderState { surface, window }) = &mut self.state {
                    self.context
                        .resize_surface(surface, size.width, size.height);
                    window.request_redraw();
                };
            }
            WindowEvent::MouseInput { state, button, .. } => {
                if button == MouseButton::Left {
                    self.mouse_down = state == ElementState::Pressed;
                }
            }
            WindowEvent::MouseWheel { delta, .. } => {
                const BASE: f64 = 1.05;
                const PIXELS_PER_LINE: f64 = 20.0;

                if let Some(prior_position) = self.prior_position {
                    let exponent = if let MouseScrollDelta::PixelDelta(delta) = delta {
                        delta.y / PIXELS_PER_LINE
                    } else if let MouseScrollDelta::LineDelta(_, y) = delta {
                        y as f64
                    } else {
                        0.0
                    };
                    self.transform = Affine::translate(prior_position)
                        * Affine::scale(BASE.powf(exponent))
                        * Affine::translate(-prior_position)
                        * self.transform;
                } else {
                    log::warn!("Scrolling without mouse in window; this shouldn't be possible");
                }
            }
            WindowEvent::CursorLeft { .. } => {
                self.prior_position = None;
            }
            WindowEvent::CursorMoved { position, .. } => {
                let position = Vec2::new(position.x, position.y);
                if self.mouse_down {
                    if let Some(prior) = self.prior_position {
                        self.transform = Affine::translate(position - prior) * self.transform;
                    }
                }
                self.prior_position = Some(position);
            }
            WindowEvent::RedrawRequested => {
                let _rendering_span = tracing::trace_span!("Actioning Requested Redraw").entered();
                let encoding_span = tracing::trace_span!("Encoding scene").entered();

                let Some(RenderState { surface, window }) = &self.state else {
                    return;
                };
                let width = surface.config.width;
                let height = surface.config.height;
                let device_handle = &self.context.devices[surface.dev_id];
                let snapshot = self.stats.snapshot();

                // Allow looping forever
                self.scene_ix = self.scene_ix.rem_euclid(self.scenes.len() as i32);
                self.aa_config_ix = self.aa_config_ix.rem_euclid(AA_CONFIGS.len() as i32);

                let example_scene = &mut self.scenes[self.scene_ix as usize];
                if self.prev_scene_ix != self.scene_ix {
                    self.transform = Affine::IDENTITY;
                    self.prev_scene_ix = self.scene_ix;
                    window.set_title(&format!("Vello demo - {}", example_scene.config.name));
                }
                self.fragment.reset();
                let mut scene_params = SceneParams {
                    time: self.start.elapsed().as_secs_f64(),
                    text: &mut self.simple_text,
                    images: &mut self.images,
                    resolution: None,
                    base_color: None,
                    interactive: true,
                    complexity: self.complexity,
                };
                example_scene
                    .function
                    .render(&mut self.fragment, &mut scene_params);

                // If the user specifies a base color in the CLI we use that. Otherwise we use any
                // color specified by the scene. The default is black.
                let base_color = self
                    .base_color
                    .or(scene_params.base_color)
                    .unwrap_or(Color::BLACK);
                let antialiasing_method = AA_CONFIGS[self.aa_config_ix as usize];
                let render_params = vello::RenderParams {
                    base_color,
                    width,
                    height,
                    antialiasing_method,
                };
                self.scene.reset();
                let mut transform = self.transform;
                if let Some(resolution) = scene_params.resolution {
                    // Automatically scale the rendering to fill as much of the window as possible
                    // TODO: Apply svg view_box, somehow
                    let factor = Vec2::new(width as f64, height as f64);
                    let scale_factor = (factor.x / resolution.x).min(factor.y / resolution.y);
                    transform *= Affine::scale(scale_factor);
                }
                self.scene.append(&self.fragment, Some(transform));
                if self.stats_shown {
                    snapshot.draw_layer(
                        &mut self.scene,
                        scene_params.text,
                        width as f64,
                        height as f64,
                        self.stats.samples(),
                        self.complexity_shown
                            .then_some(self.scene_complexity)
                            .flatten(),
                        self.vsync_on,
                        antialiasing_method,
                    );
                    #[cfg(feature = "wgpu-profiler")]
                    if let Some(profiling_result) = self.renderers[surface.dev_id]
                        .as_mut()
                        .and_then(|it| it.profile_result.take())
                    {
                        if self.profile_stored.is_none()
                            || self.profile_taken.elapsed() > Duration::from_secs(1)
                        {
                            self.profile_stored = Some(profiling_result);
                            self.profile_taken = Instant::now();
                        }
                    }
                    #[cfg(feature = "wgpu-profiler")]
                    if let Some(profiling_result) = self.profile_stored.as_ref() {
                        stats::draw_gpu_profiling(
                            &mut self.scene,
                            scene_params.text,
                            width as f64,
                            height as f64,
                            profiling_result,
                        );
                    }
                }
                drop(encoding_span);
                let texture_span = tracing::trace_span!("Getting texture").entered();
                let surface_texture = surface
                    .surface
                    .get_current_texture()
                    .expect("failed to get surface texture");

                drop(texture_span);
                let render_span = tracing::trace_span!("Dispatching render").entered();
                // Note: we don't run the async/"robust" pipeline, as
                // it requires more async wiring for the readback. See
                // [#gpu > async on wasm](https://xi.zulipchat.com/#narrow/stream/197075-gpu/topic/async.20on.20wasm)
                if self.async_pipeline && cfg!(not(target_arch = "wasm32")) {
                    self.scene_complexity = vello::block_on_wgpu(
                        &device_handle.device,
                        self.renderers[surface.dev_id]
                            .as_mut()
                            .unwrap()
                            .render_to_surface_async(
                                &device_handle.device,
                                &device_handle.queue,
                                &self.scene,
                                &surface_texture,
                                &render_params,
                            ),
                    )
                    .expect("failed to render to surface");
                } else {
                    self.renderers[surface.dev_id]
                        .as_mut()
                        .unwrap()
                        .render_to_surface(
                            &device_handle.device,
                            &device_handle.queue,
                            &self.scene,
                            &surface_texture,
                            &render_params,
                        )
                        .expect("failed to render to surface");
                }
                surface_texture.present();
                drop(render_span);

                {
                    let _poll_aspan = tracing::trace_span!("Polling wgpu device").entered();
                    device_handle.device.poll(wgpu::Maintain::Poll);
                }
                let new_time = Instant::now();
                self.stats.add_sample(stats::Sample {
                    frame_time_us: (new_time - self.frame_start_time).as_micros() as u64,
                });
                self.frame_start_time = new_time;
            }
            _ => {}
        }
    }

    fn about_to_wait(&mut self, _event_loop: &winit::event_loop::ActiveEventLoop) {
        self.touch_state.end_frame();
        let touch_info = self.touch_state.info();
        if let Some(touch_info) = touch_info {
            let centre = Vec2::new(touch_info.zoom_centre.x, touch_info.zoom_centre.y);
            self.transform = Affine::translate(touch_info.translation_delta)
                * Affine::translate(centre)
                * Affine::scale(touch_info.zoom_delta)
                * Affine::rotate(touch_info.rotation_delta)
                * Affine::translate(-centre)
                * self.transform;
        }

        if let Some(render_state) = &mut self.state {
            render_state.window.request_redraw();
        }
    }

    fn user_event(&mut self, _event_loop: &winit::event_loop::ActiveEventLoop, event: UserEvent) {
        match event {
            #[cfg(not(any(target_arch = "wasm32", target_os = "android")))]
            UserEvent::HotReload => {
                let Some(render_state) = &mut self.state else {
                    return;
                };
                let device_handle = &self.context.devices[render_state.surface.dev_id];
                log::info!("==============\nReloading shaders");
                let start = Instant::now();
                let result = self.renderers[render_state.surface.dev_id]
                    .as_mut()
                    .unwrap()
                    .reload_shaders(&device_handle.device);
                // We know that the only async here (`pop_error_scope`) is actually sync, so blocking is fine
                match pollster::block_on(result) {
                    Ok(_) => log::info!("Reloading took {:?}", start.elapsed()),
                    Err(e) => log::error!("Failed to reload shaders: {e}"),
                }
            }
        }
    }

    fn suspended(&mut self, event_loop: &winit::event_loop::ActiveEventLoop) {
        log::info!("Suspending");
        #[cfg(not(target_arch = "wasm32"))]
        // When we suspend, we need to remove the `wgpu` Surface
        if let Some(render_state) = self.state.take() {
            self.cached_window = Some(render_state.window);
        }
        event_loop.set_control_flow(ControlFlow::Wait);
    }
}

fn run(
    event_loop: EventLoop<UserEvent>,
    args: Args,
    scenes: SceneSet,
    render_cx: RenderContext,
    #[cfg(target_arch = "wasm32")] render_state: RenderState,
) {
    use winit::keyboard::*;

    #[allow(unused_mut)]
    let mut renderers: Vec<Option<Renderer>> = vec![];

    #[cfg(not(target_arch = "wasm32"))]
    let render_state = None::<RenderState>;

    // The design of `RenderContext` forces delayed renderer initialisation to
    // not work on wasm, as WASM futures effectively must be 'static.
    // Otherwise, this could work by sending the result to event_loop.proxy
    // instead of blocking
    #[cfg(target_arch = "wasm32")]
    let render_state = {
        renderers.resize_with(render_cx.devices.len(), || None);
        let id = render_state.surface.dev_id;
        #[allow(unused_mut)]
        let mut renderer = Renderer::new(
            &render_cx.devices[id].device,
            RendererOptions {
                surface_format: Some(render_state.surface.format),
                use_cpu: args.use_cpu,
                antialiasing_support: AA_CONFIGS.iter().copied().collect(),
                // We currently initialise on one thread on WASM, but mark this here
                // anyway
                num_init_threads: NonZeroUsize::new(1),
            },
        )
        .map_err(|e| {
            // Pretty-print any renderer creation error using Display formatting before unwrapping.
            eprintln!("{e}");
            e
        })
        .expect("Failed to create renderer");
        #[cfg(feature = "wgpu-profiler")]
        renderer
            .profiler
            .change_settings(wgpu_profiler::GpuProfilerSettings {
                enable_timer_queries: args.startup_gpu_profiling_on,
                enable_debug_groups: args.startup_gpu_profiling_on,
                ..Default::default()
            })
            .expect("Not setting max_num_pending_frames");
        renderers[id] = Some(renderer);
        Some(render_state)
    };

    let mut app = VelloApp {
        context: render_cx,
        renderers,
        state: render_state,
        #[cfg(not(target_arch = "wasm32"))]
        cached_window: None,
        #[cfg(not(target_arch = "wasm32"))]
        use_cpu: args.use_cpu,
        #[cfg(not(target_arch = "wasm32"))]
        num_init_threads: args.num_init_threads,
        scenes: scenes.scenes,
        scene: Scene::new(),
        fragment: Scene::new(),
        simple_text: SimpleText::new(),
        images: ImageCache::new(),
        stats: stats::Stats::new(),
        stats_shown: true,
        base_color: args.args.base_color,
        async_pipeline: args.async_pipeline,
        scene_complexity: None,
        complexity_shown: false,
        vsync_on: !args.startup_vsync_off,

        #[cfg(feature = "wgpu-profiler")]
        gpu_profiling_on: args.startup_gpu_profiling_on,
        #[cfg(feature = "wgpu-profiler")]
        profile_stored: None,
        #[cfg(feature = "wgpu-profiler")]
        profile_taken: Instant::now(),

        aa_config_ix: 0,

        frame_start_time: Instant::now(),
        start: Instant::now(),

        touch_state: multi_touch::TouchState::new(),
        navigation_fingers: HashSet::new(),
        transform: Affine::IDENTITY,
        mouse_down: false,
        prior_position: None,
        scene_ix: args.scene.unwrap_or(0),
        complexity: 0,
        prev_scene_ix: 0,
        modifiers: ModifiersState::default(),
    };

    event_loop.run_app(&mut app).expect("run to completion");
}

#[cfg(feature = "wgpu-profiler")]
/// A function extracted to fix rustfmt
fn store_profiling(
    renderer: &Renderer,
    profile_stored: &Option<Vec<wgpu_profiler::GpuTimerQueryResult>>,
) {
    if let Some(profile_result) = &renderer.profile_result.as_ref().or(profile_stored.as_ref()) {
        // There can be empty results if the required features aren't supported
        if !profile_result.is_empty() {
            let path = std::path::Path::new("trace.json");
            match wgpu_profiler::chrometrace::write_chrometrace(path, profile_result) {
                Ok(()) => {
                    println!("Wrote trace to path {path:?}");
                }
                Err(e) => {
                    log::warn!("Failed to write trace {e}");
                }
            }
        }
    }
}

fn window_attributes() -> WindowAttributes {
    Window::default_attributes()
        .with_inner_size(LogicalSize::new(1044, 800))
        .with_resizable(true)
        .with_title("Vello demo")
}

#[derive(Debug)]
enum UserEvent {
    #[cfg(not(any(target_arch = "wasm32", target_os = "android")))]
    HotReload,
}

#[cfg(target_arch = "wasm32")]
fn display_error_message() -> Option<()> {
    let window = web_sys::window()?;
    let document = window.document()?;
    let elements = document.get_elements_by_tag_name("body");
    let body = elements.item(0)?;
    body.set_inner_html(
        r#"<style>
        p {
            margin: 2em 10em;
            font-family: sans-serif;
        }
        </style>
        <p><a href="https://caniuse.com/webgpu">WebGPU</a>
        is not enabled. Make sure your browser is updated to
        <a href="https://chromiumdash.appspot.com/schedule">Chrome M113</a> or
        another browser compatible with WebGPU.</p>"#,
    );
    Some(())
}

#[cfg(not(target_os = "android"))]
pub fn main() -> anyhow::Result<()> {
    // TODO: initializing both env_logger and console_logger fails on wasm.
    // Figure out a more principled approach.
    #[cfg(not(target_arch = "wasm32"))]
    env_logger::builder()
        .format_timestamp(Some(env_logger::TimestampPrecision::Millis))
        .init();
    let args = parse_arguments();
    let scenes = args.args.select_scene_set()?;
    if let Some(scenes) = scenes {
        let event_loop = EventLoop::<UserEvent>::with_user_event().build()?;
        #[allow(unused_mut)]
        let mut render_cx = RenderContext::new();
        #[cfg(not(target_arch = "wasm32"))]
        {
            let proxy = event_loop.create_proxy();
            let _keep = hot_reload::hot_reload(move || {
                proxy.send_event(UserEvent::HotReload).ok().map(drop)
            });

            run(event_loop, args, scenes, render_cx);
        }
        #[cfg(target_arch = "wasm32")]
        {
            std::panic::set_hook(Box::new(console_error_panic_hook::hook));
            console_log::init().expect("could not initialize logger");
            use winit::platform::web::WindowExtWebSys;
            #[allow(deprecated)]
            let window = Arc::new(event_loop.create_window(window_attributes()).unwrap());
            // On wasm, append the canvas to the document body
            let canvas = window.canvas().unwrap();
            web_sys::window()
                .and_then(|win| win.document())
                .and_then(|doc| doc.body())
                .and_then(|body| body.append_child(canvas.as_ref()).ok())
                .expect("couldn't append canvas to document body");
            // Best effort to start with the canvas focused, taking input
            _ = web_sys::HtmlElement::from(canvas).focus();
            wasm_bindgen_futures::spawn_local(async move {
                let (width, height, scale_factor) = web_sys::window()
                    .map(|w| {
                        (
                            w.inner_width().unwrap().as_f64().unwrap(),
                            w.inner_height().unwrap().as_f64().unwrap(),
                            w.device_pixel_ratio(),
                        )
                    })
                    .unwrap();
                let size =
                    winit::dpi::PhysicalSize::from_logical::<_, f64>((width, height), scale_factor);
                _ = window.request_inner_size(size);
                let surface = render_cx
                    .create_surface(
                        window.clone(),
                        size.width,
                        size.height,
                        wgpu::PresentMode::AutoVsync,
                    )
                    .await;
                if let Ok(surface) = surface {
                    let render_state = RenderState { window, surface };
                    // No error handling here; if the event loop has finished, we don't need to send them the surface
                    run(event_loop, args, scenes, render_cx, render_state);
                } else {
                    _ = display_error_message();
                }
            });
        }
    }
    Ok(())
}

fn parse_arguments() -> Args {
    // We allow baking in arguments at compile time. This is especially useful for
    // Android and WASM.
    // This is used on desktop platforms to allow debugging the same settings
    let args = if let Some(args) = option_env!("VELLO_STATIC_ARGS") {
        // We split by whitespace here to allow passing multiple arguments
        // In theory, we could do more advanced parsing/splitting (e.g. using quotes),
        // but that would require a lot more effort

        // We `chain` in a fake binary name, because clap ignores the first argument otherwise
        // Ideally, we'd use the `no_binary_name` argument, but setting that at runtime would
        // require globals or some worse hacks
        Args::parse_from(std::iter::once("with_winit").chain(args.split_ascii_whitespace()))
    } else {
        Args::parse()
    };
    args
}

#[cfg(target_os = "android")]
use winit::platform::android::activity::AndroidApp;

#[cfg(target_os = "android")]
#[no_mangle]
fn android_main(app: AndroidApp) {
    use winit::platform::android::EventLoopBuilderExtAndroid;
    let config = android_logger::Config::default();
    // We allow configuring the Android logging with an environment variable at build time
    let config = if let Some(logging_config) = option_env!("VELLO_STATIC_LOG") {
        let mut filter = android_logger::FilterBuilder::new();
        filter.filter_level(log::LevelFilter::Warn);
        filter.parse(logging_config);
        let filter = filter.build();
        // This shouldn't be needed in theory, but without this the max
        // level is set to 0 (i.e. Off)
        let config = config.with_max_level(filter.filter());
        config.with_filter(filter)
    } else {
        config.with_max_level(log::LevelFilter::Warn)
    };
    android_logger::init_once(config);

    // Send tracing events to Android Trace
    use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};

    tracing_subscriber::registry()
        .with(tracing_android_trace::AndroidTraceLayer::new())
        .try_init()
        .unwrap();
    log::info!(
        "Max level: {}",
        tracing::level_filters::LevelFilter::current()
    );

    let event_loop = EventLoop::with_user_event()
        .with_android_app(app)
        .build()
        .expect("Required to continue");
    let args = parse_arguments();
    let scenes = args.args.select_scene_set().unwrap().unwrap();
    let render_cx = RenderContext::new();

    run(event_loop, args, scenes, render_cx);
}
