// Copyright 2019 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::{Context as _, Error};
use async_trait::async_trait;
use derivative::Derivative;
use fidl::endpoints::ProtocolMarker;
use fidl_fuchsia_hardware_backlight::{
    DeviceMarker as BacklightMarker, DeviceProxy as BacklightProxy, State as BacklightCommand,
};
use fidl_fuchsia_ui_display_internal::{DisplayPowerMarker, DisplayPowerProxy};
use fuchsia_async as fasync;
use fuchsia_component::client::connect_to_protocol;
use fuchsia_zircon as zx;
use futures::{channel::oneshot, lock::Mutex};
use std::sync::Arc;

/// The minimum brightness value that can be sent to the backlight service.
const MIN_REGULATED_BRIGHTNESS: f64 = 0.0004;
/// The maximum brightness that can be sent to the backlight service.
const MAX_REGULATED_BRIGHTNESS: f64 = 1.0;

fn open_backlight() -> Result<BacklightProxy, Error> {
    tracing::info!("Opening backlight");
    let (proxy, server) = fidl::endpoints::create_proxy::<BacklightMarker>()
        .context("Failed to create backlight proxy")?;
    // TODO(kpt): Don't hardcode this path b/138666351
    fdio::service_connect("/dev/class/backlight/000", server.into_channel())
        .context("Failed to connect built-in service")?;
    Ok(proxy)
}

fn open_display_power_service() -> Result<DisplayPowerProxy, Error> {
    tracing::info!("Opening display controller");
    connect_to_protocol::<DisplayPowerMarker>()
        .context("Failed to connect to display power service")
}

/// Possible combinations of backlight and display power states.
///
/// When powering down, the backlight must always be turned off with a delay before the DDIC is
/// turned off.
///
/// When powering up, the DDIC must always be turned on with a delay before the backlight is turned
/// on.
#[derive(Derivative)]
#[derivative(Debug)]
enum PowerState {
    /// This state should only be used as a temporary placeholder while swapping values inside
    /// containers (e.g. Mutex).
    Indeterminate,
    BothOn,
    /// The backlight is off and the DDIC is scheduled to turn off.
    BacklightOffDisplayPoweringDown(#[derivative(Debug = "ignore")] fasync::Task<()>),
    BothOff,
    /// The DDIC is on and the backlight is scheduled to turn on. A sequence of backlight changes
    /// may be queued.
    DisplayOnBacklightPoweringUp(
        #[derivative(Debug = "ignore")] fasync::Task<()>,
        Vec<PendingBacklightCommand>,
    ),
}

impl Default for PowerState {
    fn default() -> Self {
        Self::Indeterminate
    }
}

/// A backlight command that is queued to be invoked after the power on delay elapses.
#[derive(Debug)]
struct PendingBacklightCommand {
    command: BacklightCommand,
    /// Will be resolved when the command is invoked (or cancelled if the command is dropped due to
    /// a state change).
    future_handle: oneshot::Sender<Result<(), Error>>,
}

#[derive(Debug, Clone)]
pub struct Backlight {
    backlight_proxy: BacklightProxy,
    display_power: Option<DisplayPower>,
}

impl Backlight {
    /// Creates a simple `Backlight` control, for devices on which DDIC power cannot be switched
    /// off and on.
    pub fn without_display_power() -> Result<Self, Error> {
        let backlight_proxy = open_backlight()?;
        Self::without_display_power_internal(backlight_proxy)
    }

    fn without_display_power_internal(backlight_proxy: BacklightProxy) -> Result<Self, Error> {
        Ok(Backlight { backlight_proxy, display_power: None })
    }

    /// Creates a `Backlight` control that manages both the backlight brightness/power and the power
    /// state of the DDIC.
    #[allow(unused)]
    pub async fn with_display_power(
        power_off_delay_millis: u16,
        power_on_delay_millis: u16,
    ) -> Result<Self, Error> {
        let backlight_proxy = open_backlight()?;
        let display_power_proxy = open_display_power_service()?;
        Self::with_display_power_internal(
            backlight_proxy,
            display_power_proxy,
            zx::Duration::from_millis(power_off_delay_millis as i64),
            zx::Duration::from_millis(power_on_delay_millis as i64),
        )
        .await
    }

    async fn with_display_power_internal(
        backlight_proxy: BacklightProxy,
        display_power_proxy: DisplayPowerProxy,
        power_off_delay: impl Into<zx::Duration>,
        power_on_delay: impl Into<zx::Duration>,
    ) -> Result<Self, Error> {
        let display_power = DisplayPower::new(
            &backlight_proxy,
            display_power_proxy,
            power_off_delay,
            power_on_delay,
        )
        .await?;
        Ok(Backlight { backlight_proxy, display_power: Some(display_power) })
    }

    pub async fn get_max_absolute_brightness(&self) -> Result<f64, Error> {
        let connection = self
            .backlight_proxy
            .get_max_absolute_brightness()
            .await
            .context("Didn't connect correctly")?;
        let max_brightness: f64 = connection
            .map_err(zx::Status::from_raw)
            .context("Failed to get_max_absolute_brightness")?;
        Ok(max_brightness)
    }

