// Copyright 2020 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 std::sync::Arc;
use std::{fs, io};

use anyhow::{format_err, Error};
use async_trait::async_trait;
use fidl_fuchsia_ui_brightness::{
    ControlRequest as BrightnessControlRequest, ControlWatchAutoBrightnessAdjustmentResponder,
    ControlWatchAutoBrightnessResponder, ControlWatchCurrentBrightnessResponder,
};
use fuchsia_async::{self as fasync, DurationExt};
use fuchsia_zircon::sys::ZX_ERR_NOT_SUPPORTED;
use fuchsia_zircon::{Duration, DurationNum};
use futures::channel::mpsc::UnboundedSender;
use futures::future::{AbortHandle, Abortable};
use futures::lock::Mutex;
use futures::prelude::*;
use lazy_static::lazy_static;
use serde::{Deserialize, Serialize};
use splines::{Interpolation, Key, Spline};
use watch_handler::{Sender, WatchHandler};

use crate::sender_channel::SenderChannel;
use lib::backlight::BacklightControl;
use lib::sensor::SensorControl;

// Delay between sensor reads
const SLOW_SCAN_TIMEOUT_MS: i64 = 2000;
// Delay if we have made a large change in auto brightness
const QUICK_SCAN_TIMEOUT_MS: i64 = 100;
// What constitutes a large change in brightness?
// This seems small but it is significant and works nicely.
const LARGE_CHANGE_THRESHOLD_NITS: i32 = 0.016 as i32;
const AUTO_MINIMUM_BRIGHTNESS: f32 = 0.004;
const BRIGHTNESS_USER_MULTIPLIER_CENTER: f32 = 1.0;
const BRIGHTNESS_USER_MULTIPLIER_MAX: f32 = 8.0;
const BRIGHTNESS_USER_MULTIPLIER_MIN: f32 = 0.25;
const BRIGHTNESS_TABLE_FILE_PATH: &str = "/data/brightness_table";
const BRIGHTNESS_MINIMUM_CHANGE: f32 = 0.00001;
const MANUAL_BRIGHTNESS_DEFAULT: Duration = Duration::from_millis(250);

// Minimum time between brightness steps. 50 ms is the configured ramp time of the backlight.
// It'll do its smoothing within this, so there is no need to send events more frequently.
const BRIGHTNESS_MIN_STEP_TIME_MS: f64 = 50_f64;
// Brightness changes should take this time unless we exceed the MAX_BRIGHTNESS_STEP_TIME
const BRIGHTNESS_CHANGE_DURATION_MS: i64 = 2000;
// The number of possible values for the backlight hardware (0 - 4095)
// This is used to ensure we are not trying to set 1.0, 1.2, 1.4, 1.6, 1.8, 2.0
// Which would actually set 1, 1, 1, 2, 2, 2
// Instead we set 1 and 2 over a longer period of time.
const BACKLIGHT_GRANULARITY: f64 = 4095_f64;

#[derive(Serialize, Deserialize, Clone)]
struct BrightnessPoint {
    ambient_lux: f32,
    display_nits: f32,
}

#[derive(Serialize, Deserialize, Clone)]
struct BrightnessTable {
    points: Vec<BrightnessPoint>,
}

impl From<fidl_fuchsia_ui_brightness::BrightnessPoint> for BrightnessPoint {
    fn from(brightness_point: fidl_fuchsia_ui_brightness::BrightnessPoint) -> Self {
        return BrightnessPoint {
            ambient_lux: brightness_point.ambient_lux,
            display_nits: brightness_point.display_nits,
        };
    }
}

impl From<fidl_fuchsia_ui_brightness::BrightnessTable> for BrightnessTable {
    fn from(brightness_table: fidl_fuchsia_ui_brightness::BrightnessTable) -> Self {
        let fidl_fuchsia_ui_brightness::BrightnessTable { points } = brightness_table;
        return BrightnessTable { points: points.into_iter().map(|p| p.into()).collect() };
    }
}

//This is the default table, and a default curve will be generated base on this table.
//This will be replaced once SetBrightnessTable is called.
lazy_static! {
    static ref BRIGHTNESS_TABLE: Arc<Mutex<BrightnessTable>> = {
        let mut lux_to_nits = Vec::new();
        lux_to_nits.push(BrightnessPoint { ambient_lux: 0., display_nits: 0. });
        lux_to_nits.push(BrightnessPoint { ambient_lux: 10., display_nits: 3.33 });
        lux_to_nits.push(BrightnessPoint { ambient_lux: 30., display_nits: 8.7 });
        lux_to_nits.push(BrightnessPoint { ambient_lux: 60., display_nits: 18.27 });
        lux_to_nits.push(BrightnessPoint { ambient_lux: 100., display_nits: 32.785 });
        lux_to_nits.push(BrightnessPoint { ambient_lux: 150., display_nits: 36.82 });
        lux_to_nits.push(BrightnessPoint { ambient_lux: 210., display_nits: 75.0 });
        lux_to_nits.push(BrightnessPoint { ambient_lux: 250., display_nits: 124.16 });
        lux_to_nits.push(BrightnessPoint { ambient_lux: 300., display_nits: 162.96 });
        lux_to_nits.push(BrightnessPoint { ambient_lux: 340., display_nits: 300. });
        Arc::new(Mutex::new(BrightnessTable { points: lux_to_nits }))
    };
}

lazy_static! {
    static ref AUTO_BRIGHTNESS_ADJUSTMENT: Arc<Mutex<f32>> = Arc::new(Mutex::new(1.0));
    static ref GET_BRIGHTNESS_FAILED_FIRST: Arc<Mutex<bool>> = Arc::new(Mutex::new(true));
    static ref LAST_SET_BRIGHTNESS: Arc<Mutex<f32>> = Arc::new(Mutex::new(1.0));
    static ref BRIGHTNESS_CHANGE_DURATION: Arc<Mutex<Duration>> =
        Arc::new(Mutex::new(BRIGHTNESS_CHANGE_DURATION_MS.millis()));
}

pub struct WatcherCurrentResponder {
    watcher_current_responder: ControlWatchCurrentBrightnessResponder,
}

impl Sender<f32> for WatcherCurrentResponder {
    fn send_response(self, data: f32) {
        if let Err(e) = self.watcher_current_responder.send(data) {
            tracing::error!("Failed to reply to WatchCurrentBrightness: {}", e);
        }
    }
}

pub struct WatcherAutoResponder {
    watcher_auto_responder: ControlWatchAutoBrightnessResponder,
}

impl Sender<bool> for WatcherAutoResponder {
    fn send_response(self, data: bool) {
        if let Err(e) = self.watcher_auto_responder.send(data) {
            tracing::error!("Failed to reply to WatchAutoBrightness: {}", e);
        }
    }
}

pub struct WatcherAdjustmentResponder {
    watcher_adjustment_responder: ControlWatchAutoBrightnessAdjustmentResponder,
}

