// 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::{anyhow, Context, Error};
use carnelian::{
    app::{Config, ViewCreationParameters},
    color::Color,
    drawing::{load_font, DisplayRotation, FontFace},
    input, make_message,
    render::rive::load_rive,
    scene::{
        facets::{
            FacetId, RiveFacet, SetColorMessage, SetTextMessage, TextFacet, TextFacetOptions,
            TextHorizontalAlignment,
        },
        group::GroupId,
        layout::{Alignment, CrossAxisAlignment},
        scene::{Scene, SceneBuilder},
    },
    App, AppAssistant, AppAssistantPtr, AppSender, MessageTarget, Point, Size, ViewAssistant,
    ViewAssistantContext, ViewAssistantPtr, ViewKey,
};
use euclid::{point2, size2};
use fidl_fuchsia_boot::ArgumentsMarker;
use fidl_fuchsia_hardware_display::VirtconMode;
use fuchsia_async::{self as fasync, DurationExt};
use fuchsia_fs::directory::{WatchEvent, Watcher};
use fuchsia_zircon as zx;
use futures::StreamExt;
use recovery_ui_config::Config as UiConfig;
use rive_rs as rive;
use std::path::PathBuf;

mod menu;
use menu::{Key, MenuButtonType, MenuEvent, MenuState, MenuStateMachine};

use installer::{
    do_install, find_install_source, get_bootloader_type, restart, BootloaderType,
    InstallationPaths,
};
use recovery_util_block::{get_block_device, get_block_devices, BlockDevice};

const INSTALLER_HEADLINE: &'static str = "Fuchsia Workstation Installer";

const BG_COLOR: Color = Color { r: 238, g: 23, b: 128, a: 255 };
const WARN_BG_COLOR: Color = Color { r: 158, g: 11, b: 0, a: 255 };
const SUCCESS_BG_COLOR: Color = Color { r: 79, g: 194, b: 50, a: 255 };
const TEXT_COLOR: Color = Color::new(); // Black
const SELECTED_BUTTON_COLOR: Color = Color::white();

// Menu interaction
const HID_USAGE_KEY_UP: u32 = 82;
const HID_USAGE_KEY_DOWN: u32 = 81;
const HID_USAGE_KEY_ENTER: u32 = 40;

const LOGO_IMAGE_PATH: &str = "/pkg/data/logo.riv";

enum InstallerMessages {
    MenuUp,
    MenuDown,
    MenuEnter,
    Error(String),
    GotInstallSource(BlockDevice),
    GotBootloaderType(BootloaderType),
    GotInstallDestinations(Vec<BlockDevice>),
    GotBlockDevices(Vec<BlockDevice>),
    ProgressUpdate(String),
    Success,
}

struct InstallerAppAssistant {
    display_rotation: DisplayRotation,
    automated: bool,
}

impl InstallerAppAssistant {
    fn new(display_rotation: DisplayRotation, automated: bool) -> Self {
        Self { display_rotation, automated }
    }
}

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

    fn create_view_assistant_with_parameters(
        &mut self,
        params: ViewCreationParameters,
    ) -> Result<ViewAssistantPtr, Error> {
        let logo_file = load_rive(LOGO_IMAGE_PATH).ok();
        Ok(Box::new(InstallerViewAssistant::new(
            params.app_sender,
            params.view_key,
            logo_file,
            self.automated,
        )?))
    }

    fn filter_config(&mut self, config: &mut Config) {
        config.view_mode = carnelian::app::ViewMode::Direct;
        config.virtcon_mode = Some(VirtconMode::Forced);
        config.display_rotation = self.display_rotation;
        config.buffer_count = Some(1);
    }
}

struct SceneDetails {
    scene: Scene,
    size: Size,
    background: FacetId,
    subheading: FacetId,
    message: Option<FacetId>,
    buttons: Vec<FacetId>,
    message_group: GroupId,
    button_group: GroupId,
}

struct InstallerViewAssistant {
    app_sender: AppSender,
    view_key: ViewKey,
    scene_details: Option<SceneDetails>,
    face: FontFace,
    menu_state_machine: MenuStateMachine,
    installation_paths: InstallationPaths,
    logo_file: Option<rive::File>,
    automated: bool,
}

