// 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};
use argh::FromArgs;
use carnelian::{
    color::Color,
    drawing::{load_font, path_for_circle, DisplayRotation, FontFace},
    facet::{
        RasterFacet, Scene, SceneBuilder, ShedFacet, TextFacetOptions, TextHorizontalAlignment,
        TextVerticalAlignment,
    },
    input, make_message,
    render::{BlendMode, Context as RenderContext, Fill, FillRule, Raster, Style},
    App, AppAssistant, AppAssistantPtr, AppContext, AssistantCreatorFunc, Coord, LocalBoxFuture,
    Point, Size, ViewAssistant, ViewAssistantContext, ViewAssistantPtr, ViewKey,
};
use euclid::{point2, size2};
use fidl_fuchsia_input_report::ConsumerControlButton;
use fidl_fuchsia_recovery::FactoryResetMarker;
use fidl_fuchsia_recovery_policy::FactoryResetMarker as FactoryResetPolicyMarker;
use fuchsia_async::{self as fasync, Task};
use fuchsia_component::client::connect_to_service;
use fuchsia_zircon::{Duration, Event};
use futures::StreamExt;
use std::borrow::{Borrow, Cow};
use std::path::{Path, PathBuf};

const FACTORY_RESET_TIMER_IN_SECONDS: u8 = 10;
const LOGO_IMAGE_PATH: &str = "/pkg/data/logo.shed";
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 setup;

#[cfg(feature = "http_setup_server")]
mod ota;

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

#[cfg(feature = "http_setup_server")]
mod storage;

mod fdr;
use fdr::{FactoryResetState, ResetEvent};

fn display_rotation_from_str(s: &str) -> Result<DisplayRotation, String> {
    match s {
        "0" => Ok(DisplayRotation::Deg0),
        "90" => Ok(DisplayRotation::Deg90),
        "180" => Ok(DisplayRotation::Deg180),
        "270" => Ok(DisplayRotation::Deg270),
        _ => Err(format!("Invalid DisplayRotation {}", s)),
    }
}

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()
}

/// FDR
#[derive(Debug, FromArgs)]
#[argh(name = "recovery")]
struct Args {
    /// rotate
    #[argh(option, from_str_fn(display_rotation_from_str))]
    rotation: Option<DisplayRotation>,
}

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 RECOVERY_MODE_BODY: &'static str = "Press and hold both volume keys to factory reset.";

const COUNTDOWN_MODE_HEADLINE: &'static str = "Factory reset device";
const COUNTDOWN_MODE_BODY: &'static str = "Continue 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_context: AppContext,
    display_rotation: DisplayRotation,
    fdr_restriction: FdrRestriction,
}

impl RecoveryAppAssistant {
    pub fn new(app_context: &AppContext, fdr_restriction: FdrRestriction) -> Self {
        let args: Args = argh::from_env();

        Self {
            app_context: app_context.clone(),
            display_rotation: args.rotation.unwrap_or(DisplayRotation::Deg0),
            fdr_restriction,
        }
    }
}

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

    fn create_view_assistant(&mut self, view_key: ViewKey) -> Result<ViewAssistantPtr, Error> {
        let body = get_recovery_body(self.fdr_restriction.is_initially_enabled());
        Ok(Box::new(RecoveryViewAssistant::new(
            &self.app_context,
            view_key,
            RECOVERY_MODE_HEADLINE,
            body.map(Into::into),
            self.fdr_restriction,
        )?))
    }

    fn get_display_rotation(&self) -> DisplayRotation {
        self.display_rotation
    }
}

struct RenderResources {
    scene: Scene,
}

impl RenderResources {
    fn new(
        render_context: &mut RenderContext,
        target_size: Size,
        heading: &str,
        body: Option<&str>,
        countdown_ticks: u8,
        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 top_margin = 0.255;

        let body_text_size = min_dimension / 18.0;
        let countdown_text_size = min_dimension / 6.0;

        let mut builder = SceneBuilder::new(BG_COLOR);

        let logo_size: Size = size2(logo_edge, logo_edge);
        // Calculate position for centering the logo image
        let logo_position = {
            let x = target_size.width / 2.0;
            let y = top_margin * target_size.height + logo_edge / 2.0;
            point2(x, y)
        };

        if is_counting_down {
            let circle = raster_for_circle(logo_position, 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,
                },
                Point::zero(),
            );

            builder.text(
                face.clone(),
                &format!("{:02}", countdown_ticks),
                countdown_text_size,
                logo_position,
                TextFacetOptions {
                    horizontal_alignment: TextHorizontalAlignment::Center,
                    vertical_alignment: TextVerticalAlignment::Center,
                    color: Color::white(),
                    ..TextFacetOptions::default()
                },
            );
            let _ = builder.facet(Box::new(circle_facet));
        } else {
            let shed_facet =
                ShedFacet::new(PathBuf::from(LOGO_IMAGE_PATH), logo_position, logo_size);
            builder.facet(Box::new(shed_facet));
        }