impl Sender<f32> for WatcherAdjustmentResponder {
    fn send_response(self, data: f32) {
        if let Err(e) = self.watcher_adjustment_responder.send(data) {
            tracing::error!("Failed to reply to WatchAutoBrightnessAdjustment: {}", e);
        }
    }
}

#[derive(Debug)]
pub struct Control {
    sensor: Arc<Mutex<dyn SensorControl>>,
    backlight: Arc<dyn BacklightControl>,
    set_brightness_abort_handle: Arc<Mutex<Option<AbortHandle>>>,
    auto_brightness_abort_handle: Option<AbortHandle>,
    spline: Spline<f32, f32>,
    current_sender_channel: Arc<Mutex<SenderChannel<f32>>>,
    auto_sender_channel: Arc<Mutex<SenderChannel<bool>>>,
    adjustment_sender_channel: Arc<Mutex<SenderChannel<f32>>>,
}

impl Control {
    pub async fn new(
        sensor: Arc<Mutex<dyn SensorControl>>,
        backlight: Arc<dyn BacklightControl>,
        current_sender_channel: Arc<Mutex<SenderChannel<f32>>>,
        auto_sender_channel: Arc<Mutex<SenderChannel<bool>>>,
        adjustment_sender_channel: Arc<Mutex<SenderChannel<f32>>>,
    ) -> Control {
        tracing::info!("New Control class");

        let set_brightness_abort_handle = Arc::new(Mutex::new(None::<AbortHandle>));
        let default_table_points = &*BRIGHTNESS_TABLE.lock().await.points;
        let brightness_table = read_brightness_table_file(BRIGHTNESS_TABLE_FILE_PATH)
            .unwrap_or_else(|e| {
                tracing::warn!(
                    "Failed to read existing settings: {}, using default table instead.",
                    e
                );
                BrightnessTable { points: default_table_points.to_vec() }
            });

        let spline = generate_spline(&brightness_table);

        let auto_brightness_abort_handle = None::<AbortHandle>;
        let result = Control {
            backlight,
            sensor,
            set_brightness_abort_handle,
            auto_brightness_abort_handle,
            spline,
            current_sender_channel,
            auto_sender_channel,
            adjustment_sender_channel,
        };
        // Disable startup auto-brightness loop by default
        // result.start_auto_brightness_task();
        result
    }

    pub async fn handle_request(
        &mut self,
        request: BrightnessControlRequest,
        watch_current_handler: Arc<Mutex<WatchHandler<f32, WatcherCurrentResponder>>>,
        watch_auto_handler: Arc<Mutex<WatchHandler<bool, WatcherAutoResponder>>>,
        watch_adjustment_handler: Arc<Mutex<WatchHandler<f32, WatcherAdjustmentResponder>>>,
    ) {
        // TODO(kpt): "Consider adding additional tests against the resulting FIDL service itself so
        // that you can ensure it continues serving clients correctly."
        match request {
            BrightnessControlRequest::SetAutoBrightness { control_handle: _ } => {
                self.set_auto_brightness().await;
            }
            BrightnessControlRequest::WatchAutoBrightness { responder } => {
                let watch_auto_result =
                    self.watch_auto_brightness(watch_auto_handler, responder).await;
                match watch_auto_result {
                    Ok(_v) => {}
                    Err(e) => tracing::error!("Watch auto brightness failed due to err {}.", e),
                }
            }
            BrightnessControlRequest::SetManualBrightness { value, control_handle: _ } => {
                let value = num_traits::clamp(value, 0.0, 1.0);
                self.set_manual_brightness(value).await;
            }
            BrightnessControlRequest::SetManualBrightnessSmooth {
                value,
                duration: duration_ns,
                control_handle: _,
            } => {
                self.set_manual_brightness_smooth(value, Duration::from_nanos(duration_ns)).await;
            }
            BrightnessControlRequest::WatchCurrentBrightness { responder } => {
                let watch_current_result =
                    self.watch_current_brightness(watch_current_handler, responder).await;
                match watch_current_result {
                    Ok(_v) => {}
                    Err(e) => tracing::error!("Watch current brightness failed due to err {}.", e),
                }
            }
            BrightnessControlRequest::SetBrightnessTable { table, control_handle: _ } => {
                let result = self.check_brightness_table_and_set_new_curve(&table.into()).await;
                match result {
                    Ok(_v) => tracing::info!("Brightness table is valid and set"),
                    Err(e) => {
                        // TODO(lingxueluo): Close the connection if brightness table not valid.
                        tracing::error!("Brightness table is not valid because {}", e);
                    }
                }
            }

            BrightnessControlRequest::SetAutoBrightnessAdjustment {
                adjustment,
                control_handle: _,
            } => {
                self.scale_new_adjustment(adjustment).await;
            }
            BrightnessControlRequest::WatchAutoBrightnessAdjustment { responder } => {
                let watch_adjustment_result = self
                    .watch_auto_brightness_adjustment(watch_adjustment_handler, responder)
                    .await;
                match watch_adjustment_result {
                    Ok(_v) => {}
                    Err(e) => tracing::error!("Watch adjustment failed due to err {}.", e),
                }
            }
            BrightnessControlRequest::GetMaxAbsoluteBrightness { responder } => {
                let result = self.get_max_absolute_brightness();
                match result.await {
                    Ok(value) => {
                        if let Err(e) = responder.send(Ok(value)) {
                            tracing::error!("Failed to reply to GetMaxAbsoluteBrightness: {}", e);
                        }
                    }
                    Err(e) => {
                        tracing::error!("Failed to get max absolute brightness: {}", e);

                        if let Err(e) = responder.send(Err(ZX_ERR_NOT_SUPPORTED)) {
                            tracing::error!("Failed to reply to GetMaxAbsoluteBrightness: {}", e);
                        }
                    }
                }
            }
        }
    }

    pub async fn add_current_sender_channel(&mut self, sender: UnboundedSender<f32>) {
        self.current_sender_channel.lock().await.add_sender_channel(sender).await;
    }

    pub async fn add_auto_sender_channel(&mut self, sender: UnboundedSender<bool>) {
        self.auto_sender_channel.lock().await.add_sender_channel(sender).await;
    }

    pub async fn add_adjustment_sender_channel(&mut self, sender: UnboundedSender<f32>) {
        self.adjustment_sender_channel.lock().await.add_sender_channel(sender).await;
    }

    pub fn get_backlight_and_auto_brightness_on(&mut self) -> (Arc<dyn BacklightControl>, bool) {
        (self.backlight.clone(), self.auto_brightness_abort_handle.is_some())
    }

    // FIDL message handlers
    async fn set_auto_brightness(&mut self) {
        if self.auto_brightness_abort_handle.is_none() {
            tracing::info!("Auto-brightness turned on");
            self.start_auto_brightness_task();
            self.auto_sender_channel
                .lock()
                .await
                .send_value(self.auto_brightness_abort_handle.is_some());
        }
    }

    async fn watch_auto_brightness(
        &mut self,
        watch_auto_handler: Arc<Mutex<WatchHandler<bool, WatcherAutoResponder>>>,
        responder: ControlWatchAutoBrightnessResponder,
    ) -> Result<(), Error> {
        let mut hanging_get_lock = watch_auto_handler.lock().await;
        hanging_get_lock.watch(WatcherAutoResponder { watcher_auto_responder: responder })?;
        Ok(())
    }

