// Copyright 2021 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 {
    crate::consumer_controls_binding::ConsumerControlsEvent,
    crate::input_device,
    crate::input_handler::UnhandledInputHandler,
    anyhow::{anyhow, Context as _, Error},
    async_trait::async_trait,
    async_utils::hanging_get::server::HangingGet,
    fidl_fuchsia_input_report as fidl_input_report, fidl_fuchsia_io as fio,
    fidl_fuchsia_media::AudioRenderUsage,
    fidl_fuchsia_media_sounds::PlayerMarker,
    fidl_fuchsia_recovery::FactoryResetMarker,
    fidl_fuchsia_recovery_policy::{DeviceRequest, DeviceRequestStream},
    fidl_fuchsia_recovery_ui::{
        FactoryResetCountdownRequestStream, FactoryResetCountdownState,
        FactoryResetCountdownWatchResponder,
    },
    fuchsia_async::{Duration, Task, Time, Timer},
    fuchsia_component,
    fuchsia_zircon::Channel,
    futures::StreamExt,
    std::{
        cell::RefCell,
        fs::{self, File},
        path::Path,
        rc::Rc,
    },
};

/// FactoryResetState tracks the state of the device through the factory reset
/// process.
///
/// # Values
/// ## Disallowed
/// Factory reset of the device is not allowed. This is used to
/// keep public devices from being reset, such as when being used in kiosk mode.
///
/// ### Transitions
/// Disallowed → Idle
///
/// ## Idle
/// This is the default state for a device when factory resets are allowed but
/// is not currently being reset.
///
/// ### Transitions
/// Idle → Disallowed
/// Idle → ButtonCountdown
///
/// ## ButtonCountdown
/// This state represents the fact that the reset button has been pressed and a
/// countdown has started to verify that the button was pressed intentionally.
///
/// ### Transitions
/// ButtonCountdown → Disallowed
/// ButtonCountdown → Idle
/// ButtonCountdown → ResetCountdown
///
/// ## ResetCountdown
/// The button countdown has completed indicating that this was a purposeful
/// action so a reset countdown is started to give the user a chance to cancel
/// the factory reset.
///
/// ### Transitions
/// ResetCountdown → Disallowed
/// ResetCountdown → Idle
/// ResetCountdown → Resetting
///
/// ## Resetting
/// Once the device is in this state a factory reset is imminent and can no
/// longer be cancelled.
#[derive(Clone, Copy, Debug, PartialEq)]
enum FactoryResetState {
    Disallowed,
    Idle,
    ButtonCountdown { deadline: Time },
    ResetCountdown { deadline: Time },
    Resetting,
}

const FACTORY_RESET_DISALLOWED_PATH: &'static str = "/data/factory_reset_disallowed";
const FACTORY_RESET_SOUND_PATH: &'static str = "/config/data/chirp-start-tone.wav";

const BUTTON_TIMEOUT: Duration = Duration::from_millis(500);
const RESET_TIMEOUT: Duration = Duration::from_seconds(10);

type NotifyFn = Box<dyn Fn(&FactoryResetState, FactoryResetCountdownWatchResponder) -> bool + Send>;
type ResetCountdownHangingGet =
    HangingGet<FactoryResetState, FactoryResetCountdownWatchResponder, NotifyFn>;

/// A [`FactoryResetHandler`] tracks the state of the consumer control buttons
/// and starts the factory reset process after appropriate timeouts.
pub struct FactoryResetHandler {
    factory_reset_state: RefCell<FactoryResetState>,
    countdown_hanging_get: RefCell<ResetCountdownHangingGet>,
}

/// Uses the `ConsumerControlsEvent` to determine whether the device should
/// start the Factory Reset process. The driver will turn special button
/// combinations into a `FactoryReset` signal so this code only needs to
/// listen for that.
fn is_reset_requested(event: &ConsumerControlsEvent) -> bool {
    event.pressed_buttons.iter().any(|button| match button {
        fidl_input_report::ConsumerControlButton::FactoryReset => true,
        _ => false,
    })
}

impl FactoryResetHandler {
    /// Creates a new [`FactoryResetHandler`] that listens for the reset button
    /// and handles timing down and, ultimately, factory resetting the device.
    pub fn new() -> Rc<Self> {
        let initial_state = if Path::new(FACTORY_RESET_DISALLOWED_PATH).exists() {
            FactoryResetState::Disallowed
        } else {
            FactoryResetState::Idle
        };

        let countdown_hanging_get = FactoryResetHandler::init_hanging_get(initial_state);

        Rc::new(Self {
            factory_reset_state: RefCell::new(initial_state),
            countdown_hanging_get: RefCell::new(countdown_hanging_get),
        })
    }