    async fn get(&self) -> Result<f64, Error> {
        let backlight_info = get_state_normalized(&self.backlight_proxy).await?;
        assert!(backlight_info.brightness >= 0.0);
        assert!(backlight_info.brightness <= MAX_REGULATED_BRIGHTNESS);
        Ok(if backlight_info.backlight_on { backlight_info.brightness } else { 0.0 })
    }

    async fn set(&self, value: f64) -> Result<(), Error> {
        // TODO(https://fxbug.dev/42111816): Handle error here as well, similar to get_brightness above. Might involve
        let regulated_value =
            num_traits::clamp(value, MIN_REGULATED_BRIGHTNESS, MAX_REGULATED_BRIGHTNESS);
        let backlight_on = value > 0.0;

        match self.display_power.as_ref() {
            None => self.set_backlight_state_normalized(regulated_value, backlight_on).await,
            Some(display_power) => {
                self.clone().set_dual_state(display_power, regulated_value, backlight_on).await
            }
        }
    }

    async fn set_dual_state(
        &self,
        display_power: &DisplayPower,
        regulated_value: f64,
        backlight_on: bool,
    ) -> Result<(), Error> {
        let power_state_arc = display_power.power_state.clone();
        // Note that `power_state` MUST be `drop()`ped before yielding an async value, or there will
        // be a deadlock. Rewriting this `match` expression to not use `.await`, and hence to be
        // able to drop the guard implicitly when it goes out of scope, would be too messy.
        let mut power_state = power_state_arc.lock().await;
        match &mut *power_state {
            PowerState::BothOn => {
                if backlight_on {
                    // See below
                } else {
                    self.set_backlight_state_normalized(regulated_value, backlight_on).await?;
                    tracing::info!("Turned backlight off");
                    tracing::info!("DDIC power off scheduled");
                    let task =
                        self.clone().make_scheduled_updates_task(display_power.power_off_delay);
                    *power_state = PowerState::BacklightOffDisplayPoweringDown(task);
                }
                drop(power_state);
                self.set_backlight_state_normalized(regulated_value, backlight_on).await
            }
            PowerState::BacklightOffDisplayPoweringDown(_task) => {
                if backlight_on {
                    tracing::info!("DDIC power on cancelled");
                    // Cancel the scheduled display shutdown.
                    *power_state = PowerState::BothOn;
                    drop(power_state);
                    self.set_backlight_state_normalized(regulated_value, backlight_on).await
                } else {
                    // No-op. Already scheduled to turn off.
                    drop(power_state);
                    Ok(())
                }
            }
            PowerState::BothOff => {
                if backlight_on {
                    display_power.set_display_power_and_log_errors(true).await?;
                    let (pending_change, receiver) =
                        Self::make_pending_change(regulated_value, backlight_on);
                    let task =
                        self.clone().make_scheduled_updates_task(display_power.power_on_delay);
                    *power_state =
                        PowerState::DisplayOnBacklightPoweringUp(task, vec![pending_change]);
                    drop(power_state);
                    tracing::info!("Backlight power on scheduled");
                    receiver.await?
                } else {
                    // No-op. Already off.
                    drop(power_state);
                    Ok(())
                }
            }
            PowerState::DisplayOnBacklightPoweringUp(_task, ref mut pending_changes) => {
                if backlight_on {
                    let (pending_change, receiver) =
                        Self::make_pending_change(regulated_value, backlight_on);
                    pending_changes.push(pending_change);
                    drop(power_state);
                    receiver.await?
                } else {
                    tracing::info!("Backlight power on cancelled");
                    // Cancel scheduled backlight power on.
                    *power_state = PowerState::BothOff;
                    drop(power_state);
                    Ok(())
                }
            }
            PowerState::Indeterminate => {
                unreachable!()
            }
        }
    }

    fn make_scheduled_updates_task(&self, delay: zx::Duration) -> fasync::Task<()> {
        let time = fasync::Time::after(delay);
        tracing::trace!("Setting timer for {:?}", &time);
        let timer = fasync::Timer::new(time);
        let self_ = self.clone();
        let fut = async move {
            tracing::trace!("Awaiting timer");
            timer.await;
            tracing::trace!("Timer {:?} elapsed", time);
            self_.process_scheduled_updates().await;
        };
        fasync::Task::local(fut)
    }

    /// Creates a pending command that can be queued in a
    /// [`PowerState::DisplayOnBacklightPoweringUp`] state.
    fn make_pending_change(
        regulated_value: f64,
        backlight_on: bool,
    ) -> (PendingBacklightCommand, oneshot::Receiver<Result<(), Error>>) {
        let (sender, receiver) = oneshot::channel::<Result<(), Error>>();
        let pending_change = PendingBacklightCommand {
            command: BacklightCommand { backlight_on, brightness: regulated_value },
            future_handle: sender,
        };
        (pending_change, receiver)
    }