    fn start_auto_brightness_task(&mut self) {
        if let Some(handle) = &self.auto_brightness_abort_handle.take() {
            handle.abort();
        }
        let backlight = self.backlight.clone();
        let sensor = self.sensor.clone();
        let set_brightness_abort_handle = self.set_brightness_abort_handle.clone();
        let current_sender_channel = self.current_sender_channel.clone();
        let spline = self.spline.clone();
        let (abort_handle, abort_registration) = AbortHandle::new_pair();
        fasync::Task::spawn(
            Abortable::new(
                async move {
                    let backlight = backlight.clone();
                    let max_brightness = {
                        let backlight = backlight.clone();
                        let max_result = backlight.get_max_absolute_brightness();
                        match max_result.await {
                            Ok(max_value) => max_value,
                            Err(_e) => 250.0,
                        }
                    };
                    // initialize to an impossible number
                    let mut last_value: i32 = -1;
                    loop {
                        let current_sender_channel = current_sender_channel.clone();
                        let sensor = sensor.clone();
                        let mut value =
                            read_sensor_and_get_brightness(sensor, &spline, max_brightness).await;
                        let adjustment = *AUTO_BRIGHTNESS_ADJUSTMENT.lock().await;
                        value = num_traits::clamp(value * adjustment, AUTO_MINIMUM_BRIGHTNESS, 1.0);
                        set_brightness(
                            value,
                            set_brightness_abort_handle.clone(),
                            backlight.clone(),
                            current_sender_channel,
                        )
                        .await;
                        let large_change =
                            (last_value as i32 - value as i32).abs() > LARGE_CHANGE_THRESHOLD_NITS;
                        last_value = value as i32;
                        let delay_timeout =
                            if large_change { QUICK_SCAN_TIMEOUT_MS } else { SLOW_SCAN_TIMEOUT_MS };
                        fuchsia_async::Timer::new(Duration::from_millis(delay_timeout).after_now())
                            .await;
                    }
                },
                abort_registration,
            )
            .unwrap_or_else(|_| ()),
        )
        .detach();
        self.auto_brightness_abort_handle = Some(abort_handle);
    }

    async fn set_manual_brightness(&mut self, value: f32) {
        self.set_manual_brightness_smooth(value, MANUAL_BRIGHTNESS_DEFAULT).await;
    }

    async fn set_manual_brightness_smooth(&mut self, value: f32, duration: Duration) {
        if let Some(handle) = self.auto_brightness_abort_handle.take() {
            tracing::info!("Auto-brightness off, brightness set to {}", value);
            handle.abort();
        }

        let value = num_traits::clamp(value, 0.0, 1.0);
        {
            // Hold the locks for as little time as possible
            *BRIGHTNESS_CHANGE_DURATION.lock().await = duration;
            self.auto_sender_channel.lock().await.send_value(false);
        }
        let current_sender_channel = self.current_sender_channel.clone();
        set_brightness(
            value,
            self.set_brightness_abort_handle.clone(),
            self.backlight.clone(),
            current_sender_channel,
        )
        .await;
    }

    async fn watch_current_brightness(
        &mut self,
        watch_current_handler: Arc<Mutex<WatchHandler<f32, WatcherCurrentResponder>>>,
        responder: ControlWatchCurrentBrightnessResponder,
    ) -> Result<(), Error> {
        let mut hanging_get_lock = watch_current_handler.lock().await;
        hanging_get_lock.watch(WatcherCurrentResponder { watcher_current_responder: responder })?;
        Ok(())
    }

    async fn set_brightness_curve(&mut self, table: &BrightnessTable) {
        tracing::info!("Setting new brightness curve.");
        self.spline = generate_spline(table);

        self.start_auto_brightness_task();

        let result = self.store_brightness_table(table, BRIGHTNESS_TABLE_FILE_PATH);
        match result {
            Ok(_v) => tracing::info!("Stored successfully"),
            Err(e) => tracing::info!("Didn't store successfully due to error {}", e),
        }
    }

    fn store_brightness_table(
        &mut self,
        table: &BrightnessTable,
        file_path: &str,
    ) -> Result<(), Error> {
        tracing::info!("Storing brightness table set.");
        let file = fs::File::create(file_path)?;
        serde_json::to_writer(io::BufWriter::new(file), &table)
            .map_err(|e| anyhow::format_err!("Failed to write to file, ran into error: {:?}", e))
    }

    async fn check_brightness_table_and_set_new_curve(
        &mut self,
        table: &BrightnessTable,
    ) -> Result<(), Error> {
        let BrightnessTable { points } = table;
        if points.is_empty() {
            tracing::info!("Brightness table can not be empty, use the default table instead.");
            let BrightnessTable { points } = &*BRIGHTNESS_TABLE.lock().await;
            let brightness_table = BrightnessTable { points: points.to_vec() };
            self.set_brightness_curve(&brightness_table).await;
            return Ok(());
        }
        let mut last_lux = -1.0;
        for brightness_point in points {
            if brightness_point.ambient_lux < 0.0 || brightness_point.display_nits < 0.0 {
                tracing::info!("Lux or nits in this table is negative.");
                return Err(format_err!(format!("Lux or nits in this table is negative.")));
            }
            if brightness_point.ambient_lux > last_lux {
                last_lux = brightness_point.ambient_lux;
            } else {
                tracing::info!("Not increasing lux in this table.");
                return Err(format_err!(format!("Not increasing lux in this table.")));
            }
        }
        self.set_brightness_curve(&table).await;
        Ok(())
    }

    async fn scale_new_adjustment(&mut self, mut adjustment: f32) -> f32 {
        self.adjustment_sender_channel.lock().await.send_value(adjustment);
        // |adjustment| ranges from [-1.0, 1.0]
        // Default adjustment is 0.0, map that to x1.0
        if adjustment >= 0.0 {
            // Map from [0.0, 1.0] to [BRIGHTNESS_USER_MULTIPLIER_CENTER,
            // BRIGHTNESS_USER_MULTIPLIER_MAX]
            adjustment = adjustment
                * (BRIGHTNESS_USER_MULTIPLIER_MAX - BRIGHTNESS_USER_MULTIPLIER_CENTER)
                + BRIGHTNESS_USER_MULTIPLIER_CENTER;
        } else {
            // Map from [-1.0, 0.0) to [BRIGHTNESS_USER_MULTIPLIER_MIN,
            // BRIGHTNESS_USER_MULTIPLIER_CENTER)
            adjustment = adjustment
                * (BRIGHTNESS_USER_MULTIPLIER_CENTER - BRIGHTNESS_USER_MULTIPLIER_MIN)
                + BRIGHTNESS_USER_MULTIPLIER_CENTER;
        }

        *AUTO_BRIGHTNESS_ADJUSTMENT.lock().await = adjustment;
        return adjustment;
    }