    /// Handles the request stream for FactoryResetCountdown
    ///
    /// # Parameters
    /// `stream`: The `FactoryResetCountdownRequestStream` to be handled.
    pub fn handle_factory_reset_countdown_request_stream(
        self: Rc<Self>,
        mut stream: FactoryResetCountdownRequestStream,
    ) -> impl futures::Future<Output = Result<(), Error>> {
        let subscriber = self.countdown_hanging_get.borrow_mut().new_subscriber();

        async move {
            while let Some(request_result) = stream.next().await {
                let watcher = request_result?
                    .into_watch()
                    .ok_or(anyhow!("Failed to get FactoryResetCoundown Watcher"))?;
                subscriber.register(watcher)?;
            }

            Ok(())
        }
    }

    /// Handles the request stream for fuchsia.recovery.policy.Device
    ///
    /// # Parameters
    /// `stream`: The `DeviceRequestStream` to be handled.
    pub fn handle_recovery_policy_device_request_stream(
        self: Rc<Self>,
        mut stream: DeviceRequestStream,
    ) -> impl futures::Future<Output = Result<(), Error>> {
        async move {
            while let Some(request_result) = stream.next().await {
                let DeviceRequest::SetIsLocalResetAllowed { allowed, .. } = request_result?;
                match self.factory_reset_state() {
                    FactoryResetState::Disallowed if allowed => {
                        // Update state and delete file
                        self.set_factory_reset_state(FactoryResetState::Idle);
                        fs::remove_file(FACTORY_RESET_DISALLOWED_PATH).map_err(|error| {
                            anyhow!("Failed to SetIsLocalResetAllowed to true: {:?}", error)
                        })?;
                    }
                    _ if !allowed => {
                        // Update state and create file
                        self.set_factory_reset_state(FactoryResetState::Disallowed);
                        File::create(FACTORY_RESET_DISALLOWED_PATH).map_err(|error| {
                            anyhow!("Failed to SetIsLocalResetAllowed to false: {:?}", error)
                        })?;
                    }
                    _ => (),
                }
            }

            Ok(())
        }
    }

    /// Handles `ConsumerControlEvent`s when the device is in the
    /// `FactoryResetState::Idle` state
    async fn handle_allowed_event(self: &Rc<Self>, event: &ConsumerControlsEvent) {
        if is_reset_requested(event) {
            if let Err(error) = self.start_button_countdown().await {
                tracing::error!("Failed to factory reset device: {:?}", error);
            }
        }
    }

    /// Handles `ConsumerControlEvent`s when the device is in the
    /// `FactoryResetState::Disallowed` state
    fn handle_disallowed_event(self: &Rc<Self>, event: &ConsumerControlsEvent) {
        if is_reset_requested(event) {
            tracing::error!("Attempted to factory reset a device that is not allowed to reset");
        }
    }

    /// Handles `ConsumerControlEvent`s when the device is in the
    /// `FactoryResetState::ButtonCountdown` state
    fn handle_button_countdown_event(self: &Rc<Self>, event: &ConsumerControlsEvent) {
        if !is_reset_requested(event) {
            // Cancel button timeout
            self.set_factory_reset_state(FactoryResetState::Idle);
        }
    }

    /// Handles `ConsumerControlEvent`s when the device is in the
    /// `FactoryResetState::ResetCountdown` state
    fn handle_reset_countdown_event(self: &Rc<Self>, event: &ConsumerControlsEvent) {
        if !is_reset_requested(event) {
            // Cancel reset timeout
            self.set_factory_reset_state(FactoryResetState::Idle);
        }
    }

    fn init_hanging_get(initial_state: FactoryResetState) -> ResetCountdownHangingGet {
        let notify_fn: NotifyFn = Box::new(|state, responder| {
            let deadline = match state {
                FactoryResetState::ResetCountdown { deadline } => {
                    Some(deadline.into_nanos() as i64)
                }
                _ => None,
            };

            let countdown_state = FactoryResetCountdownState {
                scheduled_reset_time: deadline,
                ..FactoryResetCountdownState::EMPTY
            };

            if responder.send(countdown_state).is_err() {
                tracing::error!("Failed to send factory reset countdown state");
            }

            true
        });

        ResetCountdownHangingGet::new(initial_state, notify_fn)
    }