impl InstallerViewAssistant {
    fn new(
        app_sender: AppSender,
        view_key: ViewKey,
        logo_file: Option<rive::File>,
        automated: bool,
    ) -> Result<InstallerViewAssistant, Error> {
        let face = load_font(PathBuf::from("/pkg/data/fonts/Roboto-Regular.ttf"))?;

        Ok(InstallerViewAssistant {
            app_sender,
            view_key,
            scene_details: None,
            face,
            menu_state_machine: MenuStateMachine::new(),
            installation_paths: InstallationPaths::new(),
            logo_file,
            automated,
        })
    }

    fn update(&mut self) {
        // Update the existing scene with the current state of the menu.
        // We don't know what has changed so just update everything.
        if let Some(scene_details) = self.scene_details.as_mut() {
            scene_details.scene.send_message(
                &scene_details.background,
                Box::new(SetColorMessage {
                    color: menu_state_to_background_color(self.menu_state_machine.get_state()),
                }),
            );
            scene_details.scene.send_message(
                &scene_details.subheading,
                Box::new(SetTextMessage { text: self.menu_state_machine.get_heading() }),
            );

            // Remove and re-add message.
            // Necessary as we can't change the font size of an existing TextFacet.
            if let Some(message) = scene_details.message {
                scene_details.scene.remove_facet_from_group(message, scene_details.message_group);
                scene_details.scene.remove_facet(message).unwrap();
            }

            let message_text_size = menu_state_to_message_text_size(
                self.menu_state_machine.get_state(),
                scene_details.size,
            );

            let message = TextFacet::with_options(
                self.face.clone(),
                &self.menu_state_machine.get_message(),
                message_text_size,
                TextFacetOptions {
                    horizontal_alignment: TextHorizontalAlignment::Center,
                    color: TEXT_COLOR,
                    ..TextFacetOptions::default()
                },
            );
            let message = scene_details.scene.add_facet(message);
            scene_details.scene.add_facet_to_group(message, scene_details.message_group, None);
            scene_details.scene.move_facet_forward(message).unwrap();
            scene_details.message = Some(message);

            // Remove and re-add buttons.
            // Necessary so we can have a variable number of buttons.
            for button in scene_details.buttons.iter() {
                scene_details.scene.remove_facet_from_group(*button, scene_details.button_group);
                scene_details.scene.remove_facet(*button).unwrap();
            }
            scene_details.buttons.clear();

            let button_text_size = menu_state_to_button_text_size(
                self.menu_state_machine.get_state(),
                scene_details.size,
            );

            for button in self.menu_state_machine.get_buttons() {
                let button = TextFacet::with_options(
                    self.face.clone(),
                    &button.get_text(),
                    button_text_size,
                    TextFacetOptions {
                        color: if button.is_selected() {
                            SELECTED_BUTTON_COLOR
                        } else {
                            TEXT_COLOR
                        },
                        ..TextFacetOptions::default()
                    },
                );

                let button = scene_details.scene.add_facet(button);
                scene_details.scene.add_facet_to_group(button, scene_details.button_group, None);
                scene_details.scene.move_facet_forward(button).unwrap();
                scene_details.buttons.push(button);
            }
        }
    }

    fn handle_installer_message(&mut self, message: &InstallerMessages) {
        match message {
            // Menu Interaction
            InstallerMessages::MenuUp => {
                self.menu_state_machine.handle_event(MenuEvent::Navigate(Key::Up));
            }
            InstallerMessages::MenuDown => {
                self.menu_state_machine.handle_event(MenuEvent::Navigate(Key::Down));
            }
            InstallerMessages::MenuEnter => {
                // Get disks if usb install selected
                match self.menu_state_machine.get_selected_button_type() {
                    MenuButtonType::USBInstall => {
                        // Get installation targets
                        fasync::Task::local(setup_installation_paths(
                            self.app_sender.clone(),
                            self.view_key,
                        ))
                        .detach();
                    }
                    MenuButtonType::Disk(target) => {
                        // Disk was selected as installation target
                        self.installation_paths.install_target = Some(target.clone());
                        self.menu_state_machine.handle_event(MenuEvent::Enter);
                    }
                    MenuButtonType::Yes => {
                        // User agrees to wipe disk and install
                        self.menu_state_machine.handle_event(MenuEvent::Enter);
                        fasync::Task::local(fuchsia_install(
                            self.app_sender.clone(),
                            self.view_key,
                            self.installation_paths.clone(),
                        ))
                        .detach();
                    }
                    MenuButtonType::Restart => {
                        // Restart the machine.
                        fasync::Task::local(restart()).detach();
                    }
                    _ => {
                        self.menu_state_machine.handle_event(MenuEvent::Enter);
                    }
                }
            }
            InstallerMessages::Error(error_msg) => {
                self.menu_state_machine.handle_event(MenuEvent::Error(error_msg.clone()));
            }
            InstallerMessages::GotInstallSource(install_source_path) => {
                self.installation_paths.install_source = Some(install_source_path.clone());
            }
            InstallerMessages::GotBootloaderType(bootloader_type) => {
                self.installation_paths.bootloader_type = Some(bootloader_type.clone());
            }
            InstallerMessages::GotInstallDestinations(destinations) => {
                self.installation_paths.install_destinations = destinations.clone();
                // Send disks to menu
                self.menu_state_machine
                    .handle_event(MenuEvent::GotBlockDevices(destinations.clone()));
            }
            InstallerMessages::GotBlockDevices(devices) => {
                self.installation_paths.available_disks = devices.clone();
            }
            InstallerMessages::ProgressUpdate(string) => {
                self.menu_state_machine.handle_event(MenuEvent::ProgressUpdate(string.clone()));
            }
            InstallerMessages::Success => {
                self.menu_state_machine.handle_event(MenuEvent::Success);
            }
        }

        // Render menu changes
        self.app_sender.request_render(self.view_key);
    }
}