    async fn watch_auto_brightness_adjustment(
        &mut self,
        watch_adjustment_handler: Arc<Mutex<WatchHandler<f32, WatcherAdjustmentResponder>>>,
        responder: ControlWatchAutoBrightnessAdjustmentResponder,
    ) -> Result<(), Error> {
        let mut hanging_get_lock = watch_adjustment_handler.lock().await;
        hanging_get_lock
            .watch(WatcherAdjustmentResponder { watcher_adjustment_responder: responder })?;
        Ok(())
    }

    async fn get_max_absolute_brightness(&mut self) -> Result<f64, Error> {
        self.backlight.get_max_absolute_brightness().await
    }
}

#[async_trait(? Send)]
pub trait ControlTrait {
    async fn handle_request(
        &mut self,
        request: BrightnessControlRequest,
        watch_current_handler: Arc<Mutex<WatchHandler<f32, WatcherCurrentResponder>>>,
        watch_auto_handler: Arc<Mutex<WatchHandler<bool, WatcherAutoResponder>>>,
        watch_adjustment_handler: Arc<Mutex<WatchHandler<f32, WatcherAdjustmentResponder>>>,
    );
    async fn add_current_sender_channel(&mut self, sender: UnboundedSender<f32>);
    async fn add_auto_sender_channel(&mut self, sender: UnboundedSender<bool>);
    async fn add_adjustment_sender_channel(&mut self, sender: UnboundedSender<f32>);
    fn get_backlight_and_auto_brightness_on(&mut self) -> (Arc<dyn BacklightControl>, bool);
}

#[async_trait(? Send)]
impl ControlTrait for Control {
    async fn handle_request(
        &mut self,
        request: BrightnessControlRequest,
        watch_current_handler: Arc<Mutex<WatchHandler<f32, WatcherCurrentResponder>>>,
        watch_auto_handler: Arc<Mutex<WatchHandler<bool, WatcherAutoResponder>>>,
        watch_adjustment_handler: Arc<Mutex<WatchHandler<f32, WatcherAdjustmentResponder>>>,
    ) {
        self.handle_request(
            request,
            watch_current_handler,
            watch_auto_handler,
            watch_adjustment_handler,
        )
        .await;
    }

    async fn add_current_sender_channel(&mut self, sender: UnboundedSender<f32>) {
        self.add_current_sender_channel(sender).await;
    }

    async fn add_auto_sender_channel(&mut self, sender: UnboundedSender<bool>) {
        self.add_auto_sender_channel(sender).await;
    }

    async fn add_adjustment_sender_channel(&mut self, sender: UnboundedSender<f32>) {
        self.add_adjustment_sender_channel(sender).await;
    }

    fn get_backlight_and_auto_brightness_on(&mut self) -> (Arc<dyn BacklightControl>, bool) {
        self.get_backlight_and_auto_brightness_on()
    }
}

// TODO(kpt) Move all the folllowing functions into Control. This is delayed so that in the CL
// for the creation of this code the reviewer can see more easily that the code is unchanged
// after the extraction from main.rs.

fn read_brightness_table_file(path: &str) -> Result<BrightnessTable, Error> {
    let file = fs::File::open(path)?;
    let result = serde_json::from_reader(io::BufReader::new(file));
    let result = result
        .map_err(|e| anyhow::format_err!("Failed to read from file, ran into error: {:?}", e));
    result
}

fn generate_spline(table: &BrightnessTable) -> Spline<f32, f32> {
    let BrightnessTable { points } = table;
    let mut lux_to_nits_table_to_splines = Vec::new();
    for brightness_point in points {
        lux_to_nits_table_to_splines.push(Key::new(
            brightness_point.ambient_lux,
            brightness_point.display_nits,
            Interpolation::Linear,
        ));
    }
    Spline::from_iter(lux_to_nits_table_to_splines.iter().cloned())
}

// TODO(kpt) Move this and other functions into Control so that they can share the struct
// Then we won't need all these global locked variables.
/// Runs the main auto-brightness code.

async fn get_current_brightness(backlight: Arc<dyn BacklightControl>) -> f32 {
    let fut = backlight.get_brightness();
    // TODO(lingxueluo) Deal with this in backlight.rs later.
    match fut.await {
        Ok(brightness) => brightness as f32,
        Err(e) => {
            if *GET_BRIGHTNESS_FAILED_FIRST.lock().await {
                tracing::warn!("Failed to get backlight: {}. assuming 1.0", e);
                *GET_BRIGHTNESS_FAILED_FIRST.lock().await = false;
            }
            *LAST_SET_BRIGHTNESS.lock().await
        }
    }
}

async fn set_current_brightness(backlight: Arc<dyn BacklightControl>, value: f64) {
    backlight
        .set_brightness(value)
        .await
        .unwrap_or_else(|e| tracing::error!("Failed to set backlight: {}", e))
}

async fn read_sensor_and_get_brightness(
    sensor: Arc<Mutex<dyn SensorControl>>,
    spline: &Spline<f32, f32>,
    max_brightness: f64,
) -> f32 {
    loop {
        // Get the sensor reading in its own mutex block
        let sensor = sensor.lock().await;
        // TODO(kpt) Do we need a Mutex if sensor is only read?
        let fut = sensor.read();
        if let Some(report) = fut.await.expect("Could not read from the sensor") {
            return brightness_curve_lux_to_nits(report.illuminance, spline).await
                / max_brightness as f32;
        }
    }
}

async fn brightness_curve_lux_to_nits(lux: f32, spline: &Spline<f32, f32>) -> f32 {
    let result = (*spline).clamped_sample(lux as f32);
    match result {
        Some(nits) => {
            return nits;
        }
        None => return 1.0,
    }
}

/// Sets the brightness of the backlight to a specific value.
/// An abortable task is spawned to handle this as it can take a while to do.
async fn set_brightness(
    value: f32,
    set_brightness_abort_handle: Arc<Mutex<Option<AbortHandle>>>,
    backlight: Arc<dyn BacklightControl>,
    current_sender_channel: Arc<Mutex<SenderChannel<f32>>>,
) {
    let value = num_traits::clamp(value, 0.0, 1.0);
    let current_value = get_current_brightness(backlight.clone()).await;
    if (current_value - value).abs() >= BRIGHTNESS_MINIMUM_CHANGE {
        let mut set_brightness_abort_handle = set_brightness_abort_handle.lock().await;
        if let Some(handle) = set_brightness_abort_handle.take() {
            handle.abort();
        }
        let (abort_handle, abort_registration) = AbortHandle::new_pair();
        let backlight = backlight.clone();
        let current_sender_channel = current_sender_channel.clone();
        fasync::Task::spawn(
            Abortable::new(
                async move {
                    set_brightness_impl(value, backlight, current_sender_channel).await;
                },
                abort_registration,
            )
            .unwrap_or_else(|_task_aborted| ()),
        )
        .detach();
        *set_brightness_abort_handle = Some(abort_handle);
    }
}

