// Copyright 2018 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::{format_err, Error},
    carnelian::{
        app::{Config, ViewMode},
        color::Color,
        drawing::{path_for_circle, DisplayRotation, FontFace},
        input, make_message,
        render::{
            rive::load_rive, BlendMode, Context as RenderContext, Fill, FillRule, Raster, Style,
        },
        scene::{
            facets::{
                RasterFacet, RiveFacet, TextFacetOptions, TextHorizontalAlignment,
                TextVerticalAlignment,
            },
            layout::{
                CrossAxisAlignment, Flex, FlexOptions, MainAxisAlignment, MainAxisSize, Stack,
                StackOptions,
            },
            scene::{Scene, SceneBuilder},
        },
        App, AppAssistant, AppAssistantPtr, AppSender, AssistantCreatorFunc, Coord, LocalBoxFuture,
        MessageTarget, Point, Size, ViewAssistant, ViewAssistantContext, ViewAssistantPtr, ViewKey,
    },
    euclid::size2,
    fdr_lib::{self as fdr, FactoryResetState, ResetEvent},
    fidl_fuchsia_input_report::ConsumerControlButton,
    fidl_fuchsia_recovery_policy::FactoryResetMarker as FactoryResetPolicyMarker,
    fuchsia_async::{self as fasync, Task},
    fuchsia_component::client::connect_to_protocol,
    fuchsia_zircon::{Duration, Event},
    futures::StreamExt,
    recovery_ui::{font, proxy_view_assistant::ProxyViewAssistant},
    recovery_ui_config::Config as UiConfig,
    rive_rs::{self as rive},
    std::{
        borrow::{Borrow, Cow},
        path::Path,
    },
};

#[cfg(feature = "ota_ui")]
mod ui_v2;

#[cfg(feature = "http_setup_server")]
use {
    fidl::endpoints::{DiscoverableProtocolMarker, RequestStream},
    fidl_fuchsia_recovery_ui::{
        ProgressRendererMarker, ProgressRendererRequest, ProgressRendererRequestStream, Status,
    },
    fuchsia_async::DurationExt,
    fuchsia_runtime::{take_startup_handle, HandleType},
    ota_lib::{ota, setup, OtaComponent, OtaManager, OtaStatus},
    recovery_ui::{
        button::{Button, ButtonMessages, ButtonOptions, ButtonShape, SceneBuilderButtonExt},
        keyboard::{KeyboardMessages, KeyboardViewAssistant},
        proxy_view_assistant::ProxyMessages,
    },
    recovery_util::{
        cobalt::{self, metrics, Cobalt, CobaltImpl},
        reboot::{RebootHandler, RebootImpl},
        regulatory,
    },
    std::sync::Arc,
};

#[cfg(feature = "debug_console")]
use recovery_ui::console::{ConsoleMessages, ConsoleViewAssistant};

// 11 seconds so it can count from 10 down to 0 while displaying each tick for 1 second
const FACTORY_RESET_TIMER_IN_SECONDS: u8 = 11;
const LOGO_IMAGE_PATH: &str = "/pkg/data/logo.riv";
const INSTRUCTIONS_TEXT_PATH: &str = "/pkg/data/instructions.txt";
const BG_COLOR: Color = Color::white();
const HEADING_COLOR: Color = Color::new();
const BODY_COLOR: Color = Color { r: 0x7e, g: 0x86, b: 0x8d, a: 0xff };
const COUNTDOWN_COLOR: Color = Color { r: 0x42, g: 0x85, b: 0xf4, a: 0xff };

#[cfg(feature = "http_setup_server")]
mod http_setup_server {
    #[derive(Clone, PartialEq)]
    pub(super) enum WiFiMessages {
        Connecting,
        Connected(bool),
    }

    pub(super) const BUTTON_BORDER: f32 = 7.0;
    // Space added to between rows can have any width.
    pub(super) const SPACE_WIDTH: f32 = 10.0;
    // Nice space for text below a button
    pub(super) const SPACE_HEIGHT: f32 = 10.0;

    pub(super) const WIFI_SSID: &'static str = "WiFi Name";
    pub(super) const WIFI_PASSWORD: &'static str = "WiFi Password";
    pub(super) const WIFI_CONNECT: &'static str = "WiFi Connect";
    pub(super) const UPDATE: &'static str = "Update";
    pub(super) const REBOOT_DELAY_SECONDS: u64 = 10;
}

#[cfg(feature = "http_setup_server")]
use crate::{http_setup_server::*, setup::SetupEvent};

fn raster_for_circle(center: Point, radius: Coord, render_context: &mut RenderContext) -> Raster {
    let path = path_for_circle(center, radius, render_context);
    let mut raster_builder = render_context.raster_builder().expect("raster_builder");
    raster_builder.add(&path, None);
    raster_builder.build()
}

enum RecoveryMessages {
    #[cfg(feature = "http_setup_server")]
    EventReceived,
    #[cfg(feature = "http_setup_server")]
    StartingOta,
    #[cfg(feature = "http_setup_server")]
    OtaFinished {
        result: Result<(), Error>,
    },
    PolicyResult(usize, bool),
    ResetMessage(FactoryResetState),
    CountdownTick(u8),
    ResetFailed,
}

const RECOVERY_MODE_HEADLINE: &'static str = "Recovery mode";
const COUNTDOWN_MODE_HEADLINE: &'static str = "Factory reset device";
const COUNTDOWN_MODE_BODY: &'static str =
    "\nContinue holding the keys to the end of the countdown. \
This will wipe all of your data from this device and reset it to factory settings.";

const PATH_TO_FDR_RESTRICTION_CONFIG: &'static str = "/config/data/check_fdr_restriction.json";

/// An enum to track whether fdr is restricted or not.
#[derive(Copy, Clone)]
enum FdrRestriction {
    /// Fdr is not restricted and can proceed without any additional checks.
    NotRestricted,
    /// Fdr is possibly restricted. The policy should be checked when attempting
    /// factory device reset.
    Restricted { fdr_initially_enabled: bool },
}

impl FdrRestriction {
    fn is_initially_enabled(&self) -> bool {
        match self {
            FdrRestriction::NotRestricted => true,
            FdrRestriction::Restricted { fdr_initially_enabled } => *fdr_initially_enabled,
        }
    }
}