    /// Process scheduled updates to the power state.
    async fn process_scheduled_updates(&self) {
        let self_ = self.clone();
        match &self.display_power {
            Some(display_power) => {
                let power_state_arc = display_power.power_state.clone();
                let mut power_state_guard = power_state_arc.lock().await;
                let power_state = std::mem::take(&mut *power_state_guard);

                tracing::debug!(
                    "Processing scheduled updates after timer. Most recent state: {:?}",
                    &power_state
                );

                match power_state {
                    PowerState::BacklightOffDisplayPoweringDown(_) => {
                        if let Ok(_) = display_power.set_display_power_and_log_errors(false).await {
                            *power_state_guard = PowerState::BothOff;
                        } else {
                            // Don't get stuck in an indeterminate state, nor start a retry loop.
                            // Subsequent calls changes to the backlight state should work normally.
                            *power_state_guard = PowerState::BothOn;
                        }
                    }
                    PowerState::DisplayOnBacklightPoweringUp(_, pending_changes) => {
                        assert!(!pending_changes.is_empty());
                        let mut turned_on = false;
                        for pending_change in pending_changes.into_iter() {
                            assert!(pending_change.command.backlight_on);
                            let result = self_
                                .set_backlight_state_normalized(
                                    pending_change.command.brightness,
                                    pending_change.command.backlight_on,
                                )
                                .await;
                            // Even if a backlight command fails for some reason, we need to treat
                            // the backlight as on. Subsequent commands should still work.
                            *power_state_guard = PowerState::BothOn;
                            tracing::debug!(
                                "Sending result for pending change {:?}",
                                &pending_change
                            );
                            if let Err(e) = pending_change.future_handle.send(result) {
                                tracing::warn!(
                                    "Failed to send result for pending change: {:#?}",
                                    e
                                );
                            } else if !turned_on {
                                turned_on = true;
                                tracing::info!("Turned backlight on");
                            }
                        }
                    }
                    PowerState::Indeterminate => {
                        unreachable!()
                    }
                    _ => {}
                }
            }
            None => {
                unreachable!()
            }
        }
    }

    async fn set_backlight_state_normalized(
        &self,
        regulated_value: f64,
        backlight_on: bool,
    ) -> Result<(), Error> {
        tracing::debug!(
            "set_state_normalized(brightness: {:.3}, backlight_on: {}",
            regulated_value,
            backlight_on
        );
        self.backlight_proxy
            .set_state_normalized(&BacklightCommand { backlight_on, brightness: regulated_value })
            .await?
            .map_err(|e| zx::Status::from_raw(e))
            .context("Failed to set backlight state")
    }
}

/// Wrapper around [`DisplayPowerProxy`], with state management and configuration values.
#[derive(Debug, Clone)]
struct DisplayPower {
    proxy: DisplayPowerProxy,
    power_state: Arc<Mutex<PowerState>>,
    power_off_delay: zx::Duration,
    power_on_delay: zx::Duration,
}

impl DisplayPower {
    async fn new(
        backlight_proxy: &BacklightProxy,
        display_power_proxy: DisplayPowerProxy,
        power_off_delay: impl Into<zx::Duration>,
        power_on_delay: impl Into<zx::Duration>,
    ) -> Result<Self, Error> {
        // There is no direct way to retrieve the power state of the DDIC, so we infer it from the
        // backlight's state on startup.
        let initial_state = if get_state_normalized(&backlight_proxy).await?.backlight_on {
            PowerState::BothOn
        } else {
            PowerState::BothOff
        };
        tracing::info!("Initial power state: {:?}", &initial_state);

        Ok(DisplayPower {
            proxy: display_power_proxy,
            power_state: Arc::new(Mutex::new(initial_state)),
            power_off_delay: power_off_delay.into(),
            power_on_delay: power_on_delay.into(),
        })
    }