async fn set_brightness_impl(
    value: f32,
    backlight: Arc<dyn BacklightControl>,
    current_sender_channel: Arc<Mutex<SenderChannel<f32>>>,
) {
    let current_value = get_current_brightness(backlight.clone()).await;
    let backlight = backlight.clone();
    let current_sender_channel = current_sender_channel.clone();
    let brightness_change_duration = BRIGHTNESS_CHANGE_DURATION.lock().await;
    let duration = *brightness_change_duration;
    drop(brightness_change_duration);
    set_brightness_slowly(current_value, value, backlight, duration, current_sender_channel).await;
}

/// Change the brightness of the screen slowly. We don't want to change the screen
/// suddenly so we smooth the transition by doing it in a series of small steps over
/// a given time. The backlight granularity is taken into account to avoid very small
/// changes to brightness that don't actually change the final value in the I2C register.
async fn set_brightness_slowly(
    current_value: f32,
    to_value: f32,
    backlight: Arc<dyn BacklightControl>,
    duration: Duration,
    current_sender_channel: Arc<Mutex<SenderChannel<f32>>>,
) {
    let mut current_value = current_value as f64;
    let to_value = num_traits::clamp(to_value, 0.0, 1.0) as f64;
    assert!(to_value <= 1.0);
    assert!(current_value <= 1.0);
    let current_sender_channel = current_sender_channel.clone();
    let difference = to_value - current_value;
    if difference.abs() < BRIGHTNESS_MINIMUM_CHANGE as f64 {
        return;
    }
    let mut time_per_step =
        duration.into_millis() as f64 / (BACKLIGHT_GRANULARITY * difference.abs());
    if time_per_step < BRIGHTNESS_MIN_STEP_TIME_MS {
        // Too frequent, let's slow it down. It will still look smooth.
        time_per_step = BRIGHTNESS_MIN_STEP_TIME_MS;
    }
    let sleep_time = Duration::from_millis(time_per_step as i64);
    let steps = (duration.into_millis() as f64 / time_per_step) as i64;
    if steps > 0 {
        let step_size = difference / steps as f64;
        for _i in 1..steps {
            let current_sender_channel = current_sender_channel.clone();
            current_value = current_value + step_size;
            set_current_brightness(backlight.clone(), current_value).await;
            current_sender_channel.lock().await.send_value(current_value as f32);
            // TODO(kpt): Timer::new() should take a Duration but gets an error
            fuchsia_async::Timer::new(sleep_time.after_now()).await;
        }
    }
    // Make sure we get to the correct value
    set_current_brightness(backlight.clone(), to_value).await;
    current_sender_channel.lock().await.send_value(to_value as f32);
    *LAST_SET_BRIGHTNESS.lock().await = to_value as f32;
}

#[cfg(test)]
mod tests {
    use std::path::Path;

    use anyhow::format_err;
    use async_trait::async_trait;
    use fuchsia_async::TestExecutor;
    use futures::executor::block_on;
    use futures::pin_mut;

    use lib::sensor::AmbientLightInputRpt;

    use super::*;

    struct MockSensor {
        illuminence: f32,
    }

    #[async_trait]
    impl SensorControl for MockSensor {
        async fn read(&self) -> Result<Option<AmbientLightInputRpt>, Error> {
            Ok(Some(AmbientLightInputRpt {
                illuminance: self.illuminence,
                red: 0.0,
                green: 0.0,
                blue: 0.0,
            }))
        }
    }

    #[derive(Debug, Clone)]
    struct MockBacklight {
        inner: Arc<Mutex<Inner>>,
    }

    impl MockBacklight {
        fn new(valid_backlight: bool, value: f64, max_brightness: f64) -> Self {
            Self { inner: Arc::new(Mutex::new(Inner { valid_backlight, value, max_brightness })) }
        }
    }

    #[derive(Debug)]
    struct Inner {
        valid_backlight: bool,
        value: f64,
        max_brightness: f64,
    }

    #[async_trait]
    impl BacklightControl for MockBacklight {
        async fn get_brightness(&self) -> Result<f64, Error> {
            let inner = self.inner.lock().await;
            if inner.valid_backlight {
                Ok(inner.value)
            } else {
                Err(format_err!("Get brightness failed."))
            }
        }

        async fn set_brightness(&self, value: f64) -> Result<(), Error> {
            self.inner.lock().await.value = value;
            Ok(())
        }

        async fn get_max_absolute_brightness(&self) -> Result<f64, Error> {
            Ok(self.inner.lock().await.max_brightness)
        }
    }

    fn set_mocks(
        sensor: f32,
        backlight: f64,
    ) -> (Arc<Mutex<impl SensorControl>>, Arc<impl BacklightControl>) {
        let sensor = MockSensor { illuminence: sensor };
        let sensor = Arc::new(Mutex::new(sensor));
        let backlight = MockBacklight::new(true, backlight, 250.0);
        let backlight = Arc::new(backlight);
        (sensor, backlight)
    }

    fn set_mocks_not_valid(
        sensor: f32,
        backlight: f64,
    ) -> (Arc<Mutex<impl SensorControl>>, Arc<impl BacklightControl>) {
        let sensor = MockSensor { illuminence: sensor };
        let sensor = Arc::new(Mutex::new(sensor));
        let backlight = MockBacklight::new(false, backlight, 250.0);
        let backlight = Arc::new(backlight);
        (sensor, backlight)
    }

    async fn generate_control_struct(sensor: f32, backlight: f64) -> Control {
        let (sensor, backlight) = set_mocks(sensor, backlight);
        let set_brightness_abort_handle = Arc::new(Mutex::new(None::<AbortHandle>));
        let auto_brightness_abort_handle = None::<AbortHandle>;
        let BrightnessTable { points } = &*BRIGHTNESS_TABLE.lock().await;
        let brightness_table_old = BrightnessTable { points: points.to_vec() };
        let spline_arg = generate_spline(brightness_table_old.clone());

        let current_sender_channel: SenderChannel<f32> = SenderChannel::new();
        let current_sender_channel = Arc::new(Mutex::new(current_sender_channel));

        let auto_sender_channel: SenderChannel<bool> = SenderChannel::new();
        let auto_sender_channel = Arc::new(Mutex::new(auto_sender_channel));

        let adjustment_sender_channel: SenderChannel<f32> = SenderChannel::new();
        let adjustment_sender_channel = Arc::new(Mutex::new(adjustment_sender_channel));

        Control {
            sensor,
            backlight,
            set_brightness_abort_handle,
            auto_brightness_abort_handle,
            spline: spline_arg,
            current_sender_channel,
            auto_sender_channel,
            adjustment_sender_channel,
        }
    }

    fn generate_spline(table: BrightnessTable) -> Spline<f32, f32> {
        let BrightnessTable { points } = &table;
        let mut lux_to_nits_table_to_splines = Vec::new();
        for brightness_point in points {
            lux_to_nits_table_to_splines.push(Key::new(
                brightness_point.ambient_lux,
                brightness_point.display_nits,
                Interpolation::Linear,
            ));
        }
        Spline::from_iter(lux_to_nits_table_to_splines.iter().cloned())
    }