    /// Sets the state of FactoryResetHandler and notifies watchers of the updated state.
    fn set_factory_reset_state(self: &Rc<Self>, state: FactoryResetState) {
        *self.factory_reset_state.borrow_mut() = state;
        self.countdown_hanging_get.borrow_mut().new_publisher().set(state);
    }

    fn factory_reset_state(self: &Rc<Self>) -> FactoryResetState {
        *self.factory_reset_state.borrow()
    }

    /// Handles waiting for the reset button to be held down long enough to start
    /// the factory reset countdown.
    async fn start_button_countdown(self: &Rc<Self>) -> Result<(), Error> {
        let deadline = Time::after(BUTTON_TIMEOUT);
        self.set_factory_reset_state(FactoryResetState::ButtonCountdown { deadline });

        // Wait for button timeout
        Timer::new(Time::after(BUTTON_TIMEOUT)).await;

        // Make sure the buttons are still held
        match self.factory_reset_state() {
            FactoryResetState::ButtonCountdown { deadline: state_deadline }
                if state_deadline == deadline =>
            {
                // Proceed with reset.
                self.start_reset_countdown().await?;
            }
            _ => {
                tracing::info!("Factory reset request cancelled");
            }
        }

        Ok(())
    }

    /// Handles waiting for the reset countdown to complete before resetting the
    /// device.
    async fn start_reset_countdown(self: &Rc<Self>) -> Result<(), Error> {
        let deadline = Time::after(RESET_TIMEOUT);
        self.set_factory_reset_state(FactoryResetState::ResetCountdown { deadline });

        // Wait for reset timeout
        Timer::new(Time::after(RESET_TIMEOUT)).await;

        // Make sure the buttons are still held
        match self.factory_reset_state() {
            FactoryResetState::ResetCountdown { deadline: state_deadline }
                if state_deadline == deadline =>
            {
                // Proceed with reset.
                self.reset().await?;
            }
            _ => {
                tracing::info!("Factory reset request cancelled");
            }
        }

        Ok(())
    }

    /// Retrieves and plays the sound associated with factory resetting the device.
    async fn play_reset_sound(self: &Rc<Self>) -> Result<(), Error> {
        // Get sound
        let sound_file = File::open(FACTORY_RESET_SOUND_PATH)
            .context("Failed to open factory reset sound file")?;
        let sound_channel = Channel::from(fdio::transfer_fd(sound_file)?);
        let sound_endpoint = fidl::endpoints::ClientEnd::<fio::FileMarker>::new(sound_channel);

        // Play sound
        let sound_player = fuchsia_component::client::connect_to_protocol::<PlayerMarker>()?;

        let sound_id = 0;
        let _duration = sound_player
            .add_sound_from_file(sound_id, sound_endpoint)
            .await?
            .map_err(|status| anyhow::format_err!("AddSoundFromFile failed {}", status))?;

        sound_player
            .play_sound(sound_id, AudioRenderUsage::Media)
            .await?
            .map_err(|err| anyhow::format_err!("PlaySound failed: {:?}", err))?;

        Ok(())
    }

    /// Performs the actual factory reset.
    async fn reset(self: &Rc<Self>) -> Result<(), Error> {
        if let Err(error) = self.play_reset_sound().await {
            tracing::info!("Failed to play reset sound: {:?}", error);
        }

        // Trigger reset
        self.set_factory_reset_state(FactoryResetState::Resetting);
        tracing::info!("Triggering factory reset");
        let factory_reset = fuchsia_component::client::connect_to_protocol::<FactoryResetMarker>()?;
        factory_reset.reset().await?;
        Ok(())
    }
}