    async fn set_display_power_and_log_errors(&self, display_on: bool) -> Result<(), Error> {
        let on_off = if display_on { "on" } else { "off" };
        tracing::info!("Turning DDIC power {}", on_off);
        self.proxy
            .set_display_power(display_on)
            .await
            .map_err(|fidl_error| Into::<Error>::into(fidl_error))
            .with_context(|| format!("Failed to connect to {}", DisplayPowerMarker::DEBUG_NAME))
            .and_then(|inner| {
                inner.map_err(|e| {
                    let status = zx::Status::from_raw(e);
                    Error::from(status)
                })
            })
            .with_context(|| format!("Failed to turn {on_off} display"))
            .map_err(|e| {
                tracing::error!("{:#?}", &e);
                e
            })?;
        tracing::info!("Turned DDIC power {}", on_off);
        Ok(())
    }
}

async fn get_state_normalized(backlight_proxy: &BacklightProxy) -> Result<BacklightCommand, Error> {
    backlight_proxy
        .get_state_normalized()
        .await?
        .map_err(|e| zx::Status::from_raw(e))
        .context("Failed to get_state_normalized")
}

#[async_trait]
pub trait BacklightControl: std::fmt::Debug + Send + Sync {
    async fn get_brightness(&self) -> Result<f64, Error>;
    async fn set_brightness(&self, value: f64) -> Result<(), Error>;
    async fn get_max_absolute_brightness(&self) -> Result<f64, Error>;
}

#[async_trait]
impl BacklightControl for Backlight {
    async fn get_brightness(&self) -> Result<f64, Error> {
        self.get().await
    }
    async fn set_brightness(&self, value: f64) -> Result<(), Error> {
        self.clone().set(value).await
    }
    async fn get_max_absolute_brightness(&self) -> Result<f64, Error> {
        self.get_max_absolute_brightness().await
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use fidl::endpoints::create_proxy_and_stream;
    use fidl_fuchsia_hardware_backlight::DeviceRequestStream as BacklightRequestStream;
    use fuchsia_async::{self as fasync};
    use futures::{join, prelude::future};
    use futures_util::stream::StreamExt;

    fn mock_backlight() -> (Arc<Backlight>, BacklightRequestStream) {
        let (backlight_proxy, backlight_stream) =
            create_proxy_and_stream::<BacklightMarker>().unwrap();

        (
            Arc::new(Backlight::without_display_power_internal(backlight_proxy).unwrap()),
            backlight_stream,
        )
    }

    async fn mock_device_set(mut reqs: BacklightRequestStream) -> BacklightCommand {
        match reqs.next().await.unwrap() {
            Ok(fidl_fuchsia_hardware_backlight::DeviceRequest::SetStateNormalized {
                state: command,
                ..
            }) => {
                return command;
            }
            request => panic!("Unexpected request: {:?}", request),
        }
    }

    async fn mock_device_get(
        mut reqs: BacklightRequestStream,
        backlight_command: BacklightCommand,
    ) {
        match reqs.next().await.unwrap() {
            Ok(fidl_fuchsia_hardware_backlight::DeviceRequest::GetStateNormalized {
                responder,
            }) => {
                let response = backlight_command;
                let _ = responder.send(Ok(&response));
            }
            Ok(fidl_fuchsia_hardware_backlight::DeviceRequest::GetMaxAbsoluteBrightness {
                responder,
            }) => {
                if let Err(e) = responder.send(Ok(250.0)) {
                    panic!("Failed to reply to GetMaxAbsoluteBrightness: {}", e);
                }
            }
            request => panic!("Unexpected request: {:?}", request),
        }
    }

    #[fasync::run_singlethreaded(test)]
    async fn test_brightness_returns_zero_if_backlight_off() {
        // Setup
        let (mock, backlight_stream) = mock_backlight();
        let backlight_fut = mock_device_get(
            backlight_stream,
            BacklightCommand { backlight_on: false, brightness: 0.04 },
        );

        // Act
        let get_fut = mock.get();
        let (brightness, _) = future::join(get_fut, backlight_fut).await;

        // Assert
        assert_eq!(brightness.unwrap(), 0.0);
    }

    #[fasync::run_singlethreaded(test)]
    async fn test_brightness_returns_non_zero_if_backlight_on() {
        // Setup
        let (mock, backlight_stream) = mock_backlight();
        let backlight_fut = mock_device_get(
            backlight_stream,
            BacklightCommand { backlight_on: true, brightness: 0.04 },
        );

        // Act
        let get_fut = mock.get();
        let (brightness, _) = future::join(get_fut, backlight_fut).await;

        // Assert
        assert_eq!(brightness.unwrap(), 0.04);
    }

    #[fasync::run_singlethreaded(test)]
    async fn test_zero_brightness_turns_backlight_off() {
        // Setup
        let (mock, backlight_stream) = mock_backlight();
        let backlight_fut = mock_device_set(backlight_stream);

        // Act
        let set_fut = mock.set(0.0);
        let (_, backlight_command) = futures::join!(set_fut, backlight_fut);

        // Assert
        assert_eq!(backlight_command.backlight_on, false);
    }

    #[fasync::run_singlethreaded(test)]
    async fn test_negative_brightness_turns_backlight_off() {
        // Setup
        let (mock, backlight_stream) = mock_backlight();
        let backlight_fut = mock_device_set(backlight_stream);

        // Act
        let set_fut = mock.set(-0.01);
        let (_, backlight_command) = join!(set_fut, backlight_fut);

        // Assert
        assert_eq!(backlight_command.backlight_on, false);
    }

    #[fasync::run_singlethreaded(test)]
    async fn test_brightness_turns_backlight_on() {
        // Setup
        let (mock, backlight_stream) = mock_backlight();
        let backlight_fut = mock_device_set(backlight_stream);

        // Act
        let set_fut = mock.set(0.55);
        let (_, backlight_command) = join!(set_fut, backlight_fut);

        // Assert
        assert_eq!(backlight_command.backlight_on, true);
        assert_eq!(backlight_command.brightness, 0.55);
    }

    #[fasync::run_singlethreaded(test)]
    async fn test_get_max_absolute_brightness() {
        // Setup
        let (mock, backlight_stream) = mock_backlight();
        let backlight_fut = mock_device_get(
            backlight_stream,
            BacklightCommand { backlight_on: false, brightness: 0.04 },
        );

        // Act
        let mock_fut = mock.get_max_absolute_brightness();
        let (max_brightness, _) = future::join(mock_fut, backlight_fut).await;

        // Assert
        assert_eq!(max_brightness.unwrap(), 250.0);
    }
}

#[cfg(test)]
mod dual_state_tests {
    use super::*;
    use assert_matches::assert_matches;
    use fidl::endpoints::create_proxy_and_stream;
    use fidl_fuchsia_hardware_backlight::DeviceRequestStream as BacklightRequestStream;
    use fidl_fuchsia_ui_display_internal::{DisplayPowerRequest, DisplayPowerRequestStream};
    use fuchsia_async::{self as fasync, Task};
    use futures::{prelude::future, Future, TryStreamExt};
    use std::task::Poll;
    use test_helpers::ResettableFuture;