    fn cmp_float(value1: f32, value2: f32) -> bool {
        (value1 - value2).abs() < 0.01
    }

    #[fasync::run_singlethreaded(test)]
    async fn test_brightness_curve() {
        let BrightnessTable { points } = &*BRIGHTNESS_TABLE.lock().await;
        let brightness_table = BrightnessTable { points: points.to_vec() };
        let spline = generate_spline(brightness_table);

        assert_eq!(cmp_float(0., brightness_curve_lux_to_nits(0.0, &spline).await), true);
        assert_eq!(cmp_float(0.333, brightness_curve_lux_to_nits(1.0, &spline).await), true);
        assert_eq!(cmp_float(0.666, brightness_curve_lux_to_nits(2.0, &spline).await), true);
        assert_eq!(cmp_float(4.67, brightness_curve_lux_to_nits(15.0, &spline).await), true);
        assert_eq!(cmp_float(4.94, brightness_curve_lux_to_nits(16.0, &spline).await), true);
        assert_eq!(cmp_float(32.78, brightness_curve_lux_to_nits(100.0, &spline).await), true);
        assert_eq!(cmp_float(36.82, brightness_curve_lux_to_nits(150.0, &spline).await), true);
        assert_eq!(cmp_float(68.63, brightness_curve_lux_to_nits(200.0, &spline).await), true);
        assert_eq!(cmp_float(111.87, brightness_curve_lux_to_nits(240.0, &spline).await), true);
        assert_eq!(cmp_float(162.96, brightness_curve_lux_to_nits(300.0, &spline).await), true);
        assert_eq!(cmp_float(300., brightness_curve_lux_to_nits(340.0, &spline).await), true);
    }

    #[fasync::run_singlethreaded(test)]
    async fn test_brightness_table_valid() {
        let mut control = generate_control_struct(400.0, 0.5).await;
        let brightness_table = {
            let mut lux_to_nits = Vec::new();
            lux_to_nits.push(BrightnessPoint { ambient_lux: 10., display_nits: 50. });
            lux_to_nits.push(BrightnessPoint { ambient_lux: 30., display_nits: 50. });
            lux_to_nits.push(BrightnessPoint { ambient_lux: 60., display_nits: 50. });
            lux_to_nits.push(BrightnessPoint { ambient_lux: 100., display_nits: 50. });
            lux_to_nits.push(BrightnessPoint { ambient_lux: 150., display_nits: 50. });
            lux_to_nits.push(BrightnessPoint { ambient_lux: 210., display_nits: 50. });
            lux_to_nits.push(BrightnessPoint { ambient_lux: 250., display_nits: 50. });
            lux_to_nits.push(BrightnessPoint { ambient_lux: 300., display_nits: 50. });

            BrightnessTable { points: lux_to_nits }
        };
        control.check_brightness_table_and_set_new_curve(&brightness_table).await.unwrap();
        assert_eq!(cmp_float(50.0, brightness_curve_lux_to_nits(0.0, &control.spline).await), true);
        assert_eq!(cmp_float(50.0, brightness_curve_lux_to_nits(1.0, &control.spline).await), true);
        assert_eq!(cmp_float(50.0, brightness_curve_lux_to_nits(2.0, &control.spline).await), true);
        assert_eq!(
            cmp_float(50.0, brightness_curve_lux_to_nits(15.0, &control.spline).await),
            true
        );
        assert_eq!(
            cmp_float(50.0, brightness_curve_lux_to_nits(16.0, &control.spline).await),
            true
        );
        assert_eq!(
            cmp_float(50.0, brightness_curve_lux_to_nits(100.0, &control.spline).await),
            true
        );
        assert_eq!(
            cmp_float(50.0, brightness_curve_lux_to_nits(150.0, &control.spline).await),
            true
        );
        assert_eq!(
            cmp_float(50.0, brightness_curve_lux_to_nits(200.0, &control.spline).await),
            true
        );
        assert_eq!(
            cmp_float(50.0, brightness_curve_lux_to_nits(240.0, &control.spline).await),
            true
        );
        assert_eq!(
            cmp_float(50.0, brightness_curve_lux_to_nits(300.0, &control.spline).await),
            true
        );
    }

    #[fasync::run_singlethreaded(test)]
    async fn test_brightness_table_not_valid_negative_value() {
        let mut control = generate_control_struct(400.0, 0.5).await;
        let brightness_table = {
            let mut lux_to_nits = Vec::new();
            lux_to_nits.push(BrightnessPoint { ambient_lux: -10., display_nits: 50. });
            lux_to_nits.push(BrightnessPoint { ambient_lux: 30., display_nits: 50. });
            BrightnessTable { points: lux_to_nits }
        };
        control.check_brightness_table_and_set_new_curve(&brightness_table).await.unwrap_err();
    }

    #[fasync::run_singlethreaded(test)]
    async fn test_brightness_table_not_valid_lux_not_increasing() {
        let mut control = generate_control_struct(400.0, 0.5).await;
        let brightness_table = {
            let mut lux_to_nits = Vec::new();
            lux_to_nits.push(BrightnessPoint { ambient_lux: 10., display_nits: 50. });
            lux_to_nits.push(BrightnessPoint { ambient_lux: 30., display_nits: 50. });
            lux_to_nits.push(BrightnessPoint { ambient_lux: 3., display_nits: 50. });
            lux_to_nits.push(BrightnessPoint { ambient_lux: 100., display_nits: 50. });
            BrightnessTable { points: lux_to_nits }
        };
        control.check_brightness_table_and_set_new_curve(&brightness_table).await.unwrap_err();
    }

    #[fasync::run_singlethreaded(test)]
    async fn test_brightness_table_valid_but_empty() {
        let mut control = generate_control_struct(400.0, 0.5).await;
        let brightness_table = {
            let lux_to_nits = Vec::new();
            BrightnessTable { points: lux_to_nits }
        };
        let old_curve = &control.spline.clone();
        control.check_brightness_table_and_set_new_curve(&brightness_table).await.unwrap();
        assert_eq!(
            cmp_float(
                brightness_curve_lux_to_nits(0.0, old_curve).await,
                brightness_curve_lux_to_nits(0.0, &control.spline).await,
            ),
            true
        );
        assert_eq!(
            cmp_float(
                brightness_curve_lux_to_nits(1.0, old_curve).await,
                brightness_curve_lux_to_nits(1.0, &control.spline).await,
            ),
            true
        );
        assert_eq!(
            cmp_float(
                brightness_curve_lux_to_nits(2.0, old_curve).await,
                brightness_curve_lux_to_nits(2.0, &control.spline).await,
            ),
            true
        );
        assert_eq!(
            cmp_float(
                brightness_curve_lux_to_nits(15.0, old_curve).await,
                brightness_curve_lux_to_nits(15.0, &control.spline).await,
            ),
            true
        );
        assert_eq!(
            cmp_float(
                brightness_curve_lux_to_nits(16.0, old_curve).await,
                brightness_curve_lux_to_nits(16.0, &control.spline).await,
            ),
            true
        );
        assert_eq!(
            cmp_float(
                brightness_curve_lux_to_nits(100.0, old_curve).await,
                brightness_curve_lux_to_nits(100.0, &control.spline).await,
            ),
            true
        );
        assert_eq!(
            cmp_float(
                brightness_curve_lux_to_nits(150.0, old_curve).await,
                brightness_curve_lux_to_nits(150.0, &control.spline).await,
            ),
            true
        );
        assert_eq!(
            cmp_float(
                brightness_curve_lux_to_nits(200.0, old_curve).await,
                brightness_curve_lux_to_nits(200.0, &control.spline).await,
            ),
            true
        );
        assert_eq!(
            cmp_float(
                brightness_curve_lux_to_nits(240.0, old_curve).await,
                brightness_curve_lux_to_nits(240.0, &control.spline).await,
            ),
            true
        );
        assert_eq!(
            cmp_float(
                brightness_curve_lux_to_nits(300.0, old_curve).await,
                brightness_curve_lux_to_nits(300.0, &control.spline).await,
            ),
            true
        );
        assert_eq!(
            cmp_float(
                brightness_curve_lux_to_nits(340.0, old_curve).await,
                brightness_curve_lux_to_nits(340.0, &control.spline).await,
            ),
            true
        );
    }

