// Copyright 2022 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use {
    anyhow::Error,
    carnelian::{
        app::Config,
        color::Color,
        make_app_assistant,
        render::{rive::load_rive, Context as RenderContext},
        scene::{
            facets::{FacetId, RiveFacet, SetSizeMessage},
            scene::{Scene, SceneBuilder},
        },
        App, AppAssistant, Size, ViewAssistant, ViewAssistantContext, ViewAssistantPtr, ViewKey,
    },
    fuchsia_trace_provider,
    fuchsia_zircon::{Event, Time},
    rive_rs::{self as rive},
    std::path::PathBuf,
};

const POINTER: &'static str = "/pkg/data/pointer.riv";
const BACKGROUND_COLOR: Color = Color { r: 0, g: 0, b: 0, a: 0 };

#[derive(Default)]
struct CursorManagerAppAssistant;

impl AppAssistant for CursorManagerAppAssistant {
    fn setup(&mut self) -> Result<(), Error> {
        Ok(())
    }

    fn create_view_assistant(&mut self, _view_key: ViewKey) -> Result<ViewAssistantPtr, Error> {
        Ok(Box::new(CursorManagerViewAssistant::new()))
    }

    fn filter_config(&mut self, config: &mut Config) {
        config.view_mode = carnelian::app::ViewMode::Hosted;
        config.input = false;
        config.needs_blending = true;
        config.startup_delay = std::time::Duration::from_millis(500);
    }
}

struct SceneDetails {
    scene: Scene,
    _file: rive::File,
    rive: FacetId,
    artboard: rive::Object<rive::Artboard>,
    animation: Option<rive::animation::LinearAnimationInstance>,
}

struct CursorManagerViewAssistant {
    last_presentation_time: Option<Time>,
    scene_details: Option<SceneDetails>,
}

impl CursorManagerViewAssistant {
    fn new() -> CursorManagerViewAssistant {
        CursorManagerViewAssistant { last_presentation_time: None, scene_details: None }
    }

    fn set_size(&mut self, size: &Size) {
        if let Some(scene_details) = self.scene_details.as_mut() {
            scene_details
                .scene
                .send_message(&scene_details.rive, Box::new(SetSizeMessage { size: *size }));
        }
    }
}

impl ViewAssistant for CursorManagerViewAssistant {
    fn resize(&mut self, new_size: &Size) -> Result<(), Error> {
        self.set_size(new_size);
        Ok(())
    }

    fn render(
        &mut self,
        render_context: &mut RenderContext,
        ready_event: Event,
        context: &ViewAssistantContext,
    ) -> Result<(), Error> {
        let mut scene_details = self.scene_details.take().unwrap_or_else(|| {
            let file = load_rive(PathBuf::from(POINTER)).expect("failed to load animation");
            let mut builder = SceneBuilder::new().background_color(BACKGROUND_COLOR).mutable(false);
            let artboard = file.artboard().expect("failed to get artboard");
            let artboard_ref = artboard.as_ref();
            let rive_facet = RiveFacet::new(context.size, artboard.clone());
            let rive = builder.facet(Box::new(rive_facet));
            let scene = builder.build();
            let animation = artboard_ref
                .animations()
                .next()
                .map(|animation| rive::animation::LinearAnimationInstance::new(animation));

            SceneDetails { scene, _file: file, rive, artboard, animation }
        });

        let artboard_ref = scene_details.artboard.as_ref();
        let request_render = if let Some(animation) = scene_details.animation.as_mut() {
            let presentation_time = context.presentation_time;
            let elapsed = if let Some(last_presentation_time) = self.last_presentation_time {
                const NANOS_PER_SECOND: f32 = 1_000_000_000.0;
                (presentation_time - last_presentation_time).into_nanos() as f32 / NANOS_PER_SECOND
            } else {
                0.0
            };
            self.last_presentation_time = Some(presentation_time);

            animation.advance(elapsed);
            animation.apply(scene_details.artboard.clone(), 1.0);

            artboard_ref.advance(elapsed);
            true
        } else {
            artboard_ref.advance(0.0);
            false
        };

        scene_details.scene.render(render_context, ready_event, context)?;

        if request_render {
            context.request_render();
        }

        self.scene_details = Some(scene_details);

        Ok(())
    }
}

fn main() -> Result<(), Error> {
    fuchsia_trace_provider::trace_provider_create_with_fdio();
    App::run(make_app_assistant::<CursorManagerAppAssistant>())
}