    #[derive(Debug, Clone)]
    struct FakeBacklightService {
        get_state_normalized_response: ResettableFuture<Result<BacklightCommand, i32>>,
        set_state_normalized_response: Arc<Mutex<Result<(), i32>>>,
    }

    #[allow(dead_code)]
    impl FakeBacklightService {
        pub fn new() -> Self {
            Self {
                get_state_normalized_response: ResettableFuture::new(),
                set_state_normalized_response: Arc::new(Mutex::new(Ok(()))),
            }
        }

        pub fn start(&self) -> Result<(BacklightProxy, Task<()>), Error> {
            let (proxy, stream) = create_proxy_and_stream::<BacklightMarker>()?;
            let task = Task::local(self.clone().process_requests(stream));
            Ok((proxy, task))
        }

        async fn process_requests(self, mut stream: BacklightRequestStream) {
            use fidl_fuchsia_hardware_backlight::DeviceRequest::*;

            tracing::debug!("FakeBacklightService::process_requests");
            while let Ok(Some(req)) = stream.try_next().await {
                tracing::debug!("FakeBacklightService: {}", req.method_name());
                match req {
                    GetStateNormalized { responder } => {
                        let result = self.get_state_normalized_response.get().await;
                        responder
                            .send(result.as_ref().map_err(|e| *e))
                            .expect("send GetStateNormalized");
                    }
                    SetStateNormalized { state, responder } => {
                        let result = self.set_state_normalized_response.lock().await.clone();
                        if result.is_ok() {
                            self.set_get_state_normalized_response(Ok(state)).await;
                        }
                        responder.send(result).expect("send SetStateNormalized");
                    }
                    _ => {
                        unimplemented!();
                    }
                };
            }
        }

        pub async fn set_get_state_normalized_response(
            &self,
            response: Result<BacklightCommand, i32>,
        ) {
            self.get_state_normalized_response.set(response).await;
        }

        pub async fn clear_get_state_normalized_response(&self) {
            self.get_state_normalized_response.clear().await;
        }

        pub async fn set_set_state_normalized_response(&self, result: Result<(), i32>) {
            let mut guard = self.set_state_normalized_response.lock().await;
            *guard = result;
        }
    }

    #[derive(Debug, Clone)]
    struct FakeDisplayPowerService {
        set_display_power_response: Arc<Mutex<Result<(), i32>>>,
        last_set_display_power_value: Arc<Mutex<Option<bool>>>,
    }

    #[allow(dead_code)]
    impl FakeDisplayPowerService {
        pub fn new() -> Self {
            Self {
                set_display_power_response: Arc::new(Mutex::new(Ok(()))),
                last_set_display_power_value: Arc::new(Mutex::new(None)),
            }
        }

        pub fn start(&self) -> Result<(DisplayPowerProxy, Task<()>), Error> {
            let (proxy, stream) = create_proxy_and_stream::<DisplayPowerMarker>()?;
            let task = Task::local(self.clone().process_requests(stream));
            Ok((proxy, task))
        }

        async fn process_requests(self, mut stream: DisplayPowerRequestStream) {
            tracing::debug!("FakeDisplayPowerService::process_requests");
            while let Ok(Some(req)) = stream.try_next().await {
                tracing::debug!("FakeDisplayPowerService: {}", req.method_name());
                match req {
                    DisplayPowerRequest::SetDisplayPower { power_on, responder } => {
                        let result = self.set_display_power_response.lock().await.clone();
                        if result.is_ok() {
                            self.last_set_display_power_value.lock().await.replace(power_on);
                        }
                        responder.send(result).expect("send SetDisplayPower");
                    }
                };
            }
            tracing::warn!("FakeDisplayPowerService stopped");
        }

        pub async fn set_set_display_power_response(&self, response: Result<(), i32>) {
            (*self.set_display_power_response.lock().await) = response;
        }

        pub async fn last_set_display_power_value(&self) -> Option<bool> {
            self.last_set_display_power_value.lock().await.clone()
        }
    }

    trait PollExt<T> {
        fn into_option(self) -> Option<T>;
        #[allow(dead_code)]
        fn unwrap(self) -> T;
    }

    impl<T> PollExt<T> for Poll<T> {
        fn into_option(self) -> Option<T> {
            match self {
                Poll::Ready(x) => Some(x),
                Poll::Pending => None,
            }
        }

        fn unwrap(self) -> T {
            self.into_option().unwrap()
        }
    }

    trait TestExecutorExt {
        fn pin_and_run_until_stalled<F: Future>(&mut self, main_future: F) -> Option<F::Output>;
        /// Wakes expired timers and runs any existing spawned tasks until they stall. Returns
        /// `true` if one or more timers were awoken.
        fn wake_timers_and_run_until_stalled(&mut self) -> bool;
    }

    impl TestExecutorExt for fasync::TestExecutor {
        fn pin_and_run_until_stalled<F: Future>(&mut self, main_future: F) -> Option<F::Output> {
            self.run_until_stalled(&mut Box::pin(main_future)).into_option()
        }