#[async_trait(?Send)]
impl UnhandledInputHandler for FactoryResetHandler {
    /// This InputHandler doesn't consume any input events. It just passes them on to the next handler in the pipeline.
    /// Since it doesn't need exclusive access to the events this seems like the best way to avoid handlers further
    /// down the pipeline missing events that they need.
    async fn handle_unhandled_input_event(
        self: Rc<Self>,
        unhandled_input_event: input_device::UnhandledInputEvent,
    ) -> Vec<input_device::InputEvent> {
        match unhandled_input_event {
            input_device::UnhandledInputEvent {
                device_event: input_device::InputDeviceEvent::ConsumerControls(ref event),
                device_descriptor: input_device::InputDeviceDescriptor::ConsumerControls(_),
                event_time: _,
                trace_id: _,
            } => {
                match self.factory_reset_state() {
                    FactoryResetState::Idle => {
                        let event_clone = event.clone();
                        Task::local(async move { self.handle_allowed_event(&event_clone).await })
                            .detach()
                    }
                    FactoryResetState::Disallowed => self.handle_disallowed_event(event),
                    FactoryResetState::ButtonCountdown { deadline: _ } => {
                        self.handle_button_countdown_event(event)
                    }
                    FactoryResetState::ResetCountdown { deadline: _ } => {
                        self.handle_reset_countdown_event(event)
                    }
                    FactoryResetState::Resetting => {
                        tracing::warn!("Recieved an input event while factory resetting the device")
                    }
                };
            }
            _ => (),
        };

        vec![input_device::InputEvent::from(unhandled_input_event)]
    }
}

#[cfg(test)]
mod tests {
    use {
        super::*,
        crate::consumer_controls_binding::ConsumerControlsDeviceDescriptor,
        assert_matches::assert_matches,
        fidl::endpoints::create_proxy_and_stream,
        fidl_fuchsia_recovery_policy::{DeviceMarker, DeviceProxy},
        fidl_fuchsia_recovery_ui::{FactoryResetCountdownMarker, FactoryResetCountdownProxy},
        fuchsia_async::TestExecutor,
        fuchsia_zircon as zx,
        pin_utils::pin_mut,
        pretty_assertions::assert_eq,
        std::task::Poll,
    };

    fn create_factory_reset_countdown_proxy(
        reset_handler: Rc<FactoryResetHandler>,
    ) -> FactoryResetCountdownProxy {
        let (countdown_proxy, countdown_stream) =
            create_proxy_and_stream::<FactoryResetCountdownMarker>()
                .expect("Failed to create countdown proxy");

        let stream_fut =
            reset_handler.clone().handle_factory_reset_countdown_request_stream(countdown_stream);

        Task::local(async move {
            if stream_fut.await.is_err() {
                tracing::warn!("Failed to handle factory reset countdown request stream");
            }
        })
        .detach();

        countdown_proxy
    }

    fn create_recovery_policy_proxy(reset_handler: Rc<FactoryResetHandler>) -> DeviceProxy {
        let (device_proxy, device_stream) = create_proxy_and_stream::<DeviceMarker>()
            .expect("Failed to create recovery policy device proxy");

        Task::local(async move {
            if reset_handler
                .handle_recovery_policy_device_request_stream(device_stream)
                .await
                .is_err()
            {
                tracing::warn!("Failed to handle recovery policy device request stream");
            }
        })
        .detach();

        device_proxy
    }

    fn create_input_device_descriptor() -> input_device::InputDeviceDescriptor {
        input_device::InputDeviceDescriptor::ConsumerControls(ConsumerControlsDeviceDescriptor {
            buttons: vec![
                fidl_input_report::ConsumerControlButton::CameraDisable,
                fidl_input_report::ConsumerControlButton::FactoryReset,
                fidl_input_report::ConsumerControlButton::MicMute,
                fidl_input_report::ConsumerControlButton::Pause,
                fidl_input_report::ConsumerControlButton::VolumeDown,
                fidl_input_report::ConsumerControlButton::VolumeUp,
            ],
        })
    }

    fn create_reset_consumer_controls_event() -> ConsumerControlsEvent {
        ConsumerControlsEvent::new(vec![fidl_input_report::ConsumerControlButton::FactoryReset])
    }

    fn create_non_reset_consumer_controls_event() -> ConsumerControlsEvent {
        ConsumerControlsEvent::new(vec![
            fidl_input_report::ConsumerControlButton::CameraDisable,
            fidl_input_report::ConsumerControlButton::MicMute,
            fidl_input_report::ConsumerControlButton::Pause,
            fidl_input_report::ConsumerControlButton::VolumeDown,
            fidl_input_report::ConsumerControlButton::VolumeUp,
        ])
    }

    fn create_non_reset_input_event() -> input_device::UnhandledInputEvent {
        let device_event = input_device::InputDeviceEvent::ConsumerControls(
            create_non_reset_consumer_controls_event(),
        );

        input_device::UnhandledInputEvent {
            device_event,
            device_descriptor: create_input_device_descriptor(),
            event_time: zx::Time::get_monotonic(),
            trace_id: None,
        }
    }