impl ViewAssistant for InstallerViewAssistant {
    fn setup(&mut self, _context: &ViewAssistantContext) -> Result<(), Error> {
        if self.automated {
            fasync::Task::local(drive_automated_install(self.app_sender.clone(), self.view_key))
                .detach();
        }
        Ok(())
    }

    fn resize(&mut self, _new_size: &Size) -> Result<(), Error> {
        self.scene_details = None;
        Ok(())
    }

    fn get_scene(&mut self, size: Size) -> Option<&mut Scene> {
        let scene_details = self.scene_details.take().unwrap_or_else(|| {
            // Create the scene from scratch based on the current menu state.

            // The scene always has a static heading at the top and logo in the corner.
            let min_dimension = size.width.min(size.height);

            let mut builder = SceneBuilder::new().round_scene_corners(true);

            // Place the logo at the bottom right.
            let logo_edge = min_dimension * 0.24;
            let logo_size: Size = size2(logo_edge, logo_edge);

            let logo_position = {
                let x = size.width * 0.8;
                let y = size.height * 0.7;
                point2(x, y)
            };

            if let Some(logo_file) = &self.logo_file {
                builder.facet_at_location(
                    Box::new(
                        RiveFacet::new_from_file(logo_size, &logo_file, None)
                            .expect("facet_from_file"),
                    ),
                    logo_position,
                );
            }

            let mut subheading = None;
            let mut message_group = None;
            let mut button_group = None;

            builder.group().stack().expand().align(Alignment::top_center()).contents(
                |builder: &mut SceneBuilder| {
                    builder.group().column().contents(|builder: &mut SceneBuilder| {
                        // Place the heading at the top.
                        builder.text(
                            self.face.clone(),
                            INSTALLER_HEADLINE,
                            min_dimension / 10.0,
                            Point::zero(),
                            TextFacetOptions { color: TEXT_COLOR, ..TextFacetOptions::default() },
                        );

                        builder.space(size / 50.0);

                        // The remaining parts of the scene are dynamic:
                        //  - A subheading
                        //  - An optional message
                        //  - 0 or more buttons

                        subheading = Some(builder.text(
                            self.face.clone(),
                            &self.menu_state_machine.get_heading(),
                            min_dimension / 15.0,
                            Point::zero(),
                            TextFacetOptions { color: TEXT_COLOR, ..TextFacetOptions::default() },
                        ));

                        builder.space(size / 10.0);

                        // Allocate a group for the message.
                        message_group = Some(builder.group().column().contents(|_| {}));

                        builder.space(size / 30.0);

                        // Allocate a group for the buttons.
                        button_group = Some(
                            builder
                                .group()
                                .column()
                                .cross_align(CrossAxisAlignment::Start)
                                .contents(|_| {}),
                        );
                    });
                },
            );

            // Set background colour.
            // This must be added after everything else to be rendered at the back.
            let background = builder.rectangle(
                size,
                menu_state_to_background_color(self.menu_state_machine.get_state()),
            );

            let subheading = subheading.unwrap();
            let message_group = message_group.unwrap();
            let button_group = button_group.unwrap();
            SceneDetails {
                scene: builder.build(),
                size,
                background,
                subheading,
                message: None,
                buttons: vec![],
                message_group,
                button_group,
            }
        });

        self.scene_details = Some(scene_details);

        // Fill in the dynamic parts of the scene.
        self.update();

        Some(&mut self.scene_details.as_mut().unwrap().scene)
    }