        fn wake_timers_and_run_until_stalled(&mut self) -> bool {
            let did_wake_timers = self.wake_expired_timers();
            let _ = self.run_until_stalled(&mut future::pending::<()>());
            did_wake_timers
        }
    }

    #[allow(dead_code)]
    struct Handles {
        fake_backlight_service: FakeBacklightService,
        backlight_proxy: BacklightProxy,
        backlight_task: Task<()>,

        fake_display_power_service: FakeDisplayPowerService,
        display_power_proxy: DisplayPowerProxy,
        display_power_task: Task<()>,

        backlight: Backlight,
    }

    impl Handles {
        /// Note that callers need to declare a variable for the executor _before_ the handles, or
        /// else the executor will cause a panic when it's dropped before its futures.
        fn new(
            power_off_delay_ms: i64,
            power_on_delay_ms: i64,
            initial_backlight_state: BacklightCommand,
        ) -> (fasync::TestExecutor, Handles) {
            let mut exec = fasync::TestExecutor::new_with_fake_time();
            exec.set_fake_time(zx::Time::ZERO.into());

            let fake_backlight_service = FakeBacklightService::new();
            let (backlight_proxy, backlight_task) = fake_backlight_service.start().unwrap();

            let fake_display_power_service = FakeDisplayPowerService::new();
            let (display_power_proxy, display_power_task) =
                fake_display_power_service.start().unwrap();

            let fake_backlight_service_ = fake_backlight_service.clone();

            let backlight = exec
                .pin_and_run_until_stalled(async {
                    fake_backlight_service_
                        .set_get_state_normalized_response(Ok(initial_backlight_state))
                        .await;

                    Backlight::with_display_power_internal(
                        backlight_proxy.clone(),
                        display_power_proxy.clone(),
                        zx::Duration::from_millis(power_off_delay_ms),
                        zx::Duration::from_millis(power_on_delay_ms),
                    )
                    .await
                    .unwrap()
                })
                .unwrap();

            (
                exec,
                Handles {
                    fake_backlight_service,
                    backlight_proxy,
                    backlight_task,
                    fake_display_power_service,
                    display_power_proxy,
                    display_power_task,
                    backlight,
                },
            )
        }
    }

    #[test]
    fn positive_brightness_changes_without_affecting_ddic() {
        let power_off_delay_ms = 100;
        let power_on_delay_ms = 50;

        let (mut exec, h) = Handles::new(
            power_off_delay_ms,
            power_on_delay_ms,
            BacklightCommand { backlight_on: true, brightness: 1.0 },
        );

        exec.pin_and_run_until_stalled(async {
            assert_eq!(h.backlight.get().await.unwrap(), 1.0);

            h.backlight.set(0.9).await.unwrap();
            assert_eq!(h.backlight.get().await.unwrap(), 0.9);

            h.backlight.set(0.5).await.unwrap();
            assert_eq!(h.backlight.get().await.unwrap(), 0.5);

            assert_eq!(h.fake_display_power_service.last_set_display_power_value().await, None)
        })
        .unwrap();
    }

    #[test]
    fn zero_brightness_turns_ddic_off() {
        let power_off_delay_ms = 100;
        let power_on_delay_ms = 50;

        let (mut exec, h) = Handles::new(
            power_off_delay_ms,
            power_on_delay_ms,
            BacklightCommand { backlight_on: true, brightness: 1.0 },
        );

        exec.pin_and_run_until_stalled(async {
            assert_eq!(h.backlight.get().await.unwrap(), 1.0);
            assert_eq!(h.fake_display_power_service.last_set_display_power_value().await, None);

            h.backlight.set(0.0).await.unwrap();
            assert_eq!(h.backlight.get().await.unwrap(), 0.0);
            assert_eq!(h.fake_display_power_service.last_set_display_power_value().await, None);
        })
        .unwrap();

        // Right before the power-off delay
        exec.set_fake_time(
            (zx::Time::ZERO + zx::Duration::from_millis(power_off_delay_ms - 1)).into(),
        );
        assert_eq!(exec.wake_timers_and_run_until_stalled(), false);

        exec.pin_and_run_until_stalled(async {
            assert_eq!(h.fake_display_power_service.last_set_display_power_value().await, None);
        })
        .unwrap();

        // Right after the power-off delay.
        exec.set_fake_time(
            (zx::Time::ZERO + zx::Duration::from_millis(power_off_delay_ms + 1)).into(),
        );
        assert_eq!(exec.wake_timers_and_run_until_stalled(), true);

        exec.pin_and_run_until_stalled(async {
            assert_eq!(
                h.fake_display_power_service.last_set_display_power_value().await,
                Some(false)
            );
        })
        .unwrap();
    }