struct RecoveryAppAssistant {
    app_sender: AppSender,
    display_rotation: DisplayRotation,
    fdr_restriction: FdrRestriction,
    #[cfg(feature = "http_setup_server")]
    ota_manager: Arc<dyn OtaManager>,
}

impl RecoveryAppAssistant {
    pub fn new(
        app_sender: &AppSender,
        display_rotation: DisplayRotation,
        fdr_restriction: FdrRestriction,
        #[cfg(feature = "http_setup_server")] ota_manager: Arc<dyn OtaManager>,
    ) -> Self {
        Self {
            app_sender: app_sender.clone(),
            display_rotation,
            fdr_restriction,
            #[cfg(feature = "http_setup_server")]
            ota_manager,
        }
    }

    #[cfg(feature = "http_setup_server")]
    async fn update_ota_manager(ota_manager: &dyn OtaManager, status: Status) {
        match status {
            Status::Active => {
                println!("OTA update is now in progress...")
            }
            Status::Complete => ota_manager.complete_ota(OtaStatus::Succeeded).await,
            _ => ota_manager.complete_ota(OtaStatus::Failed).await,
        }
    }
}

impl AppAssistant for RecoveryAppAssistant {
    fn setup(&mut self) -> Result<(), Error> {
        println!("recovery: AppAssistant setup");
        Ok(())
    }

    fn create_view_assistant(&mut self, view_key: ViewKey) -> Result<ViewAssistantPtr, Error> {
        let body = get_recovery_body(self.fdr_restriction.is_initially_enabled());
        let file = load_rive(LOGO_IMAGE_PATH).ok();
        let font_face = font::get_default_font_face().clone();

        #[cfg(feature = "debug_console")]
        let console_view_assistant_ptr: Option<ViewAssistantPtr> =
            Some(Box::new(ConsoleViewAssistant::new(font_face.clone())?));
        #[cfg(not(feature = "debug_console"))]
        let console_view_assistant_ptr: Option<ViewAssistantPtr> = None;
        let app_sender = self.app_sender.clone();
        let view_assistant_ptr = Box::new(RecoveryViewAssistant::new(
            app_sender,
            view_key,
            file,
            RECOVERY_MODE_HEADLINE,
            body.map(Into::into),
            self.fdr_restriction,
            font_face,
            #[cfg(feature = "http_setup_server")]
            self.ota_manager.clone(),
        )?);

        // ProxyView is a root view that conditionally displays the top View
        // from a stack (initialized with "RecoveryView"), or the Console.
        let proxy_ptr = Box::new(ProxyViewAssistant::new(
            None,
            console_view_assistant_ptr,
            view_assistant_ptr,
        )?);
        Ok(proxy_ptr)
    }

    #[cfg(feature = "http_setup_server")]
    fn outgoing_services_names(&self) -> Vec<&'static str> {
        vec![ProgressRendererMarker::PROTOCOL_NAME]
    }

    #[cfg(feature = "http_setup_server")]
    fn handle_service_connection_request(
        &mut self,
        service_name: &str,
        channel: fasync::Channel,
    ) -> Result<(), Error> {
        match service_name {
            ProgressRendererMarker::PROTOCOL_NAME => {
                let ota_manager = self.ota_manager.clone();

                fasync::Task::local(async move {
                    let mut stream = ProgressRendererRequestStream::from_channel(channel);
                    while let Some(Ok(request)) = stream.next().await {
                        match request {
                            ProgressRendererRequest::Render {
                                status,
                                percent_complete: _,
                                responder,
                            } => {
                                Self::update_ota_manager(&*ota_manager, status).await;
                                responder.send().expect("Error replying to progress update");
                            }
                            ProgressRendererRequest::Render2 { payload, responder } => {
                                if let Some(status) = payload.status {
                                    Self::update_ota_manager(&*ota_manager, status).await;
                                }
                                responder.send().expect("Error replying to progress update");
                            }
                        }
                    }
                })
                .detach();
            }
            _ => panic!("Error: Unexpected service: {}", service_name),
        }
        Ok(())
    }

    fn filter_config(&mut self, config: &mut Config) {
        config.display_rotation = self.display_rotation;
        config.view_mode = ViewMode::Direct;
    }
}

#[cfg(feature = "http_setup_server")]
struct RenderResources {
    scene: Scene,
    #[cfg(feature = "http_setup_server")]
    buttons: Vec<Button>,
}

#[cfg(not(feature = "http_setup_server"))]
struct RenderResources {
    scene: Scene,
}