    fn handle_keyboard_event(
        &mut self,
        context: &mut ViewAssistantContext,
        _event: &input::Event,
        keyboard_event: &input::keyboard::Event,
    ) -> Result<(), Error> {
        if keyboard_event.phase == input::keyboard::Phase::Pressed {
            let pressed_key = keyboard_event.hid_usage;
            match pressed_key {
                HID_USAGE_KEY_UP => {
                    context.queue_message(make_message(InstallerMessages::MenuUp));
                }
                HID_USAGE_KEY_DOWN => {
                    context.queue_message(make_message(InstallerMessages::MenuDown));
                }
                HID_USAGE_KEY_ENTER => {
                    context.queue_message(make_message(InstallerMessages::MenuEnter));
                }
                _ => {}
            }
        }

        Ok(())
    }

    fn handle_message(&mut self, message: carnelian::Message) {
        if let Some(message) = message.downcast_ref::<InstallerMessages>() {
            self.handle_installer_message(message);
        }
    }
}

fn menu_state_to_background_color(state: MenuState) -> Color {
    match state {
        MenuState::Warning => WARN_BG_COLOR,
        MenuState::Error => WARN_BG_COLOR,
        MenuState::Success => SUCCESS_BG_COLOR,
        _ => BG_COLOR,
    }
}

fn menu_state_to_message_text_size(state: MenuState, screen_size: Size) -> f32 {
    let base = screen_size.width.min(screen_size.height);
    match state {
        MenuState::Warning => base / 20.0,
        MenuState::Progress => base / 25.0,
        MenuState::Error => base / 20.0,
        _ => 0.0,
    }
}

fn menu_state_to_button_text_size(state: MenuState, screen_size: Size) -> f32 {
    let base = screen_size.width.min(screen_size.height);
    match state {
        MenuState::SelectInstall => base / 20.0,
        MenuState::SelectDisk => base / 33.0,
        MenuState::Warning => base / 20.0,
        MenuState::Error => base / 20.0,
        MenuState::Success => base / 20.0,
        _ => 0.0,
    }
}

async fn drive_automated_install(app_sender: AppSender, view_key: ViewKey) {
    // Simulate pressing enter 3 times.
    for _ in 0..3 {
        app_sender.queue_message(
            MessageTarget::View(view_key),
            make_message(InstallerMessages::MenuEnter),
        );
        fasync::Timer::new(zx::Duration::from_seconds(1).after_now()).await
    }
}

async fn get_installation_paths(app_sender: AppSender, view_key: ViewKey) -> Result<(), Error> {
    let block_devices = get_block_devices().await?;
    let bootloader_type = get_bootloader_type().await?;

    // Send got bootloader message
    app_sender.queue_message(
        MessageTarget::View(view_key),
        make_message(InstallerMessages::GotBootloaderType(bootloader_type)),
    );

    // Find the location of the installer
    let install_source = find_install_source(&block_devices, bootloader_type).await?;

    // Send got installer messgae
    app_sender.queue_message(
        MessageTarget::View(view_key),
        make_message(InstallerMessages::GotInstallSource(install_source.clone())),
    );

    // Make list of available destinations for installation
    let mut destinations = Vec::new();
    for block_device in block_devices.iter() {
        if block_device != install_source {
            destinations.push(block_device.clone());
        }
    }

    // Send error if no destinations found
    if destinations.is_empty() {
        return Err(anyhow!("Found no block devices for installation."));
    };

    app_sender.queue_message(
        MessageTarget::View(view_key),
        make_message(InstallerMessages::GotBlockDevices(block_devices)),
    );

    // Else end destinations
    app_sender.queue_message(
        MessageTarget::View(view_key),
        make_message(InstallerMessages::GotInstallDestinations(
            destinations.into_iter().filter(|d| d.is_disk()).collect(),
        )),
    );

    Ok(())
}

async fn setup_installation_paths(app_sender: AppSender, view_key: ViewKey) {
    match get_installation_paths(app_sender.clone(), view_key).await {
        Ok(_install_source) => {
            tracing::info!("Found installer & block devices ");
        }
        Err(e) => {
            // Send error
            app_sender.queue_message(
                MessageTarget::View(view_key),
                make_message(InstallerMessages::Error(e.to_string())),
            );
            tracing::info!("ERROR getting install target: {}", e);
        }
    };
}