    #[test]
    fn backlight_turns_on_after_ddic() {
        let power_off_delay_ms = 100;
        let power_on_delay_ms = 50;

        let (mut exec, h) = Handles::new(
            power_off_delay_ms,
            power_on_delay_ms,
            BacklightCommand { backlight_on: false, brightness: MIN_REGULATED_BRIGHTNESS },
        );

        exec.pin_and_run_until_stalled(async {
            assert_eq!(h.backlight.get().await.unwrap(), 0.0);
            assert_eq!(h.fake_display_power_service.last_set_display_power_value().await, None);
        })
        .unwrap();

        let backlight_ = h.backlight.clone();

        let mut turn_on_backlight_fut = Box::pin(async {
            backlight_.set(0.1).await.unwrap();
        });
        assert_matches!(exec.run_until_stalled(&mut turn_on_backlight_fut), Poll::Pending);

        exec.pin_and_run_until_stalled(async {
            assert_eq!(h.backlight.get().await.unwrap(), 0.0);
            assert_eq!(
                h.fake_display_power_service.last_set_display_power_value().await,
                Some(true)
            );
        })
        .unwrap();

        exec.set_fake_time(
            (zx::Time::ZERO + zx::Duration::from_millis(power_on_delay_ms - 1)).into(),
        );
        assert_eq!(exec.wake_timers_and_run_until_stalled(), false);
        assert_matches!(exec.run_until_stalled(&mut turn_on_backlight_fut), Poll::Pending);
        exec.pin_and_run_until_stalled(async {
            assert_eq!(h.backlight.get().await.unwrap(), 0.0);
        })
        .unwrap();

        exec.set_fake_time(
            (zx::Time::ZERO + zx::Duration::from_millis(power_on_delay_ms + 1)).into(),
        );
        assert_eq!(exec.wake_timers_and_run_until_stalled(), true);
        assert_matches!(exec.run_until_stalled(&mut turn_on_backlight_fut), Poll::Ready(()));
        exec.pin_and_run_until_stalled(async {
            assert_eq!(h.backlight.get().await.unwrap(), 0.1);
        })
        .unwrap();
    }

    #[test]
    fn repeated_backlight_off_commands_do_not_affect_ddic() {
        let power_off_delay_ms = 100;
        let power_on_delay_ms = 50;

        let (mut exec, h) = Handles::new(
            power_off_delay_ms,
            power_on_delay_ms,
            BacklightCommand { backlight_on: false, brightness: MIN_REGULATED_BRIGHTNESS },
        );

        exec.pin_and_run_until_stalled(async {
            assert_eq!(h.backlight.get().await.unwrap(), 0.0);
            assert_eq!(h.fake_display_power_service.last_set_display_power_value().await, None);

            h.backlight.set(0.0).await.unwrap();
            assert_eq!(h.backlight.get().await.unwrap(), 0.0);
            assert_eq!(h.fake_display_power_service.last_set_display_power_value().await, None);
        })
        .unwrap();
    }

    #[test]
    fn ddic_power_off_is_preempted_by_backlight_on_commands() {
        let power_off_delay_ms = 100;
        let power_on_delay_ms = 50;

        let (mut exec, h) = Handles::new(
            power_off_delay_ms,
            power_on_delay_ms,
            BacklightCommand { backlight_on: true, brightness: 1.0 },
        );

        exec.pin_and_run_until_stalled(async {
            h.backlight.set(0.0).await.unwrap();
            assert_eq!(h.backlight.get().await.unwrap(), 0.0);
            assert_eq!(h.fake_display_power_service.last_set_display_power_value().await, None);
        })
        .unwrap();

        // Right before the power-off delay
        exec.set_fake_time(
            (zx::Time::ZERO + zx::Duration::from_millis(power_off_delay_ms - 10)).into(),
        );
        assert_eq!(exec.wake_timers_and_run_until_stalled(), false);

        exec.pin_and_run_until_stalled(async {
            assert_eq!(h.fake_display_power_service.last_set_display_power_value().await, None);
        })
        .unwrap();

        exec.pin_and_run_until_stalled(async {
            h.backlight.set(0.5).await.unwrap();
            assert_eq!(h.backlight.get().await.unwrap(), 0.5);
            assert_eq!(h.fake_display_power_service.last_set_display_power_value().await, None);
        })
        .unwrap();

        // Right after the power-off delay.
        exec.set_fake_time(
            (zx::Time::ZERO + zx::Duration::from_millis(power_off_delay_ms + 10)).into(),
        );
        // The timer task should have been canceled (dropped).
        assert_eq!(exec.wake_timers_and_run_until_stalled(), false);

        exec.pin_and_run_until_stalled(async {
            assert_eq!(h.fake_display_power_service.last_set_display_power_value().await, None);
        })
        .unwrap();
    }