impl RenderResources {
    fn new(
        render_context: &mut RenderContext,
        file: &Option<rive::File>,
        target_size: Size,
        heading: &str,
        body: Option<&str>,
        countdown_ticks: u8,
        #[cfg(feature = "http_setup_server")] wifi_ssid: &Option<String>,
        #[cfg(feature = "http_setup_server")] wifi_password: &Option<String>,
        #[cfg(feature = "http_setup_server")] wifi_connected: &WiFiMessages,
        face: &FontFace,
        is_counting_down: bool,
    ) -> Self {
        let min_dimension = target_size.width.min(target_size.height);
        let logo_edge = min_dimension * 0.24;
        let text_size = min_dimension / 10.0;
        let body_text_size = min_dimension / 18.0;
        #[cfg(feature = "http_setup_server")]
        let button_text_size = min_dimension / 16.0;
        let countdown_text_size = min_dimension / 6.0;
        #[cfg(feature = "http_setup_server")]
        let mut buttons: Vec<Button> = Vec::new();

        let mut builder = SceneBuilder::new().background_color(BG_COLOR).round_scene_corners(true);
        builder.group().column().max_size().main_align(MainAxisAlignment::Start).contents(
            |builder| {
                let logo_size: Size = size2(logo_edge, logo_edge);
                builder.space(size2(min_dimension, 50.0));

                if is_counting_down {
                    // Centre the circle and countdown in the screen
                    builder.start_group(
                        "circle_and_countdown_row",
                        Flex::with_options_ptr(FlexOptions::row(
                            MainAxisSize::Max,
                            MainAxisAlignment::Center,
                            CrossAxisAlignment::End,
                        )),
                    );

                    // Stack the circle and text
                    builder.start_group(
                        "circle_stack",
                        Stack::with_options_ptr(StackOptions {
                            expand: false,
                            alignment: carnelian::scene::layout::Alignment::center(),
                        }),
                    );

                    // Display countdown as 1 less than ticks remaining, don't allow negative numbers
                    let countdown_ticks = std::cmp::max(countdown_ticks as i32 - 1, 0);
                    // Place countdown text
                    builder.text(
                        face.clone(),
                        &format!("{}", countdown_ticks),
                        countdown_text_size,
                        Point::zero(),
                        TextFacetOptions {
                            color: Color::white(),
                            horizontal_alignment: TextHorizontalAlignment::Center,
                            vertical_alignment: TextVerticalAlignment::Bottom,
                            visual: true,
                            ..TextFacetOptions::default()
                        },
                    );

                    let circle = raster_for_circle(
                        Point::new(logo_edge / 2.0, logo_edge / 2.0),
                        logo_edge / 2.0,
                        render_context,
                    );
                    let circle_facet = RasterFacet::new(
                        circle,
                        Style {
                            fill_rule: FillRule::NonZero,
                            fill: Fill::Solid(COUNTDOWN_COLOR),
                            blend_mode: BlendMode::Over,
                        },
                        logo_size,
                    );
                    builder.facet(Box::new(circle_facet));

                    builder.end_group(); // circle_stack
                    builder.end_group(); // circle_and_countdown_row
                } else {
                    if let Some(file) = file {
                        // Centre the logo
                        builder.start_group(
                            "logo_row",
                            Flex::with_options_ptr(FlexOptions::row(
                                MainAxisSize::Max,
                                MainAxisAlignment::Center,
                                CrossAxisAlignment::End,
                            )),
                        );

                        let facet = RiveFacet::new_from_file(logo_size, &file, None)
                            .expect("facet_from_file");
                        builder.facet(Box::new(facet));
                        builder.end_group(); // logo_row
                    }
                }

                builder.space(size2(min_dimension, 50.0));
                builder.text(
                    face.clone(),
                    &heading,
                    text_size,
                    Point::zero(),
                    TextFacetOptions {
                        horizontal_alignment: TextHorizontalAlignment::Center,
                        color: HEADING_COLOR,
                        ..TextFacetOptions::default()
                    },
                );

                let wrap_width = target_size.width * 0.8;

                if let Some(body) = body {
                    builder.text(
                        face.clone(),
                        &body,
                        body_text_size,
                        Point::zero(),
                        TextFacetOptions {
                            horizontal_alignment: TextHorizontalAlignment::Left,
                            color: BODY_COLOR,
                            max_width: Some(wrap_width),
                            ..TextFacetOptions::default()
                        },
                    );
                }

                // Add the WiFi connection buttons.
                #[cfg(feature = "http_setup_server")]
                if !is_counting_down {
                    builder.space(size2(min_dimension, 50.0));
                    builder.start_group(
                        "button_row",
                        Flex::with_options_ptr(FlexOptions::row(
                            MainAxisSize::Max,
                            MainAxisAlignment::SpaceEvenly,
                            CrossAxisAlignment::End,
                        )),
                    );

                    let button_text = WIFI_SSID;
                    let info_text = if let Some(wifi_ssid) = wifi_ssid.as_ref() {
                        wifi_ssid
                    } else {
                        "<No Name>"
                    };
                    RenderResources::build_button_group(
                        face,
                        body_text_size,
                        button_text_size,
                        &mut buttons,
                        builder,
                        wrap_width,
                        &button_text,
                        info_text,
                    );

                    let button_text = WIFI_PASSWORD;
                    let info_text =
                        if wifi_password.is_some() && !wifi_password.as_ref().unwrap().is_empty() {
                            "********"
                        } else {
                            "<No Password>"
                        };
                    RenderResources::build_button_group(
                        face,
                        body_text_size,
                        button_text_size,
                        &mut buttons,
                        builder,
                        wrap_width,
                        &button_text,
                        info_text,
                    );

                    let button_text = WIFI_CONNECT;
                    let info_text = match wifi_connected {
                        WiFiMessages::Connecting => "Connecting",
                        WiFiMessages::Connected(connected) => {
                            if *connected {
                                "Connected"
                            } else {
                                "Not Connected"
                            }
                        }
                    };
                    RenderResources::build_button_group(
                        face,
                        body_text_size,
                        button_text_size,
                        &mut buttons,
                        builder,
                        wrap_width,
                        &button_text,
                        info_text,
                    );

                    let button_text = UPDATE;
                    let info_text = " ";
                    RenderResources::build_button_group(
                        face,
                        body_text_size,
                        button_text_size,
                        &mut buttons,
                        builder,
                        wrap_width,
                        &button_text,
                        info_text,
                    );

                    // End row button_row
                    builder.end_group();
                }
            },
        );

        let mut scene = builder.build();
        scene.layout(target_size);
        #[cfg(feature = "http_setup_server")]
        {
            if buttons.len() >= 4 {
                buttons[0].set_focused(&mut scene, true);
                buttons[1].set_focused(&mut scene, true);
                buttons[2].set_focused(
                    &mut scene,
                    wifi_ssid.is_some() && wifi_connected == &WiFiMessages::Connected(false),
                );
                buttons[3]
                    .set_focused(&mut scene, wifi_connected == &WiFiMessages::Connected(true));
            }
            Self { scene, buttons }
        }

        #[cfg(not(feature = "http_setup_server"))]
        Self { scene }
    }

    #[cfg(feature = "http_setup_server")]
    fn build_button_group(
        face: &FontFace,
        body_text_size: f32,
        button_text_size: f32,
        buttons: &mut Vec<Button>,
        builder: &mut SceneBuilder,
        wrap_width: f32,
        button_text: &&str,
        info_text: &str,
    ) {
        builder.start_group(
            &("button_group_".to_owned() + button_text),
            Flex::with_options_ptr(FlexOptions::column(
                MainAxisSize::Min,
                MainAxisAlignment::SpaceEvenly,
                CrossAxisAlignment::Center,
            )),
        );
        buttons.push(builder.button(
            button_text,
            None,
            ButtonOptions {
                font_size: button_text_size,
                padding: BUTTON_BORDER,
                shape: ButtonShape::Rounded,
                ..ButtonOptions::default()
            },
        ));
        builder.space(size2(SPACE_WIDTH, SPACE_HEIGHT));
        builder.text(
            face.clone(),
            info_text,
            body_text_size,
            Point::zero(),
            TextFacetOptions {
                horizontal_alignment: TextHorizontalAlignment::Left,
                color: BODY_COLOR,
                max_width: Some(wrap_width),
                ..TextFacetOptions::default()
            },
        );
        // End column button_group_password
        builder.end_group();
    }
}