    #[fasync::run_singlethreaded(test)]
    async fn test_scale_new_adjustment() {
        let mut control = generate_control_struct(400.0, 0.5).await;
        let mut new_adjust = control.scale_new_adjustment(-1.0).await;
        assert_eq!(0.25, new_adjust);
        new_adjust = control.scale_new_adjustment(1.0).await;
        assert_eq!(8.0, new_adjust);
        new_adjust = control.scale_new_adjustment(0.0).await;
        assert_eq!(1.0, new_adjust);
    }

    fn assert_float_f32(expected: f32, value: f32) {
        assert!(
            (expected - value as f32).abs() < 0.00001,
            "expected {}, found {}",
            expected,
            value
        );
    }

    #[test]
    fn test_set_brightness_slowly_send_value() {
        // Need to use a TestExecutor with fake time to run past the timeouts without delay
        let mut exec = TestExecutor::new_with_fake_time();
        exec.set_fake_time(fasync::Time::from_nanos(0));

        let control = block_on(generate_control_struct(400.0, 0.5));
        let (channel_sender, mut channel_receiver) = futures::channel::mpsc::unbounded::<f32>();
        {
            let mut channel = block_on(control.current_sender_channel.lock());
            block_on(channel.add_sender_channel(channel_sender));
        }

        // This will produce 10 50ms steps of 0.002 brightness
        let future = set_brightness_slowly(
            0.4,
            0.42,
            control.backlight,
            500.millis(),
            control.current_sender_channel,
        );
        pin_mut!(future);

        for _i in 1..10 {
            assert!(exec.run_until_stalled(&mut future).is_pending());
            if let Some(deadline) = exec.wake_next_timer() {
                let deadline = deadline.into_nanos().nanos();
                assert_eq!(50, deadline.into_millis());
            } else {
                panic!("Timer has no value");
            }
        }
        // Make sure we have finished
        assert!(exec.run_until_stalled(&mut future).is_ready());

        // Check the receiver's results
        assert_float_f32(0.402, block_on(channel_receiver.next()).unwrap());
        assert_float_f32(0.404, block_on(channel_receiver.next()).unwrap());
        assert_float_f32(0.406, block_on(channel_receiver.next()).unwrap());
        assert_float_f32(0.408, block_on(channel_receiver.next()).unwrap());
        assert_float_f32(0.410, block_on(channel_receiver.next()).unwrap());
        assert_float_f32(0.412, block_on(channel_receiver.next()).unwrap());
        assert_float_f32(0.414, block_on(channel_receiver.next()).unwrap());
        assert_float_f32(0.416, block_on(channel_receiver.next()).unwrap());
        assert_float_f32(0.418, block_on(channel_receiver.next()).unwrap());
        assert_float_f32(0.420, block_on(channel_receiver.next()).unwrap());
    }

    #[test]
    fn test_set_brightness_slowly_long_timeout() {
        // Need to use a TestExecutor with fake time to run past the timeouts without delay
        let mut exec = TestExecutor::new_with_fake_time();
        exec.set_fake_time(fasync::Time::from_nanos(0));

        let control = block_on(generate_control_struct(400.0, 0.5));
        let (channel_sender, mut channel_receiver) = futures::channel::mpsc::unbounded::<f32>();
        {
            let mut channel = block_on(control.current_sender_channel.lock());
            block_on(channel.add_sender_channel(channel_sender));
        }

        // This will produce 2 approx 5sec steps of -0.00025 brightness
        let future = set_brightness_slowly(
            0.0006,
            0.0001,
            control.backlight,
            10.seconds(),
            control.current_sender_channel,
        );
        pin_mut!(future);

        for _i in 1..2 {
            assert!(exec.run_until_stalled(&mut future).is_pending());
            if let Some(deadline) = exec.wake_next_timer() {
                let deadline = deadline.into_nanos().nanos();
                assert!(deadline > 4500.millis());
                assert!(deadline < 5000.millis());
            } else {
                panic!("Timer has no value");
            }
        }
        // Make sure we have finished
        assert!(exec.run_until_stalled(&mut future).is_ready());

        // Check the receiver's results
        assert_float_f32(0.00035, block_on(channel_receiver.next()).unwrap());
        assert_float_f32(0.0001, block_on(channel_receiver.next()).unwrap());
    }

    #[fasync::run_singlethreaded(test)]
    async fn test_read_sensor_and_get_brightness_bright() {
        let BrightnessTable { points } = &*BRIGHTNESS_TABLE.lock().await;
        let brightness_table = BrightnessTable { points: points.to_vec() };
        let spline = generate_spline(brightness_table);
        let (sensor, _backlight) = set_mocks(400.0, 1.5);
        let value = read_sensor_and_get_brightness(sensor, &spline, 250.0).await;
        assert_eq!(cmp_float(1.2, value), true);
    }

    #[fasync::run_singlethreaded(test)]
    async fn test_read_sensor_and_get_brightness_low_light() {
        let BrightnessTable { points } = &*BRIGHTNESS_TABLE.lock().await;
        let brightness_table = BrightnessTable { points: points.to_vec() };
        let spline = generate_spline(brightness_table);
        let (sensor, _backlight) = set_mocks(0.0, 0.0);
        let value = read_sensor_and_get_brightness(sensor, &spline, 250.0).await;
        assert_eq!(cmp_float(0.0, value), true);
    }

    #[fasync::run_singlethreaded(test)]
    async fn test_set_brightness_is_abortable_with_auto_brightness_on() {
        let control = generate_control_struct(400.0, 0.5).await;
        let set_brightness_abort_handle = Arc::new(Mutex::new(None::<AbortHandle>));
        let (_sensor, backlight) = set_mocks(0.0, 0.0);
        let backlight = backlight.clone();
        set_brightness(
            0.04,
            set_brightness_abort_handle.clone(),
            backlight.clone(),
            control.current_sender_channel,
        )
        .await;
        // Abort the task before it really gets going
        let mut set_brightness_abort_handle = set_brightness_abort_handle.lock().await;
        if let Some(handle) = set_brightness_abort_handle.take() {
            handle.abort();
        }
        // It should not have reached the final value yet.
        // We know that set_brightness_slowly, at the bottom of the task, finishes at the correct
        // value from other tests if it has sufficient time.
        assert_ne!(cmp_float(0.04, backlight.get_brightness().await.unwrap() as f32), true);
    }