    fn create_reset_input_event() -> input_device::UnhandledInputEvent {
        let device_event = input_device::InputDeviceEvent::ConsumerControls(
            create_reset_consumer_controls_event(),
        );

        input_device::UnhandledInputEvent {
            device_event,
            device_descriptor: create_input_device_descriptor(),
            event_time: zx::Time::get_monotonic(),
            trace_id: None,
        }
    }

    fn get_countdown_state(
        proxy: &FactoryResetCountdownProxy,
        executor: &mut TestExecutor,
    ) -> FactoryResetCountdownState {
        let countdown_proxy_clone = proxy.clone();
        let countdown_state_fut = async move {
            countdown_proxy_clone.watch().await.expect("Failed to get countdown state")
        };
        pin_mut!(countdown_state_fut);

        match executor.run_until_stalled(&mut countdown_state_fut) {
            Poll::Ready(countdown_state) => countdown_state,
            _ => panic!("Failed to get countdown state"),
        }
    }

    #[fuchsia::test]
    async fn is_reset_requested_looks_for_reset_signal() {
        let reset_event = create_reset_consumer_controls_event();
        let non_reset_event = create_non_reset_consumer_controls_event();

        assert!(
            is_reset_requested(&reset_event),
            "Should reset when the reset signal is received."
        );
        assert!(
            !is_reset_requested(&non_reset_event),
            "Should only reset when the reset signal is received."
        );
    }

    #[fuchsia::test]
    async fn factory_reset_countdown_listener_gets_initial_state() {
        let reset_handler = FactoryResetHandler::new();
        let countdown_proxy = create_factory_reset_countdown_proxy(reset_handler.clone());
        let reset_state = countdown_proxy.watch().await.expect("Failed to get countdown state");
        assert!(reset_state.scheduled_reset_time.is_none());
        assert_eq!(reset_handler.factory_reset_state(), FactoryResetState::Idle);
    }

    #[fuchsia::test]
    fn factory_reset_countdown_listener_is_notified_on_state_change() -> Result<(), Error> {
        let mut executor = TestExecutor::new_with_fake_time().unwrap();
        let reset_handler = FactoryResetHandler::new();
        let countdown_proxy = create_factory_reset_countdown_proxy(reset_handler.clone());

        // The initial state should be no scheduled reset time and the
        // FactoryRestHandler state should be FactoryResetState::Idle
        let countdown_state = get_countdown_state(&countdown_proxy, &mut executor);
        let handler_state = reset_handler.factory_reset_state();
        assert!(countdown_state.scheduled_reset_time.is_none());
        assert_eq!(handler_state, FactoryResetState::Idle);

        // Send a reset event
        let reset_event = create_reset_input_event();
        let handle_input_event_fut =
            reset_handler.clone().handle_unhandled_input_event(reset_event);
        pin_mut!(handle_input_event_fut);
        assert!(executor.run_until_stalled(&mut handle_input_event_fut).is_ready());

        // The next state will be FactoryResetState::ButtonCountdown with no scheduled reset
        let countdown_state = get_countdown_state(&countdown_proxy, &mut executor);
        let handler_state = reset_handler.factory_reset_state();
        assert!(countdown_state.scheduled_reset_time.is_none());
        assert_matches!(handler_state, FactoryResetState::ButtonCountdown { deadline: _ });

        // Skip ahead 500ms for the ButtonCountdown
        executor.set_fake_time(Time::after(Duration::from_millis(500)));
        executor.wake_expired_timers();

        // After the ButtonCountdown the reset_handler enters the
        // FactoryResetState::ResetCountdown state WITH a scheduled reset time.
        let countdown_state = get_countdown_state(&countdown_proxy, &mut executor);
        let handler_state = reset_handler.factory_reset_state();
        assert!(countdown_state.scheduled_reset_time.is_some());
        assert_matches!(handler_state, FactoryResetState::ResetCountdown { deadline: _ });

        // Skip ahead 10s for the ResetCountdown
        executor.set_fake_time(Time::after(Duration::from_seconds(10)));
        executor.wake_expired_timers();

        // After the ResetCountdown the reset_handler enters the
        // FactoryResetState::Resetting state with no scheduled reset time.
        let countdown_state = get_countdown_state(&countdown_proxy, &mut executor);
        let handler_state = reset_handler.factory_reset_state();
        assert!(countdown_state.scheduled_reset_time.is_none());
        assert_eq!(handler_state, FactoryResetState::Resetting);

        Ok(())
    }