    #[test]
    fn backlight_power_on_is_preempted_by_ddic_off_commands() {
        let power_off_delay_ms = 100;
        let power_on_delay_ms = 50;

        let (mut exec, h) = Handles::new(
            power_off_delay_ms,
            power_on_delay_ms,
            BacklightCommand { backlight_on: false, brightness: MIN_REGULATED_BRIGHTNESS },
        );

        let mut turn_on_backlight_1_fut = Box::pin(h.backlight.set(0.1));
        let mut turn_on_backlight_2_fut = Box::pin(h.backlight.set(0.2));
        assert_matches!(exec.run_until_stalled(&mut turn_on_backlight_1_fut), Poll::Pending);
        assert_matches!(exec.run_until_stalled(&mut turn_on_backlight_2_fut), Poll::Pending);

        exec.set_fake_time(
            (zx::Time::ZERO + zx::Duration::from_millis(power_on_delay_ms - 1)).into(),
        );
        assert_eq!(exec.wake_timers_and_run_until_stalled(), false);
        assert_matches!(exec.run_until_stalled(&mut turn_on_backlight_1_fut), Poll::Pending);
        assert_matches!(exec.run_until_stalled(&mut turn_on_backlight_2_fut), Poll::Pending);

        let turn_off_backlight_fut = Box::pin(h.backlight.set(0.0));
        exec.pin_and_run_until_stalled(async {
            assert_matches!(turn_off_backlight_fut.await, Ok(()));
            // The futures that would have turned on the backlight should be cancelled.
            assert_matches!(
                turn_on_backlight_1_fut.await.unwrap_err().downcast::<oneshot::Canceled>(),
                Ok(_)
            );
            assert_matches!(
                turn_on_backlight_2_fut.await.unwrap_err().downcast::<oneshot::Canceled>(),
                Ok(_)
            );

            assert_eq!(h.backlight.get().await.unwrap(), 0.0);
        })
        .unwrap();

        exec.set_fake_time(
            (zx::Time::ZERO + zx::Duration::from_millis(power_on_delay_ms + 1)).into(),
        );
        assert_eq!(exec.wake_timers_and_run_until_stalled(), false);

        exec.pin_and_run_until_stalled(async {
            assert_eq!(h.backlight.get().await.unwrap(), 0.0);
        })
        .unwrap();
    }

    #[test]
    fn error_in_ddic_power_off_does_not_affect_later_backlight_commands() {
        let power_off_delay_ms = 100;
        let power_on_delay_ms = 50;

        let (mut exec, h) = Handles::new(
            power_off_delay_ms,
            power_on_delay_ms,
            BacklightCommand { backlight_on: true, brightness: 1.0 },
        );

        exec.pin_and_run_until_stalled(async {
            h.fake_display_power_service
                .set_set_display_power_response(Err(zx::Status::BAD_STATE.into_raw()))
                .await;

            assert_eq!(h.backlight.get().await.unwrap(), 1.0);
            assert_eq!(h.fake_display_power_service.last_set_display_power_value().await, None);

            h.backlight.set(0.0).await.unwrap();
            assert_eq!(h.backlight.get().await.unwrap(), 0.0);
            assert_eq!(h.fake_display_power_service.last_set_display_power_value().await, None);
        })
        .unwrap();

        exec.set_fake_time(
            (zx::Time::ZERO + zx::Duration::from_millis(power_off_delay_ms + 1)).into(),
        );
        assert_eq!(exec.wake_timers_and_run_until_stalled(), true);

        exec.pin_and_run_until_stalled(async {
            assert_eq!(h.fake_display_power_service.last_set_display_power_value().await, None);

            h.backlight.set(0.5).await.unwrap();
            assert_eq!(h.backlight.get().await.unwrap(), 0.5);
            assert_eq!(h.fake_display_power_service.last_set_display_power_value().await, None);
        })
        .unwrap();
    }

    #[test]
    fn error_in_ddic_power_on_is_recoverable() {
        let power_off_delay_ms = 100;
        let power_on_delay_ms = 50;

        let (mut exec, h) = Handles::new(
            power_off_delay_ms,
            power_on_delay_ms,
            BacklightCommand { backlight_on: false, brightness: MIN_REGULATED_BRIGHTNESS },
        );

        exec.pin_and_run_until_stalled(async {
            h.fake_display_power_service
                .set_set_display_power_response(Err(zx::Status::UNAVAILABLE.into_raw()))
                .await;

            assert_matches!(h.backlight.set(0.5).await, Err(_));
            assert_eq!(h.fake_display_power_service.last_set_display_power_value().await, None);

            h.fake_display_power_service.set_set_display_power_response(Ok(())).await;
        })
        .unwrap();

        let mut retry_fut = Box::pin(h.backlight.set(0.7));
        assert_matches!(exec.run_until_stalled(&mut retry_fut), Poll::Pending);

        exec.set_fake_time(
            (zx::Time::ZERO + zx::Duration::from_millis(power_on_delay_ms + 1)).into(),
        );
        assert_eq!(exec.wake_timers_and_run_until_stalled(), true);

        assert_matches!(exec.run_until_stalled(&mut retry_fut), Poll::Ready(Ok(())));
    }

    #[test]
    fn ddic_does_not_power_off_if_backlight_fails_to_power_off() {
        let power_off_delay_ms = 100;
        let power_on_delay_ms = 50;

        let (mut exec, h) = Handles::new(
            power_off_delay_ms,
            power_on_delay_ms,
            BacklightCommand { backlight_on: true, brightness: 0.5 },
        );

        exec.pin_and_run_until_stalled(async {
            h.fake_backlight_service
                .set_set_state_normalized_response(Err(zx::Status::NO_RESOURCES.into_raw()))
                .await;
            assert_matches!(h.backlight.set(0.0).await, Err(_));
        })
        .unwrap();

        exec.set_fake_time(
            (zx::Time::ZERO + zx::Duration::from_millis(power_off_delay_ms + 1)).into(),
        );
        assert_eq!(exec.wake_timers_and_run_until_stalled(), false);

        exec.pin_and_run_until_stalled(async {
            assert_eq!(h.fake_display_power_service.last_set_display_power_value().await, None);
        })
        .unwrap();
    }
}