        let heading_text_location =
            point2(target_size.width / 2.0, logo_position.y + logo_size.height / 2.0 + text_size);
        builder.text(
            face.clone(),
            &heading,
            text_size,
            heading_text_location,
            TextFacetOptions {
                horizontal_alignment: TextHorizontalAlignment::Center,
                color: HEADING_COLOR,
                ..TextFacetOptions::default()
            },
        );

        if let Some(body) = body {
            let margin = 0.23;
            let body_x = target_size.width * margin;
            let wrap_width = target_size.width - 2.0 * body_x;
            builder.text(
                face.clone(),
                &body,
                body_text_size,
                point2(body_x, heading_text_location.y + text_size),
                TextFacetOptions {
                    horizontal_alignment: TextHorizontalAlignment::Left,
                    color: BODY_COLOR,
                    max_width: Some(wrap_width),
                    ..TextFacetOptions::default()
                },
            );
        }

        Self { scene: builder.build() }
    }
}

struct RecoveryViewAssistant {
    face: FontFace,
    heading: String,
    body: Option<Cow<'static, str>>,
    fdr_restriction: FdrRestriction,
    reset_state_machine: fdr::FactoryResetStateMachine,
    app_context: AppContext,
    view_key: ViewKey,
    countdown_task: Option<Task<()>>,
    countdown_ticks: u8,
    render_resources: Option<RenderResources>,
}

impl RecoveryViewAssistant {
    fn new(
        app_context: &AppContext,
        view_key: ViewKey,
        heading: &str,
        body: Option<Cow<'static, str>>,
        fdr_restriction: FdrRestriction,
    ) -> Result<RecoveryViewAssistant, Error> {
        RecoveryViewAssistant::setup(app_context, view_key)?;

        let face = load_font(PathBuf::from("/pkg/data/fonts/Roboto-Regular.ttf"))?;

        Ok(RecoveryViewAssistant {
            face,
            heading: heading.to_string(),
            body,
            fdr_restriction,
            reset_state_machine: fdr::FactoryResetStateMachine::new(),
            app_context: app_context.clone(),
            view_key: 0,
            countdown_task: None,
            countdown_ticks: FACTORY_RESET_TIMER_IN_SECONDS,
            render_resources: None,
        })
    }

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

    #[cfg(feature = "http_setup_server")]
    fn setup(app_context: &AppContext, view_key: ViewKey) -> Result<(), Error> {
        let mut receiver = setup::start_server()?;
        let local_app_context = app_context.clone();
        let f = async move {
            while let Some(event) = receiver.next().await {
                println!("recovery: received request");
                match event {
                    SetupEvent::Root => local_app_context
                        .queue_message(view_key, make_message(RecoveryMessages::EventReceived)),
                    SetupEvent::DevhostOta { cfg } => {
                        local_app_context
                            .queue_message(view_key, make_message(RecoveryMessages::StartingOta));
                        let result = ota::run_devhost_ota(cfg).await;
                        local_app_context.queue_message(
                            view_key,
                            make_message(RecoveryMessages::OtaFinished { result }),
                        );
                    }
                }
            }
        };

        fasync::Task::local(f).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_context: AppContext,
        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_context.queue_message(
            view_key,
            make_message(RecoveryMessages::PolicyResult(check_id, fdr_enabled)),
        );
    }