    #[fuchsia::test]
    async fn recovery_policy_requests_update_reset_handler_state() {
        let reset_handler = FactoryResetHandler::new();
        let countdown_proxy = create_factory_reset_countdown_proxy(reset_handler.clone());

        // Initial state should be FactoryResetState::Idle with no scheduled reset
        let reset_state = countdown_proxy.watch().await.expect("Failed to get countdown state");
        assert!(reset_state.scheduled_reset_time.is_none());
        assert_eq!(reset_handler.factory_reset_state(), FactoryResetState::Idle);

        // Set FactoryResetState to Disallow
        let device_proxy = create_recovery_policy_proxy(reset_handler.clone());
        device_proxy.set_is_local_reset_allowed(false).expect("Failed to set recovery policy");

        // State should now be in Disallow and scheduled_reset_time should be None
        let reset_state = countdown_proxy.watch().await.expect("Failed to get countdown state");
        assert!(reset_state.scheduled_reset_time.is_none());
        assert_eq!(reset_handler.factory_reset_state(), FactoryResetState::Disallowed);

        // Send reset event
        let reset_event = create_reset_input_event();
        reset_handler.clone().handle_unhandled_input_event(reset_event).await;

        // State should still be Disallow
        assert_eq!(reset_handler.factory_reset_state(), FactoryResetState::Disallowed);

        // Set the state back to Allow
        let device_proxy = create_recovery_policy_proxy(reset_handler.clone());
        device_proxy.set_is_local_reset_allowed(true).expect("Failed to set recovery policy");

        // State should be FactoryResetState::Idle with no scheduled reset
        let reset_state = countdown_proxy.watch().await.expect("Failed to get countdown state");
        assert!(reset_state.scheduled_reset_time.is_none());
        assert_eq!(reset_handler.factory_reset_state(), FactoryResetState::Idle);
    }

    #[fuchsia::test]
    fn handle_allowed_event_changes_state_with_reset() {
        let mut executor = TestExecutor::new().unwrap();

        let reset_event = create_reset_consumer_controls_event();
        let reset_handler = FactoryResetHandler::new();
        let countdown_proxy = create_factory_reset_countdown_proxy(reset_handler.clone());

        // Initial state should be FactoryResetState::Idle with no scheduled reset
        let reset_state = executor.run_singlethreaded(async {
            countdown_proxy.watch().await.expect("Failed to get countdown state")
        });
        assert!(reset_state.scheduled_reset_time.is_none());
        assert_eq!(reset_handler.factory_reset_state(), FactoryResetState::Idle);

        let reset_handler_clone = reset_handler.clone();
        let handle_allowed_event_fut = reset_handler_clone.handle_allowed_event(&reset_event);
        futures::pin_mut!(handle_allowed_event_fut);
        let _ = executor.run_until_stalled(&mut handle_allowed_event_fut);

        let watch_res = executor.run_singlethreaded(countdown_proxy.watch());
        // This should result in the reset handler entering the ButtonCountdown state
        assert!(watch_res.is_ok());
        assert!(watch_res.unwrap().scheduled_reset_time.is_none());
        assert_matches!(
            reset_handler.factory_reset_state(),
            FactoryResetState::ButtonCountdown { deadline: _ }
        );
    }

    #[fuchsia::test]
    async fn handle_allowed_event_wont_change_state_without_reset() {
        let reset_handler = FactoryResetHandler::new();
        let countdown_proxy = create_factory_reset_countdown_proxy(reset_handler.clone());

        // Initial state should be FactoryResetState::Idle with no scheduled reset
        let reset_state = countdown_proxy.watch().await.expect("Failed to get countdown state");
        assert!(reset_state.scheduled_reset_time.is_none());
        assert_eq!(reset_handler.factory_reset_state(), FactoryResetState::Idle);

        let non_reset_event = create_non_reset_consumer_controls_event();
        reset_handler.clone().handle_allowed_event(&non_reset_event).await;

        // This should result in the reset handler staying in the Allowed state
        assert_eq!(reset_handler.factory_reset_state(), FactoryResetState::Idle);
    }