struct RecoveryViewAssistant {
    font_face: FontFace,
    heading: &'static str,
    body: Option<Cow<'static, str>>,
    fdr_restriction: FdrRestriction,
    reset_state_machine: fdr::FactoryResetStateMachine,
    app_sender: AppSender,
    view_key: ViewKey,
    file: Option<rive::File>,
    countdown_task: Option<Task<()>>,
    countdown_ticks: u8,
    render_resources: Option<RenderResources>,
    #[cfg(feature = "http_setup_server")]
    wifi_ssid: Option<String>,
    #[cfg(feature = "http_setup_server")]
    wifi_password: Option<String>,
    #[cfg(feature = "http_setup_server")]
    connected: WiFiMessages,
    #[cfg(feature = "http_setup_server")]
    ota_manager: Arc<dyn OtaManager>,
}

impl RecoveryViewAssistant {
    fn new(
        app_sender: AppSender,
        view_key: ViewKey,
        file: Option<rive::File>,
        heading: &'static str,
        body: Option<Cow<'static, str>>,
        fdr_restriction: FdrRestriction,
        font_face: FontFace,
        #[cfg(feature = "http_setup_server")] ota_manager: Arc<dyn OtaManager>,
    ) -> Result<RecoveryViewAssistant, Error> {
        RecoveryViewAssistant::setup(app_sender.clone(), view_key)?;

        Ok(RecoveryViewAssistant {
            font_face,
            heading,
            body,
            fdr_restriction,
            reset_state_machine: fdr::FactoryResetStateMachine::new(),
            app_sender: app_sender,
            view_key,
            file,
            countdown_task: None,
            countdown_ticks: FACTORY_RESET_TIMER_IN_SECONDS,
            render_resources: None,
            #[cfg(feature = "http_setup_server")]
            wifi_ssid: None,
            #[cfg(feature = "http_setup_server")]
            wifi_password: None,
            #[cfg(feature = "http_setup_server")]
            connected: WiFiMessages::Connected(false),
            #[cfg(feature = "http_setup_server")]
            ota_manager,
        })
    }

    #[cfg(not(feature = "http_setup_server"))]
    fn setup(_: AppSender, _: ViewKey) -> Result<(), Error> {
        Ok(())
    }

    #[cfg(feature = "http_setup_server")]
    fn setup(app_sender: AppSender, view_key: ViewKey) -> Result<(), Error> {
        use futures::FutureExt as _;

        // TODO: it should be possible to pass a handler function and avoid the need for message
        // passing, but AppSender eventually contains carnelian::FrameBufferPtr which is an alias
        // for Rc<_> which is !Send.
        let (sender, receiver) = async_channel::unbounded();
        fasync::Task::local(
            setup::start_server(move |event| async move { sender.send(event).await.unwrap() }).map(
                |result| {
                    result
                        .unwrap_or_else(|error| eprintln!("recovery: HTTP server error: {}", error))
                },
            ),
        )
        .detach();

        fasync::Task::local(
            receiver
                .fold(app_sender, move |local_app_sender, event| async move {
                    println!("recovery: received request");
                    match event {
                        SetupEvent::Root => local_app_sender.queue_message(
                            MessageTarget::View(view_key),
                            make_message(RecoveryMessages::EventReceived),
                        ),
                        SetupEvent::DevhostOta { cfg } => {
                            local_app_sender.queue_message(
                                MessageTarget::View(view_key),
                                make_message(RecoveryMessages::StartingOta),
                            );
                            match take_startup_handle(HandleType::DirectoryRequest.into()) {
                                Some(out_dir_handle) => {
                                    let out_dir =
                                        fuchsia_zircon::Channel::from(out_dir_handle).into();

                                    // TODO(https://fxbug.dev/42064284): make this call the OTA component
                                    // instead of calling isolated-ota here.
                                    let result = ota::run_devhost_ota(cfg, out_dir).await;
                                    local_app_sender.queue_message(
                                        MessageTarget::View(view_key),
                                        make_message(RecoveryMessages::OtaFinished { result }),
                                    );
                                }
                                None => {
                                    local_app_sender.queue_message(
                                        MessageTarget::View(view_key),
                                        make_message(RecoveryMessages::OtaFinished {
                                            result: Err(anyhow::anyhow!(
                                                "Couldn't take startup handle"
                                            )),
                                        }),
                                    );
                                }
                            }
                        }
                    }
                    local_app_sender
                })
                .map(|_: AppSender| ()),
        )
        .detach();

        Ok(())
    }

    /// Checks whether fdr policy allows factory reset to be performed. If not, then it will not
    /// move forward with the reset. If it is, then it will forward the message to begin reset.
    async fn check_fdr_and_maybe_reset(view_key: ViewKey, app_sender: AppSender, check_id: usize) {
        let fdr_enabled = check_fdr_enabled().await.unwrap_or_else(|error| {
            eprintln!("recovery: Error occurred, but proceeding with reset: {:?}", error);
            true
        });
        app_sender.queue_message(
            MessageTarget::View(view_key),
            make_message(RecoveryMessages::PolicyResult(check_id, fdr_enabled)),
        );
    }