    async fn execute_reset(view_key: ViewKey, app_context: AppContext) {
        let factory_reset_service = connect_to_service::<FactoryResetMarker>();
        let proxy = match factory_reset_service {
            Ok(marker) => marker.clone(),
            Err(error) => {
                app_context.queue_message(view_key, make_message(RecoveryMessages::ResetFailed));
                panic!("Could not connect to factory_reset_service: {}", error);
            }
        };

        println!("recovery: Executing factory reset command");

        let res = proxy.reset().await;
        match res {
            Ok(_) => {}
            Err(error) => {
                app_context.queue_message(view_key, make_message(RecoveryMessages::ResetFailed));
                eprintln!("recovery: Error occurred : {}", error);
            }
        };
    }
}

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,
                target_size,
                &self.heading,
                self.body.as_ref().map(Borrow::borrow),
                self.countdown_ticks,
                &self.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>() {
            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());
                }
                #[cfg(feature = "http_setup_server")]
                RecoveryMessages::OtaFinished { result } => {
                    if let Err(e) = result {
                        self.body = Some(format!("OTA failed: {:?}", e).into());
                    } else {
                        self.body = Some("OTA succeeded".into());
                    }
                }
                RecoveryMessages::PolicyResult(check_id, fdr_enabled) => {
                    let state = self
                        .reset_state_machine
                        .handle_event(ResetEvent::AwaitPolicyResult(*check_id, *fdr_enabled));
                    self.app_context.queue_message(
                        self.view_key,
                        make_message(RecoveryMessages::ResetMessage(state)),
                    );
                }
                RecoveryMessages::ResetMessage(state) => {
                    match state {
                        FactoryResetState::Waiting => {
                            self.heading = RECOVERY_MODE_HEADLINE.to_string();
                            self.body =
                                get_recovery_body(self.fdr_restriction.is_initially_enabled())
                                    .map(Into::into);
                            self.render_resources = None;
                            self.app_context.request_render(self.view_key);
                        }
                        FactoryResetState::AwaitingPolicy(_) => {} // no-op
                        FactoryResetState::StartCountdown => {
                            let view_key = self.view_key;
                            let local_app_context = self.app_context.clone();

                            let mut counter = FACTORY_RESET_TIMER_IN_SECONDS;
                            local_app_context.queue_message(
                                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_context.queue_message(
                                        view_key,
                                        make_message(RecoveryMessages::CountdownTick(counter)),
                                    );
                                    if counter == 0 {
                                        break;
                                    }
                                }
                            };
                            self.countdown_task = Some(fasync::Task::local(f));
                        }
                        FactoryResetState::CancelCountdown => {
                            self.countdown_task
                                .take()
                                .and_then(|task| Some(fasync::Task::local(task.cancel())));
                            let state = self
                                .reset_state_machine
                                .handle_event(ResetEvent::CountdownCancelled);
                            assert_eq!(state, fdr::FactoryResetState::Waiting);
                            self.app_context.queue_message(
                                self.view_key,
                                make_message(RecoveryMessages::ResetMessage(state)),
                            );
                        }
                        FactoryResetState::ExecuteReset => {
                            let view_key = self.view_key;
                            let local_app_context = self.app_context.clone();
                            let f = async move {
                                RecoveryViewAssistant::execute_reset(view_key, local_app_context)
                                    .await;
                            };
                            fasync::Task::local(f).detach();
                        }
                    };
                }
                RecoveryMessages::CountdownTick(count) => {
                    self.heading = COUNTDOWN_MODE_HEADLINE.to_string();
                    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_context.queue_message(
                            self.view_key,
                            make_message(RecoveryMessages::ResetMessage(state)),
                        );
                    } else {
                        self.body = Some(COUNTDOWN_MODE_BODY.into());
                    }
                    self.render_resources = None;
                    self.app_context.request_render(self.view_key);
                }
                RecoveryMessages::ResetFailed => {
                    self.heading = "Reset failed".to_string();
                    self.body = Some("Please restart device to try again".into());
                    self.render_resources = None;
                    self.app_context.request_render(self.view_key);
                }
            }
        }
    }

    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_context.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(())
    }

    // This is to allow development of this feature on devices without consumer control buttons.
    fn handle_keyboard_event(
        &mut self,
        context: &mut ViewAssistantContext,
        event: &input::Event,
        keyboard_event: &input::keyboard::Event,
    ) -> Result<(), Error> {
        const HID_USAGE_KEY_F11: u32 = 0x44;
        const HID_USAGE_KEY_F12: u32 = 0x45;

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

        let synthetic_event = match keyboard_event.hid_usage {
            HID_USAGE_KEY_F11 => Some(input::consumer_control::Event {
                button: ConsumerControlButton::VolumeDown,
                phase: keyboard_to_consumer_phase(keyboard_event.phase),
            }),
            HID_USAGE_KEY_F12 => Some(input::consumer_control::Event {
                button: ConsumerControlButton::VolumeUp,
                phase: keyboard_to_consumer_phase(keyboard_event.phase),
            }),
            _ => None,
        };

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

        Ok(())
    }
}

/// Determines whether or not fdr is enabled.
async fn check_fdr_enabled() -> Result<bool, Error> {
    let proxy = connect_to_service::<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.
const fn get_recovery_body(fdr_enabled: bool) -> Option<&'static str> {
    if fdr_enabled {
        Some(RECOVERY_MODE_BODY)
    } else {
        None
    }
}

fn make_app_assistant_fut(
    app_context: &AppContext,
) -> LocalBoxFuture<'_, Result<AppAssistantPtr, Error>> {
    let f = async move {
        // 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 assistant = Box::new(RecoveryAppAssistant::new(app_context, fdr_restriction));
        Ok::<AppAssistantPtr, Error>(assistant)
    };
    Box::pin(f)
}

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

fn main() -> Result<(), Error> {
    println!("recovery: started");
    App::run(make_app_assistant())
}

#[cfg(test)]
mod tests {
    use super::make_app_assistant;
    use carnelian::App;

    #[test]
    fn test_ui() -> std::result::Result<(), anyhow::Error> {
        let assistant = make_app_assistant();
        App::test(assistant)
    }
}