    #[fuchsia::test]
    async fn handle_disallowed_event_wont_change_state() {
        let reset_handler = FactoryResetHandler::new();
        *reset_handler.factory_reset_state.borrow_mut() = FactoryResetState::Disallowed;

        // Calling handle_disallowed_event shouldn't change the state no matter
        // what the contents of the event are
        let reset_event = create_reset_consumer_controls_event();
        reset_handler.handle_disallowed_event(&reset_event);
        assert_eq!(reset_handler.factory_reset_state(), FactoryResetState::Disallowed);

        let non_reset_event = create_non_reset_consumer_controls_event();
        reset_handler.handle_disallowed_event(&non_reset_event);
        assert_eq!(reset_handler.factory_reset_state(), FactoryResetState::Disallowed);
    }

    #[fuchsia::test]
    async fn handle_button_countdown_event_changes_state_when_reset_no_longer_requested() {
        let reset_handler = FactoryResetHandler::new();

        let deadline = Time::after(BUTTON_TIMEOUT);
        *reset_handler.factory_reset_state.borrow_mut() =
            FactoryResetState::ButtonCountdown { deadline };

        // Calling handle_button_countdown_event should reset the handler
        // to the idle state
        let non_reset_event = create_non_reset_consumer_controls_event();
        reset_handler.handle_button_countdown_event(&non_reset_event);
        assert_eq!(reset_handler.factory_reset_state(), FactoryResetState::Idle);
    }

    #[fuchsia::test]
    async fn handle_reset_countdown_event_changes_state_when_reset_no_longer_requested() {
        let reset_handler = FactoryResetHandler::new();

        *reset_handler.factory_reset_state.borrow_mut() =
            FactoryResetState::ResetCountdown { deadline: Time::now() };

        // Calling handle_reset_countdown_event should reset the handler
        // to the idle state
        let non_reset_event = create_non_reset_consumer_controls_event();
        reset_handler.handle_reset_countdown_event(&non_reset_event);
        assert_eq!(reset_handler.factory_reset_state(), FactoryResetState::Idle);
    }

    #[fuchsia::test]
    async fn factory_reset_disallowed_during_button_countdown() {
        let reset_handler = FactoryResetHandler::new();
        let countdown_proxy = create_factory_reset_countdown_proxy(reset_handler.clone());

        // Initial state should be FactoryResetState::Idle with no scheduled reset
        let reset_state = countdown_proxy.watch().await.expect("Failed to get countdown state");
        assert!(reset_state.scheduled_reset_time.is_none());
        assert_eq!(reset_handler.factory_reset_state(), FactoryResetState::Idle);

        // Send reset event
        let reset_event = create_reset_input_event();
        reset_handler.clone().handle_unhandled_input_event(reset_event).await;

        // State should now be ButtonCountdown and scheduled_reset_time should be None
        let reset_state = countdown_proxy.watch().await.expect("Failed to get countdown state");
        assert!(reset_state.scheduled_reset_time.is_none());
        assert_matches!(
            reset_handler.factory_reset_state(),
            FactoryResetState::ButtonCountdown { deadline: _ }
        );

        // Set FactoryResetState to Disallow
        let device_proxy = create_recovery_policy_proxy(reset_handler.clone());
        device_proxy.set_is_local_reset_allowed(false).expect("Failed to set recovery policy");

        // State should now be in Disallow and scheduled_reset_time should be None
        let reset_state = countdown_proxy.watch().await.expect("Failed to get countdown state");
        assert!(reset_state.scheduled_reset_time.is_none());
        assert_eq!(reset_handler.factory_reset_state(), FactoryResetState::Disallowed);
    }