    #[fasync::run_singlethreaded(test)]
    async fn test_set_brightness_impl() {
        let control = generate_control_struct(400.0, 0.5).await;
        let (_sensor, backlight) = set_mocks(0.0, 0.0);
        let backlight_clone = backlight.clone();
        set_brightness_impl(0.3, backlight_clone, control.current_sender_channel).await;
        assert_eq!(cmp_float(0.3, backlight.get_brightness().await.unwrap() as f32), true);
    }

    #[fasync::run_singlethreaded(test)]
    async fn test_brightness_manager_fail_gracefully() {
        let control = generate_control_struct(400.0, 0.5).await;
        let (_sensor, backlight) = set_mocks_not_valid(0.0, 0.0);
        {
            let last_set_brightness = &*LAST_SET_BRIGHTNESS.lock().await;
            assert_eq!(cmp_float(*last_set_brightness, 1.0), true);
        }
        let backlight_clone = backlight.clone();
        set_brightness_impl(0.04, backlight_clone, control.current_sender_channel).await;
        let last_set_brightness = &*LAST_SET_BRIGHTNESS.lock().await;
        assert_eq!(cmp_float(*last_set_brightness, 0.04), true);
    }

    #[fasync::run_singlethreaded(test)]
    async fn test_store_brightness_table() -> Result<(), Error> {
        let mut control = generate_control_struct(400.0, 0.5).await;
        let brightness_table = BrightnessTable {
            points: vec![
                BrightnessPoint { ambient_lux: 10., display_nits: 50. },
                BrightnessPoint { ambient_lux: 30., display_nits: 50. },
                BrightnessPoint { ambient_lux: 60., display_nits: 50. },
            ],
        };
        control.store_brightness_table(&brightness_table, "/data/test_brightness_file")?;
        let file = fs::File::open("/data/test_brightness_file")?;
        let data = serde_json::from_reader(io::BufReader::new(file))?;
        let BrightnessTable { points: read_points } = data;
        let BrightnessTable { points: write_points } = brightness_table;
        let iter = read_points.iter().zip(write_points.iter());
        for point_tuple in iter {
            let (read_point, write_point) = point_tuple;
            assert_eq!(cmp_float(read_point.ambient_lux, write_point.ambient_lux), true);
            assert_eq!(cmp_float(read_point.display_nits, write_point.display_nits), true);
        }
        Ok(())
    }

    #[fasync::run_singlethreaded(test)]
    async fn test_read_brightness_table_file_empty_file() {
        fs::File::create("/data/empty_file").unwrap();
        let result = read_brightness_table_file("/data/empty_file");
        assert_eq!(true, result.is_err());
    }

    #[fasync::run_singlethreaded(test)]
    async fn test_read_brightness_table_file_missing_file() {
        assert_eq!(false, Path::new("/data/nonexistent_file").exists());
        let result = read_brightness_table_file("/data/nonexistent_file");
        assert_eq!(true, result.is_err());
    }

    #[fasync::run_singlethreaded(test)]
    async fn test_read_brightness_table_file_invalid_data() {
        let file = fs::File::create("/data/invalid_brightness_file").unwrap();
        serde_json::to_writer(io::BufWriter::new(file), &1.0).unwrap();
        let result = read_brightness_table_file("/data/invalid_brightness_file");
        assert_eq!(true, result.is_err());
    }

    #[fasync::run_singlethreaded(test)]
    async fn test_set_manual_brightness_smooth_with_duration_got_set() {
        let mut control = generate_control_struct(400.0, 0.5).await;
        control.set_manual_brightness_smooth(0.6, Duration::from_nanos(4000000000)).await;
        let duration = *BRIGHTNESS_CHANGE_DURATION.lock().await;
        assert_eq!(4000, duration.into_millis());
    }

    #[fasync::run_singlethreaded(test)]
    async fn test_set_manual_brightness_set_duration() {
        let mut control = generate_control_struct(400.0, 0.5).await;
        control.set_manual_brightness(0.6).await;
        let duration = *BRIGHTNESS_CHANGE_DURATION.lock().await;
        assert_eq!(250, duration.into_millis());
    }

    #[test]
    fn test_set_manual_brightness_updates_brightness() {
        let mut exec = fasync::TestExecutor::new();

        let func_fut1 = generate_control_struct(400.0, 0.5);
        futures::pin_mut!(func_fut1);
        let mut control = exec.run_singlethreaded(&mut func_fut1);
        {
            let func_fut2 = control.set_manual_brightness_smooth(0.6, Duration::from_nanos(4000));
            futures::pin_mut!(func_fut2);
            exec.run_singlethreaded(&mut func_fut2);
        }
        let _ = exec.run_until_stalled(&mut future::pending::<()>());
        let backlight = control.backlight;
        let func_fut3 = backlight.get_brightness();
        futures::pin_mut!(func_fut3);
        let value = exec.run_singlethreaded(&mut func_fut3);
        assert_eq!(cmp_float(0.6, value.unwrap() as f32), true);
    }

    #[test]
    fn test_set_manual_brightness_updates_brightness_small_change() {
        const TARGET_BRIGHTNESS: f32 = 0.0006;
        const ORIGINAL_BRIGHTNESS: f32 = 0.001;
        assert!((TARGET_BRIGHTNESS - ORIGINAL_BRIGHTNESS).abs() > BRIGHTNESS_MINIMUM_CHANGE);

        let mut exec = fasync::TestExecutor::new();
        let func_fut1 = generate_control_struct(400.0, ORIGINAL_BRIGHTNESS as f64);
        futures::pin_mut!(func_fut1);
        let mut control = exec.run_singlethreaded(&mut func_fut1);
        {
            let func_fut2 =
                control.set_manual_brightness_smooth(0.0006, Duration::from_nanos(4000));
            futures::pin_mut!(func_fut2);
            exec.run_singlethreaded(&mut func_fut2);
        }
        let _ = exec.run_until_stalled(&mut future::pending::<()>());
        let backlight = control.backlight;
        let func_fut3 = backlight.get_brightness();
        futures::pin_mut!(func_fut3);
        let value = exec.run_singlethreaded(&mut func_fut3);
        let brightness_value = value.unwrap() as f32;
        assert_eq!(TARGET_BRIGHTNESS, brightness_value);
    }

    #[fasync::run_singlethreaded(test)]
    async fn test_get_max_absolute_brightness() {
        let mut control = generate_control_struct(400.0, 0.5).await;
        let max_brightness = control.get_max_absolute_brightness().await;
        assert_eq!(250.0, max_brightness.unwrap());
    }
}