    fn handle_recovery_message(&mut self, message: &RecoveryMessages) {
        match message {
            #[cfg(feature = "http_setup_server")]
            RecoveryMessages::EventReceived => {
                self.body = Some("Got event".into());
            }
            #[cfg(feature = "http_setup_server")]
            RecoveryMessages::StartingOta => {
                self.body = Some("Starting OTA update".into());
                self.render_resources = None;
                self.app_sender.request_render(self.view_key);
            }
            #[cfg(feature = "http_setup_server")]
            RecoveryMessages::OtaFinished { result } => {
                // _e because it will be unused if debug_console is not used
                if let Err(_e) = result {
                    self.body = Some(format!("OTA failed").into());
                    #[cfg(feature = "debug_console")]
                    self.app_sender.queue_message(
                        MessageTarget::View(self.view_key),
                        make_message(ConsoleMessages::AddText(format!("OTA error: {:?}", _e))),
                    );
                } else {
                    self.body = Some("OTA succeeded".into());
                }
                self.render_resources = None;
                self.app_sender.request_render(self.view_key);
            }
            RecoveryMessages::PolicyResult(check_id, fdr_enabled) => {
                let state = self
                    .reset_state_machine
                    .handle_event(ResetEvent::AwaitPolicyResult(*check_id, *fdr_enabled));
                self.app_sender.queue_message(
                    MessageTarget::View(self.view_key),
                    make_message(RecoveryMessages::ResetMessage(state)),
                );
            }
            RecoveryMessages::ResetMessage(state) => {
                match state {
                    FactoryResetState::Waiting => {
                        self.heading = RECOVERY_MODE_HEADLINE;
                        self.body = get_recovery_body(self.fdr_restriction.is_initially_enabled())
                            .map(Into::into);
                        self.render_resources = None;
                        self.app_sender.request_render(self.view_key);
                    }
                    FactoryResetState::AwaitingPolicy(_) => {} // no-op
                    FactoryResetState::StartCountdown => {
                        let view_key = self.view_key;
                        let local_app_sender = self.app_sender.clone();

                        let mut counter = FACTORY_RESET_TIMER_IN_SECONDS;
                        local_app_sender.queue_message(
                            MessageTarget::View(view_key),
                            make_message(RecoveryMessages::CountdownTick(counter)),
                        );

                        // start the countdown timer
                        let f = async move {
                            let mut interval_timer =
                                fasync::Interval::new(Duration::from_seconds(1));
                            while let Some(()) = interval_timer.next().await {
                                counter -= 1;
                                local_app_sender.queue_message(
                                    MessageTarget::View(view_key),
                                    make_message(RecoveryMessages::CountdownTick(counter)),
                                );
                                if counter == 0 {
                                    break;
                                }
                            }
                        };
                        self.countdown_task = Some(fasync::Task::local(f));
                    }
                    FactoryResetState::CancelCountdown => {
                        self.countdown_task = None;
                        let state =
                            self.reset_state_machine.handle_event(ResetEvent::CountdownCancelled);
                        assert_eq!(state, fdr::FactoryResetState::Waiting);
                        self.app_sender.queue_message(
                            MessageTarget::View(self.view_key),
                            make_message(RecoveryMessages::ResetMessage(state)),
                        );
                    }
                    FactoryResetState::ExecuteReset => {
                        let view_key = self.view_key;
                        let local_app_sender = self.app_sender.clone();
                        let f = async move {
                            if let Err(error) = fdr::reset_active_slot().await {
                                // If we fail to reset active slot, log an error and continue. There are cases
                                // where FDR can provide value without setting the active slot.
                                eprintln!(
                                    "Error occurred attempting to reset active slot: {:?}",
                                    error
                                );
                            }
                            if let Err(error) = fdr::execute_reset().await {
                                local_app_sender.queue_message(
                                    MessageTarget::View(view_key),
                                    make_message(RecoveryMessages::ResetFailed),
                                );
                                eprintln!(
                                    "Error occurred attempting to factory reset: {:?}",
                                    error
                                );
                            };
                        };
                        fasync::Task::local(f).detach();
                    }
                    FactoryResetState::AwaitingReset => {} // no-op
                };
            }
            RecoveryMessages::CountdownTick(count) => {
                self.heading = COUNTDOWN_MODE_HEADLINE;
                self.countdown_ticks = *count;
                if *count == 0 {
                    self.body = Some("Resetting device...".into());
                    let state =
                        self.reset_state_machine.handle_event(ResetEvent::CountdownFinished);
                    assert_eq!(state, FactoryResetState::ExecuteReset);
                    self.app_sender.queue_message(
                        MessageTarget::View(self.view_key),
                        make_message(RecoveryMessages::ResetMessage(state)),
                    );
                } else {
                    self.body = Some(COUNTDOWN_MODE_BODY.into());
                }
                self.render_resources = None;
                self.app_sender.request_render(self.view_key);
            }
            RecoveryMessages::ResetFailed => {
                self.heading = "Reset failed";
                self.body = Some("Please restart device to try again".into());
                self.render_resources = None;
                self.app_sender.request_render(self.view_key);
            }
        }
    }

    #[cfg(feature = "http_setup_server")]
    fn handle_keyboard_message(&mut self, message: &KeyboardMessages) {
        match message {
            KeyboardMessages::NoInput => {}
            KeyboardMessages::Result(field_name, result) if field_name == WIFI_SSID => {
                self.wifi_ssid = if result.len() == 0 { None } else { Some(result.clone()) };
                self.render_resources = None;
            }
            KeyboardMessages::Result(field_name, result) if field_name == WIFI_PASSWORD => {
                // Allow empty passwords
                self.wifi_password = Some(result.clone());
                self.render_resources = None;
            }
            KeyboardMessages::Result(_, _) => {}
        }
    }