    #[fuchsia::test]
    async fn factory_reset_disallowed_during_reset_countdown() {
        let reset_handler = FactoryResetHandler::new();
        let countdown_proxy = create_factory_reset_countdown_proxy(reset_handler.clone());

        // Initial state should be FactoryResetState::Idle with no scheduled reset
        let reset_state = countdown_proxy.watch().await.expect("Failed to get countdown state");
        assert!(reset_state.scheduled_reset_time.is_none());
        assert_eq!(reset_handler.factory_reset_state(), FactoryResetState::Idle);

        // Send reset event
        let reset_event = create_reset_input_event();
        reset_handler.clone().handle_unhandled_input_event(reset_event).await;

        // State should now be ButtonCountdown and scheduled_reset_time should be None
        let reset_state = countdown_proxy.watch().await.expect("Failed to get countdown state");
        assert!(reset_state.scheduled_reset_time.is_none());
        assert_matches!(
            reset_handler.factory_reset_state(),
            FactoryResetState::ButtonCountdown { deadline: _ }
        );

        // State should now be ResetCountdown and scheduled_reset_time should be Some
        let reset_state = countdown_proxy.watch().await.expect("Failed to get countdown state");
        assert!(reset_state.scheduled_reset_time.is_some());
        assert_matches!(
            reset_handler.factory_reset_state(),
            FactoryResetState::ResetCountdown { deadline: _ }
        );

        // Set FactoryResetState to Disallow
        let device_proxy = create_recovery_policy_proxy(reset_handler.clone());
        device_proxy.set_is_local_reset_allowed(false).expect("Failed to set recovery policy");

        // State should now be in Disallow and scheduled_reset_time should be None
        let reset_state = countdown_proxy.watch().await.expect("Failed to get countdown state");
        assert!(reset_state.scheduled_reset_time.is_none());
        assert_eq!(reset_handler.factory_reset_state(), FactoryResetState::Disallowed);
    }

    #[fuchsia::test]
    async fn factory_reset_cancelled_during_button_countdown() {
        let reset_handler = FactoryResetHandler::new();
        let countdown_proxy = create_factory_reset_countdown_proxy(reset_handler.clone());

        // Initial state should be FactoryResetState::Idle with no scheduled reset
        let reset_state = countdown_proxy.watch().await.expect("Failed to get countdown state");
        assert!(reset_state.scheduled_reset_time.is_none());
        assert_eq!(reset_handler.factory_reset_state(), FactoryResetState::Idle);

        // Send reset event
        let reset_event = create_reset_input_event();
        reset_handler.clone().handle_unhandled_input_event(reset_event).await;

        // State should now be ButtonCountdown and scheduled_reset_time should be None
        let reset_state = countdown_proxy.watch().await.expect("Failed to get countdown state");
        assert!(reset_state.scheduled_reset_time.is_none());
        assert_matches!(
            reset_handler.factory_reset_state(),
            FactoryResetState::ButtonCountdown { deadline: _ }
        );

        // Pass in an event to simulate releasing the reset button
        let non_reset_event = create_non_reset_input_event();
        reset_handler.clone().handle_unhandled_input_event(non_reset_event).await;

        // State should now be in Idle and scheduled_reset_time should be None
        let reset_state = countdown_proxy.watch().await.expect("Failed to get countdown state");
        assert!(reset_state.scheduled_reset_time.is_none());
        assert_eq!(reset_handler.factory_reset_state(), FactoryResetState::Idle);
    }

    #[fuchsia::test]
    async fn factory_reset_cancelled_during_reset_countdown() {
        let reset_handler = FactoryResetHandler::new();
        let countdown_proxy = create_factory_reset_countdown_proxy(reset_handler.clone());

        // Initial state should be FactoryResetState::Idle with no scheduled reset
        let reset_state = countdown_proxy.watch().await.expect("Failed to get countdown state");
        assert!(reset_state.scheduled_reset_time.is_none());
        assert_eq!(reset_handler.factory_reset_state(), FactoryResetState::Idle);

        // Send reset event
        let reset_event = create_reset_input_event();
        reset_handler.clone().handle_unhandled_input_event(reset_event).await;

        // State should now be ButtonCountdown and scheduled_reset_time should be None
        let reset_state = countdown_proxy.watch().await.expect("Failed to get countdown state");
        assert!(reset_state.scheduled_reset_time.is_none());
        assert_matches!(
            reset_handler.factory_reset_state(),
            FactoryResetState::ButtonCountdown { deadline: _ }
        );

        // State should now be ResetCountdown and scheduled_reset_time should be Some
        let reset_state = countdown_proxy.watch().await.expect("Failed to get countdown state");
        assert!(reset_state.scheduled_reset_time.is_some());
        assert_matches!(
            reset_handler.factory_reset_state(),
            FactoryResetState::ResetCountdown { deadline: _ }
        );

        // Pass in an event to simulate releasing the reset button
        let non_reset_event = create_non_reset_input_event();
        reset_handler.clone().handle_unhandled_input_event(non_reset_event).await;

        // State should now be in Idle and scheduled_reset_time should be None
        let reset_state = countdown_proxy.watch().await.expect("Failed to get countdown state");
        assert!(reset_state.scheduled_reset_time.is_none());
        assert_eq!(reset_handler.factory_reset_state(), FactoryResetState::Idle);
    }
}