async fn fuchsia_install(
    app_sender: AppSender,
    view_key: ViewKey,
    installation_paths: InstallationPaths,
) {
    let sender =
        app_sender.create_cross_thread_sender::<InstallerMessages>(MessageTarget::View(view_key));
    let progress_callback = |s: String| {
        sender.unbounded_send(InstallerMessages::ProgressUpdate(s)).expect("unbounded send failed");
    };

    // Execute install
    match do_install(installation_paths, &progress_callback).await {
        Ok(_) => {
            app_sender.queue_message(
                MessageTarget::View(view_key),
                make_message(InstallerMessages::Success),
            );
        }
        Err(e) => {
            tracing::error!("Error while installing: {:#}", e);
            app_sender.queue_message(
                MessageTarget::View(view_key),
                make_message(InstallerMessages::Error(e.to_string())),
            );
        }
    }
}

/// Wait for a display to become available.
async fn wait_for_display() -> Result<(), Error> {
    let dir = fuchsia_fs::directory::open_in_namespace(
        "/dev/class/display-coordinator",
        fuchsia_fs::OpenFlags::empty(),
    )
    .context("opening display coordinator dir")?;
    let mut watcher = Watcher::new(&dir).await.context("starting watch")?;
    while let Some(message) = watcher.next().await {
        let message = message.context("error on watcher channel")?;
        match message.event {
            WatchEvent::ADD_FILE | WatchEvent::EXISTING => return Ok(()),
            _ => {}
        }
    }
    Err(anyhow!("Didn't find a display device"))
}

/// Check to see if we're doing a non-interactive installs.
/// Non-interactive installs are very limited and will likely only work on systems with a single
/// disk.
/// They are intended to be used in end-to-end tests.
async fn check_is_interactive() -> Result<bool, Error> {
    let proxy = fuchsia_component::client::connect_to_protocol::<ArgumentsMarker>()
        .context("Connecting to boot arguments service")?;
    let automated =
        proxy.get_bool("installer.non-interactive", false).await.context("Getting bool")?;
    tracing::info!(
        "workstation installer: {}doing automated install.",
        if automated { "" } else { "not " }
    );

    if automated {
        wait_for_install_disk().await.context("Waiting for install disk")?;
    }
    Ok(automated)
}

/// Wait for an installation source to become present on the system.
async fn wait_for_install_disk() -> Result<(), Error> {
    let dir = fuchsia_fs::directory::open_in_namespace(
        "/dev/class/block",
        fuchsia_fs::OpenFlags::empty(),
    )
    .context("opening block dir")?;
    let mut watcher = Watcher::new(&dir).await.context("starting watch")?;
    let bootloader_type = get_bootloader_type().await?;
    let mut devices = vec![];
    while let Some(message) = watcher.next().await {
        let message = message.context("error on watcher channel")?;
        let filename = message.filename.to_str().unwrap();
        if filename == "." {
            continue;
        }
        match message.event {
            WatchEvent::ADD_FILE | WatchEvent::EXISTING => {
                let path = format!("/dev/class/block/{}", filename);
                match get_block_device(&path).await {
                    Ok(Some(bd)) => {
                        devices.push(bd);
                        if let Ok(_) = find_install_source(&devices, bootloader_type).await {
                            return Ok(());
                        }
                    }
                    _ => {}
                }
            }
            _ => {}
        }
    }
    Err(anyhow!("Didn't find an install disk"))
}

#[fuchsia::main]
fn main() -> Result<(), Error> {
    tracing::info!("workstation installer: started.");

    // Before we give control to carnelian, wait until a display driver is bound.
    let (display_result, interactive_result) = fuchsia_async::LocalExecutor::new()
        .run_singlethreaded(
            async move { futures::join!(wait_for_display(), check_is_interactive()) },
        );
    display_result.context("Waiting for display controller")?;
    let automated = interactive_result.context("Fetching installer boot arguments")?;

    let config = UiConfig::take_from_startup_handle();
    let display_rotation = match config.display_rotation {
        0 => DisplayRotation::Deg0,
        180 => DisplayRotation::Deg180,
        // Carnelian uses an inverted z-axis for rotation
        90 => DisplayRotation::Deg270,
        270 => DisplayRotation::Deg90,
        val => {
            tracing::error!("Invalid display_rotation {}, defaulting to 0 degrees", val);
            DisplayRotation::Deg0
        }
    };

    App::run(Box::new(move |_| {
        Box::pin(async move {
            let assistant = Box::new(InstallerAppAssistant::new(display_rotation, automated));
            Ok::<AppAssistantPtr, Error>(assistant)
        })
    }))
}