    #[cfg(feature = "http_setup_server")]
    fn handle_button_message(&mut self, message: &ButtonMessages) {
        match message {
            ButtonMessages::Pressed(_, label) => {
                #[cfg(feature = "debug_console")]
                self.app_sender.queue_message(
                    MessageTarget::View(self.view_key),
                    make_message(ConsoleMessages::AddText(format!("Button pressed: {}", label))),
                );

                let mut entry_text = String::new();
                let mut field_text = "";
                match label.as_ref() {
                    WIFI_SSID => {
                        field_text = WIFI_SSID;
                        if let Some(ssid) = &self.wifi_ssid {
                            entry_text = ssid.clone();
                        }
                    }
                    WIFI_PASSWORD => {
                        field_text = WIFI_PASSWORD;
                        if let Some(password) = &self.wifi_password {
                            entry_text = password.clone();
                        }
                    }
                    WIFI_CONNECT => {
                        if let Some(ssid) = &self.wifi_ssid {
                            // Allow empty passwords
                            let mut password = "";
                            if let Some(wifi_password) = &self.wifi_password {
                                password = wifi_password;
                            };
                            let local_app_sender = self.app_sender.clone();
                            local_app_sender.queue_message(
                                MessageTarget::View(self.view_key),
                                make_message(WiFiMessages::Connecting),
                            );

                            let ssid = ssid.clone();
                            let password = password.to_string().clone();
                            let view_key = self.view_key.clone();
                            let f = async move {
                                let connected = connect_to_wifi(ssid, password).await;
                                match connected {
                                    Ok(()) => {
                                        cobalt::log_metric!(
                                            cobalt::log_recovery_stage,
                                            metrics::RecoveryEventMetricDimensionResult::WiFiConnected
                                        );
                                    }
                                    Err(_) => {
                                        // Let the "Connecting" message stay there for a second so
                                        // the user can see that something was tried.
                                        let sleep_time = Duration::from_seconds(1);
                                        fuchsia_async::Timer::new(sleep_time.after_now()).await;
                                        println!(
                                            "Failed to connect: {}",
                                            connected.as_ref().err().unwrap()
                                        );
                                    }
                                }

                                local_app_sender.queue_message(
                                    MessageTarget::View(view_key),
                                    make_message(WiFiMessages::Connected(connected.is_ok())),
                                );

                                #[cfg(feature = "debug_console")]
                                local_app_sender.queue_message(
                                    MessageTarget::View(view_key),
                                    make_message(ConsoleMessages::AddText(format!(
                                        "Wifi Connect Attempt: {}",
                                        if connected.is_err() {
                                            format!("Failed! ({:?})", connected.err().unwrap())
                                        } else {
                                            "Succeeded!".to_string()
                                        }
                                    ))),
                                );
                            };
                            fasync::Task::local(f).detach();
                        }
                    }
                    UPDATE => {
                        let local_app_sender = self.app_sender.clone();
                        let view_key = self.view_key.clone();
                        local_app_sender.queue_message(
                            MessageTarget::View(view_key),
                            make_message(RecoveryMessages::StartingOta),
                        );

                        let ota_manager = self.ota_manager.clone();
                        let f = async move {
                            cobalt::log_metric!(
                                cobalt::log_recovery_stage,
                                metrics::RecoveryEventMetricDimensionResult::OtaStarted
                            );

                            let start_time = fasync::Time::now();

                            // Even if stop fails, try to update anyway.
                            println!("Stopping running OTAs...");
                            if let Err(e) = ota_manager.stop().await {
                                eprintln!("failed to stop OTA: {:?}", e);
                            }

                            println!("Starting OTA process and waiting...");
                            let res = ota_manager.start_and_wait_for_result().await;

                            let end_time = fasync::Time::now();
                            let elapsed_time = (end_time - start_time).into_seconds();

                            match res {
                                Ok(_) => {
                                    println!("OTA Success!");
                                    fasync::Task::local(async move {
                                        cobalt::log_metric!(cobalt::log_ota_duration, elapsed_time);
                                        cobalt::log_metric!(
                                            cobalt::log_recovery_stage,
                                            metrics::RecoveryEventMetricDimensionResult::OtaSuccess
                                        );

                                        let cobalt = CobaltImpl::default();
                                        if let Err(err) = cobalt.aggregate_and_upload(
                                            REBOOT_DELAY_SECONDS.try_into().unwrap(),
                                        ) {
                                            eprintln!(
                                                "aggregate_upload encountered an error {:?}",
                                                err
                                            )
                                        } else {
                                            println!("aggregate_upload finished");
                                        }

                                        let reboot_handler = RebootImpl::default();
                                        if let Err(e) = reboot_handler.reboot(None).await {
                                            eprintln!("Failed to reboot: {:?}", e);
                                        }
                                    })
                                    .detach();
                                }
                                Err(ref e) => {
                                    println!("OTA Error..... {:?}", e);
                                    fasync::Task::local(async move {
                                        cobalt::log_metric!(
                                            cobalt::log_recovery_stage,
                                            metrics::RecoveryEventMetricDimensionResult::OtaFailed
                                        );
                                    })
                                    .detach();
                                }
                            }

                            local_app_sender.queue_message(
                                MessageTarget::View(view_key),
                                make_message(RecoveryMessages::OtaFinished { result: res }),
                            );
                        };
                        fasync::Task::local(f).detach();
                    }
                    _ => {}
                }
                if !field_text.is_empty() {
                    // Fire up a new keyboard
                    let mut keyboard = Box::new(
                        KeyboardViewAssistant::new(
                            self.app_sender.clone(),
                            self.view_key,
                            self.font_face.clone(),
                        )
                        .unwrap(),
                    );
                    keyboard.set_field_name(field_text.to_string());
                    keyboard.set_text_field(entry_text);
                    self.app_sender.queue_message(
                        MessageTarget::View(self.view_key),
                        make_message(ProxyMessages::NewViewAssistant(Some(keyboard))),
                    );
                }
            }
        }
    }

    #[cfg(feature = "http_setup_server")]
    fn handle_wifi_message(&mut self, message: &WiFiMessages) {
        self.connected = message.clone();
        self.render_resources = None;
    }
}

impl ViewAssistant for RecoveryViewAssistant {
    fn setup(&mut self, context: &ViewAssistantContext) -> Result<(), Error> {
        self.view_key = context.key;
        Ok(())
    }

    fn render(
        &mut self,
        render_context: &mut RenderContext,
        ready_event: Event,
        context: &ViewAssistantContext,
    ) -> Result<(), Error> {
        // Emulate the size that Carnelian passes when the display is rotated
        let target_size = context.size;

        if self.render_resources.is_none() {
            self.render_resources = Some(RenderResources::new(
                render_context,
                &self.file,
                target_size,
                self.heading,
                self.body.as_ref().map(Borrow::borrow),
                self.countdown_ticks,
                #[cfg(feature = "http_setup_server")]
                &self.wifi_ssid,
                #[cfg(feature = "http_setup_server")]
                &self.wifi_password,
                #[cfg(feature = "http_setup_server")]
                &self.connected,
                &self.font_face,
                self.reset_state_machine.is_counting_down(),
            ));
        }

        let render_resources = self.render_resources.as_mut().unwrap();
        render_resources.scene.render(render_context, ready_event, context)?;
        context.request_render();
        Ok(())
    }

    fn handle_message(&mut self, message: carnelian::Message) {
        if let Some(message) = message.downcast_ref::<RecoveryMessages>() {
            self.handle_recovery_message(message);
        } else if cfg!(feature = "http_setup_server") {
            #[cfg(feature = "http_setup_server")]
            if let Some(message) = message.downcast_ref::<ButtonMessages>() {
                self.handle_button_message(message);
            } else if let Some(message) = message.downcast_ref::<KeyboardMessages>() {
                self.handle_keyboard_message(message);
            } else if let Some(message) = message.downcast_ref::<WiFiMessages>() {
                self.handle_wifi_message(message);
            } else {
                println!("Unknown message received: {:#?}", message);
            }
        }
    }

    fn handle_consumer_control_event(
        &mut self,
        context: &mut ViewAssistantContext,
        _: &input::Event,
        consumer_control_event: &input::consumer_control::Event,
    ) -> Result<(), Error> {
        match consumer_control_event.button {
            ConsumerControlButton::VolumeUp | ConsumerControlButton::VolumeDown => {
                let state = self.reset_state_machine.handle_event(ResetEvent::ButtonPress(
                    consumer_control_event.button,
                    consumer_control_event.phase,
                ));

                if let fdr::FactoryResetState::AwaitingPolicy(check_id) = state {
                    match self.fdr_restriction {
                        FdrRestriction::Restricted { .. } => {
                            fasync::Task::local(RecoveryViewAssistant::check_fdr_and_maybe_reset(
                                self.view_key,
                                self.app_sender.clone(),
                                check_id,
                            ))
                            .detach();
                        }
                        // When fdr is not restricted, immediately send an enabled event.
                        FdrRestriction::NotRestricted => {
                            let state = self
                                .reset_state_machine
                                .handle_event(ResetEvent::AwaitPolicyResult(check_id, true));
                            if state != fdr::FactoryResetState::ExecuteReset {
                                context.queue_message(make_message(
                                    RecoveryMessages::ResetMessage(state),
                                ));
                            }
                        }
                    }
                } else {
                    context.queue_message(make_message(RecoveryMessages::ResetMessage(state)));
                }
            }
            _ => {}
        }
        Ok(())
    }

    #[cfg(feature = "http_setup_server")]
    fn handle_pointer_event(
        &mut self,
        context: &mut ViewAssistantContext,
        _event: &input::Event,
        pointer_event: &input::pointer::Event,
    ) -> Result<(), Error> {
        if let Some(render_resources) = self.render_resources.as_mut() {
            for button in &mut render_resources.buttons {
                button.handle_pointer_event(&mut render_resources.scene, context, &pointer_event);
            }
        }
        context.request_render();
        Ok(())
    }

    // This is to allow development of this feature on devices without consumer control buttons.
    #[cfg(feature = "http_setup_server")]
    fn handle_keyboard_event(
        &mut self,
        context: &mut ViewAssistantContext,
        event: &input::Event,
        keyboard_event: &input::keyboard::Event,
    ) -> Result<(), Error> {
        const HID_USAGE_KEY_LEFT_BRACKET: u32 = 47;
        const HID_USAGE_KEY_RIGHT_BRACKET: u32 = 48;

        fn keyboard_to_consumer_phase(
            phase: carnelian::input::keyboard::Phase,
        ) -> Option<carnelian::input::consumer_control::Phase> {
            match phase {
                carnelian::input::keyboard::Phase::Pressed => {
                    Some(carnelian::input::consumer_control::Phase::Down)
                }
                carnelian::input::keyboard::Phase::Released => {
                    Some(carnelian::input::consumer_control::Phase::Up)
                }
                _ => None,
            }
        }

        let synthetic_phase = keyboard_to_consumer_phase(keyboard_event.phase);

        let synthetic_event =
            synthetic_phase.and_then(|synthetic_phase| match keyboard_event.hid_usage {
                HID_USAGE_KEY_LEFT_BRACKET => Some(input::consumer_control::Event {
                    button: ConsumerControlButton::VolumeDown,
                    phase: synthetic_phase,
                }),
                HID_USAGE_KEY_RIGHT_BRACKET => Some(input::consumer_control::Event {
                    button: ConsumerControlButton::VolumeUp,
                    phase: synthetic_phase,
                }),
                _ => None,
            });

        if let Some(synthetic_event) = synthetic_event {
            self.handle_consumer_control_event(context, event, &synthetic_event)?;
        }

        Ok(())
    }
}

/// Connects to WiFi, returns a future that will wait for a connection
#[cfg(feature = "http_setup_server")]
async fn connect_to_wifi(ssid: String, password: String) -> Result<(), Error> {
    println!("Connecting to WiFi ");
    use fidl_fuchsia_wlan_policy::SecurityType;
    use recovery_util::wlan::{create_network_info, WifiConnect, WifiConnectImpl};
    let wifi = WifiConnectImpl::new();
    let network = create_network_info(&ssid, Some(&password), Some(SecurityType::Wpa2));
    wifi.connect(network).await
}

/// Determines whether or not fdr is enabled.
async fn check_fdr_enabled() -> Result<bool, Error> {
    let proxy = connect_to_protocol::<FactoryResetPolicyMarker>()?;
    proxy
        .get_enabled()
        .await
        .map_err(|e| format_err!("Could not get status of factory reset: {:?}", e))
}

/// Return the recovery body based on whether or not factory reset is restricted.
fn get_recovery_body(fdr_enabled: bool) -> Option<String> {
    if fdr_enabled {
        let instructions = std::fs::read_to_string(INSTRUCTIONS_TEXT_PATH)
            .unwrap_or(String::from("Press and hold both volume buttons to reset this device."));
        Some(instructions)
    } else {
        None
    }
}

fn make_app_assistant_fut(
    app_sender: &AppSender,
) -> LocalBoxFuture<'_, Result<AppAssistantPtr, Error>> {
    let f = async move {
        // Route stdout to debuglog, allowing log lines to appear over serial.
        stdout_to_debuglog::init().await.unwrap_or_else(|error| {
            eprintln!("Failed to initialize debuglog: {:?}", error);
        });

        #[cfg(feature = "http_setup_server")]
        if let Err(e) = regulatory::set_region_code_from_factory().await {
            eprintln!("error setting region code: {:?}", e);
        }

        // Build the fdr restriction depending on whether the fdr restriction config exists,
        // and if so, whether or not the policy api allows fdr.
        let fdr_restriction = {
            let has_restricted_fdr_config = Path::new(PATH_TO_FDR_RESTRICTION_CONFIG).exists();
            if has_restricted_fdr_config {
                let fdr_initially_enabled = check_fdr_enabled().await.unwrap_or_else(|error| {
                    eprintln!("Could not get fdr policy. Falling back to `true`: {:?}", error);
                    true
                });
                FdrRestriction::Restricted { fdr_initially_enabled }
            } else {
                FdrRestriction::NotRestricted
            }
        };

        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 => {
                eprintln!("Invalid display_rotation {}, defaulting to 0 degrees", val);
                DisplayRotation::Deg0
            }
        };

        let assistant = Box::new(RecoveryAppAssistant::new(
            app_sender,
            display_rotation,
            fdr_restriction,
            #[cfg(feature = "http_setup_server")]
            Arc::new(OtaComponent::new()?),
        ));

        Ok::<AppAssistantPtr, Error>(assistant)
    };
    Box::pin(f)
}

fn make_app_assistant() -> AssistantCreatorFunc {
    Box::new(make_app_assistant_fut)
}

fn main() -> Result<(), Error> {
    println!("recovery: started");
    // When UI code is moved and used this main.rs will disppear.
    #[cfg(feature = "ota_ui")]
    ui_v2::main()?;
    // This line always stays here otherwise we have use problems with code that is to be moved later.
    App::run(make_app_assistant())
}

#[cfg(test)]
mod tests {
    use super::{make_app_assistant, FdrRestriction, RecoveryAppAssistant};
    use carnelian::{drawing::DisplayRotation, App, AppAssistant, AppSender};
    use std::sync::Arc;

    #[ignore] //TODO(https://fxbug.dev/42053153) Move to integration test
    #[test]
    fn test_ui() -> std::result::Result<(), anyhow::Error> {
        let assistant = make_app_assistant();
        App::test(assistant)
    }

    #[fuchsia::test]
    fn test_recovery_app_assistant_sets_up_successfully() {
        let test_app_sender = AppSender::new_for_testing_purposes_only();
        let mut recovery_app_assistant = RecoveryAppAssistant::new(
            &test_app_sender,
            DisplayRotation::Deg0,
            FdrRestriction::NotRestricted,
            #[cfg(feature = "http_setup_server")]
            Arc::new(ota::FakeOtaManager::new()),
        );
        recovery_app_assistant.setup().unwrap();
    }

    #[cfg(feature = "http_setup_server")]
    mod ota {
        use super::*;
        use anyhow::Error;
        use async_trait::async_trait;
        use fidl::endpoints::DiscoverableProtocolMarker;
        use fidl_fuchsia_recovery_ui::{
            ProgressRendererMarker, ProgressRendererRender2Request, Status,
        };
        use fuchsia_async as fasync;
        use futures::lock::Mutex;
        use ota_lib::{OtaManager, OtaStatus};

        pub struct FakeOtaManager {
            pub status: Arc<Mutex<Option<ota_lib::OtaStatus>>>,
        }
        impl FakeOtaManager {
            pub fn new() -> Self {
                Self { status: Arc::new(Mutex::new(None)) }
            }
        }

        #[async_trait]
        impl OtaManager for FakeOtaManager {
            async fn start_and_wait_for_result(&self) -> Result<(), Error> {
                Ok(())
            }

            async fn stop(&self) -> Result<(), Error> {
                Ok(())
            }

            async fn complete_ota(&self, status: OtaStatus) {
                *self.status.lock().await = Some(status);
            }
        }

        #[fuchsia::test]
        async fn test_progress_updates_reports_success_to_ota_manager() {
            let test_app_sender = AppSender::new_for_testing_purposes_only();
            let (progress_proxy, progress_server) =
                fidl::endpoints::create_proxy::<ProgressRendererMarker>().unwrap();
            let ota_manager = Arc::new(FakeOtaManager::new());

            let mut recovery_app_assistant = RecoveryAppAssistant::new(
                &test_app_sender,
                DisplayRotation::Deg0,
                FdrRestriction::NotRestricted,
                ota_manager.clone(),
            );
            assert_eq!(
                vec![ProgressRendererMarker::PROTOCOL_NAME],
                recovery_app_assistant.outgoing_services_names()
            );
            recovery_app_assistant
                .handle_service_connection_request(
                    ProgressRendererMarker::PROTOCOL_NAME,
                    fasync::Channel::from_channel(progress_server.into_channel()),
                )
                .unwrap();

            progress_proxy
                .render2(&ProgressRendererRender2Request {
                    status: Some(Status::Active),
                    percent_complete: Some(0.0),
                    ..Default::default()
                })
                .await
                .unwrap();
            progress_proxy
                .render2(&ProgressRendererRender2Request {
                    status: Some(Status::Complete),
                    percent_complete: Some(100.0),
                    ..Default::default()
                })
                .await
                .unwrap();

            assert_eq!(Some(OtaStatus::Succeeded), *ota_manager.status.lock().await);
        }

        #[fuchsia::test]
        async fn test_progress_updates_reports_error_to_ota_manager() {
            let test_app_sender = AppSender::new_for_testing_purposes_only();
            let (progress_proxy, progress_server) =
                fidl::endpoints::create_proxy::<ProgressRendererMarker>().unwrap();
            let ota_manager = Arc::new(FakeOtaManager::new());

            let mut recovery_app_assistant = RecoveryAppAssistant::new(
                &test_app_sender,
                DisplayRotation::Deg0,
                FdrRestriction::NotRestricted,
                ota_manager.clone(),
            );
            assert_eq!(
                vec![ProgressRendererMarker::PROTOCOL_NAME],
                recovery_app_assistant.outgoing_services_names()
            );
            recovery_app_assistant
                .handle_service_connection_request(
                    ProgressRendererMarker::PROTOCOL_NAME,
                    fasync::Channel::from_channel(progress_server.into_channel()),
                )
                .unwrap();

            progress_proxy
                .render2(&ProgressRendererRender2Request {
                    status: Some(Status::Active),
                    percent_complete: Some(0.0),
                    ..Default::default()
                })
                .await
                .unwrap();
            progress_proxy
                .render2(&ProgressRendererRender2Request {
                    status: Some(Status::Error),
                    ..Default::default()
                })
                .await
                .unwrap();

            assert_eq!(Some(OtaStatus::Failed), *ota_manager.status.lock().await);
        }
    }
}
