// 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 crate::backlight::BacklightControl;
use crate::sender_channel::SenderChannel;
use crate::sensor::SensorControl;
use async_trait::async_trait;
use std::cmp;
use std::sync::Arc;

use anyhow::{format_err, Error};
use fidl_fuchsia_ui_brightness::{
    ControlRequest as BrightnessControlRequest, ControlWatchAutoBrightnessAdjustmentResponder,
    ControlWatchAutoBrightnessResponder, ControlWatchCurrentBrightnessResponder,
};
use fuchsia_async::{self as fasync, DurationExt};
use fuchsia_syslog::{self, fx_log_err, fx_log_info};
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 serde_json;
use splines::{Interpolation, Key, Spline};
use std::{fs, io};
use watch_handler::{Sender, WatchHandler};

// 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;

// Gives pleasing, smooth brightness ramp up and down
const BRIGHTNESS_STEP_SIZE: f32 = 0.001;
// Time between brightness steps. Any longer than this and the screen noticeably shimmers
const MAX_BRIGHTNESS_STEP_TIME_MS: i64 = 100;
// Brightness changes should take this time unless we exceed the MAX_BRIGHTNESS_STEP_TIME
const BRIGHTNESS_CHANGE_DURATION_MS: i64 = 2000;

#[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) {
            fx_log_err!("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) {
            fx_log_err!("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) {
            fx_log_err!("Failed to reply to WatchAutoBrightnessAdjustment: {}", e);
        }
    }
}

pub struct Control {
    sensor: Arc<Mutex<dyn SensorControl>>,
    backlight: Arc<Mutex<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<Mutex<dyn BacklightControl>>,
        current_sender_channel: Arc<Mutex<SenderChannel<f32>>>,
        auto_sender_channel: Arc<Mutex<SenderChannel<bool>>>,
        adjustment_sender_channel: Arc<Mutex<SenderChannel<f32>>>,
    ) -> Control {
        fx_log_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| {
                fx_log_err!("Error occurred when trying 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 mut result = Control {
            backlight,
            sensor,
            set_brightness_abort_handle,
            auto_brightness_abort_handle,
            spline,
            current_sender_channel,
            auto_sender_channel,
            adjustment_sender_channel,
        };
        // Startup auto-brightness loop
        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) => fx_log_err!("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,
                control_handle: _,
            } => {
                self.set_manual_brightness_smooth(value, duration).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) => fx_log_err!("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) => fx_log_info!("Brightness table is valid and set"),
                    Err(e) => {
                        // TODO(lingxueluo): Close the connection if brightness table not valid.
                        fx_log_err!("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) => fx_log_err!("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(&mut Ok(value)) {
                            fx_log_err!("Failed to reply to GetMaxAbsoluteBrightness: {}", e);
                        }
                    }
                    Err(e) => {
                        fx_log_err!("Failed to get max absolute brightness: {}", e);

                        if let Err(e) = responder.send(&mut Err(ZX_ERR_NOT_SUPPORTED)) {
                            fx_log_err!("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<Mutex<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() {
            fx_log_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 backlight = backlight.lock().await;
                        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) {
        if let Some(handle) = self.auto_brightness_abort_handle.take() {
            fx_log_info!("Auto-brightness off, brightness set to {}", value);
            handle.abort();
        }
        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 set_manual_brightness_smooth(&mut self, value: f32, duration: i64) {
        let duration_nanos = Duration::from_nanos(duration);
        *BRIGHTNESS_CHANGE_DURATION.lock().await = duration_nanos.into_millis().millis();
        let value = num_traits::clamp(value, 0.0, 1.0);
        self.set_manual_brightness(value).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) {
        fx_log_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) => fx_log_info!("Stored successfully"),
            Err(e) => fx_log_info!("Didn't store successfully due to error {}", e),
        }
    }

    fn store_brightness_table(
        &mut self,
        table: &BrightnessTable,
        file_path: &str,
    ) -> Result<(), Error> {
        fx_log_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() {
            fx_log_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 {
                fx_log_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 {
                fx_log_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> {
        let backlight = self.backlight.lock().await;
        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<Mutex<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<Mutex<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
/// Runs the main auto-brightness code.
/// This task monitors its running boolean and terminates if it goes false.

async fn get_current_brightness(backlight: Arc<Mutex<dyn BacklightControl>>) -> f32 {
    let backlight = backlight.lock().await;
    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 {
                fx_log_err!("Failed to get backlight: {}. assuming 1.0", e);
                *GET_BRIGHTNESS_FAILED_FIRST.lock().await = false;
            }
            *LAST_SET_BRIGHTNESS.lock().await
        }
    }
}

async fn read_sensor_and_get_brightness(
    sensor: Arc<Mutex<dyn SensorControl>>,
    spline: &Spline<f32, f32>,
    max_brightness: f64,
) -> f32 {
    let lux = {
        // 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();
        let report = fut.await.expect("Could not read from the sensor");
        report.illuminance
    };
    brightness_curve_lux_to_nits(lux, spline).await / max_brightness as f32
}

async fn brightness_curve_lux_to_nits(lux: u16, 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<Mutex<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_STEP_SIZE {
        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);
    } else if (current_value - value).abs() > BRIGHTNESS_MINIMUM_CHANGE {
        set_brightness_impl(value, backlight, current_sender_channel).await;
    }
}

async fn set_brightness_impl(
    value: f32,
    backlight: Arc<Mutex<dyn BacklightControl>>,
    current_sender_channel: Arc<Mutex<SenderChannel<f32>>>,
) {
    let current_value = get_current_brightness(backlight.clone()).await;
    let mut backlight = backlight.lock().await;
    let set_brightness = |value| {
        backlight
            .set_brightness(value)
            .unwrap_or_else(|e| fx_log_err!("Failed to set backlight: {}", e))
    };
    let current_sender_channel = current_sender_channel.clone();
    set_brightness_slowly(
        current_value,
        value,
        set_brightness,
        *BRIGHTNESS_CHANGE_DURATION.lock().await,
        current_sender_channel,
    )
    .await;
}

/// Change the brightness of the screen slowly to `nits` nits. We don't want to change the screen
/// suddenly so we smooth the transition by doing it in a series of small steps.
/// The time per step can be changed if needed e.g. to fade up slowly and down quickly.
/// When testing we set time_per_step to zero.
async fn set_brightness_slowly(
    current_value: f32,
    to_value: f32,
    mut set_brightness: impl FnMut(f64),
    duration: Duration,
    current_sender_channel: Arc<Mutex<SenderChannel<f32>>>,
) {
    let mut current_value = current_value;
    let to_value = num_traits::clamp(to_value, 0.0, 1.0);
    assert!(to_value <= 1.0);
    assert!(current_value <= 1.0);
    let current_sender_channel = current_sender_channel.clone();
    let difference = to_value - current_value;
    let steps = (difference.abs() / BRIGHTNESS_STEP_SIZE) as u16;
    if steps > 0 {
        let time_per_step = cmp::min(duration / steps, MAX_BRIGHTNESS_STEP_TIME_MS.millis());
        let step_size = difference / steps as f32;
        for _i in 0..steps {
            let current_sender_channel = current_sender_channel.clone();
            current_value = current_value + step_size;
            set_brightness(current_value as f64);
            current_sender_channel.lock().await.send_value(current_value);
            if time_per_step.into_millis() > 0 {
                fuchsia_async::Timer::new(time_per_step.after_now()).await;
            }
        }
    }
    // Make sure we get to the correct value, there may be rounding errors
    set_brightness(to_value as f64);
    current_sender_channel.lock().await.send_value(current_value);
    *LAST_SET_BRIGHTNESS.lock().await = to_value;
}

#[cfg(test)]
mod tests {
    use super::*;

    use crate::sender_channel::SenderChannel;
    use crate::sensor::AmbientLightInputRpt;
    use anyhow::{format_err, Error};
    use async_trait::async_trait;
    use std::path::Path;

    struct MockSensor {
        illuminence: u16,
    }

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

    struct MockBacklight {
        valid_backlight: bool,
        value: f64,
        max_brightness: f64,
    }

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

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

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

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

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

    async fn generate_control_struct(sensor: u16, 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, &spline).await), true);
        assert_eq!(cmp_float(0.333, brightness_curve_lux_to_nits(1, &spline).await), true);
        assert_eq!(cmp_float(0.666, brightness_curve_lux_to_nits(2, &spline).await), true);
        assert_eq!(cmp_float(4.67, brightness_curve_lux_to_nits(15, &spline).await), true);
        assert_eq!(cmp_float(4.94, brightness_curve_lux_to_nits(16, &spline).await), true);
        assert_eq!(cmp_float(32.78, brightness_curve_lux_to_nits(100, &spline).await), true);
        assert_eq!(cmp_float(36.82, brightness_curve_lux_to_nits(150, &spline).await), true);
        assert_eq!(cmp_float(68.63, brightness_curve_lux_to_nits(200, &spline).await), true);
        assert_eq!(cmp_float(111.87, brightness_curve_lux_to_nits(240, &spline).await), true);
        assert_eq!(cmp_float(162.96, brightness_curve_lux_to_nits(300, &spline).await), true);
        assert_eq!(cmp_float(300., brightness_curve_lux_to_nits(340, &spline).await), true);
    }

    #[fasync::run_singlethreaded(test)]
    async fn test_brightness_table_valid() {
        let mut control = generate_control_struct(400, 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, &control.spline).await), true);
        assert_eq!(cmp_float(50.0, brightness_curve_lux_to_nits(1, &control.spline).await), true);
        assert_eq!(cmp_float(50.0, brightness_curve_lux_to_nits(2, &control.spline).await), true);
        assert_eq!(cmp_float(50.0, brightness_curve_lux_to_nits(15, &control.spline).await), true);
        assert_eq!(cmp_float(50.0, brightness_curve_lux_to_nits(16, &control.spline).await), true);
        assert_eq!(cmp_float(50.0, brightness_curve_lux_to_nits(100, &control.spline).await), true);
        assert_eq!(cmp_float(50.0, brightness_curve_lux_to_nits(150, &control.spline).await), true);
        assert_eq!(cmp_float(50.0, brightness_curve_lux_to_nits(200, &control.spline).await), true);
        assert_eq!(cmp_float(50.0, brightness_curve_lux_to_nits(240, &control.spline).await), true);
        assert_eq!(cmp_float(50.0, brightness_curve_lux_to_nits(300, &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.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.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.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, old_curve).await,
                brightness_curve_lux_to_nits(0, &control.spline).await,
            ),
            true
        );
        assert_eq!(
            cmp_float(
                brightness_curve_lux_to_nits(1, old_curve).await,
                brightness_curve_lux_to_nits(1, &control.spline).await,
            ),
            true
        );
        assert_eq!(
            cmp_float(
                brightness_curve_lux_to_nits(2, old_curve).await,
                brightness_curve_lux_to_nits(2, &control.spline).await,
            ),
            true
        );
        assert_eq!(
            cmp_float(
                brightness_curve_lux_to_nits(15, old_curve).await,
                brightness_curve_lux_to_nits(15, &control.spline).await,
            ),
            true
        );
        assert_eq!(
            cmp_float(
                brightness_curve_lux_to_nits(16, old_curve).await,
                brightness_curve_lux_to_nits(16, &control.spline).await,
            ),
            true
        );
        assert_eq!(
            cmp_float(
                brightness_curve_lux_to_nits(100, old_curve).await,
                brightness_curve_lux_to_nits(100, &control.spline).await,
            ),
            true
        );
        assert_eq!(
            cmp_float(
                brightness_curve_lux_to_nits(150, old_curve).await,
                brightness_curve_lux_to_nits(150, &control.spline).await,
            ),
            true
        );
        assert_eq!(
            cmp_float(
                brightness_curve_lux_to_nits(200, old_curve).await,
                brightness_curve_lux_to_nits(200, &control.spline).await,
            ),
            true
        );
        assert_eq!(
            cmp_float(
                brightness_curve_lux_to_nits(240, old_curve).await,
                brightness_curve_lux_to_nits(240, &control.spline).await,
            ),
            true
        );
        assert_eq!(
            cmp_float(
                brightness_curve_lux_to_nits(300, old_curve).await,
                brightness_curve_lux_to_nits(300, &control.spline).await,
            ),
            true
        );
        assert_eq!(
            cmp_float(
                brightness_curve_lux_to_nits(340, old_curve).await,
                brightness_curve_lux_to_nits(340, &control.spline).await,
            ),
            true
        );
    }

    #[fasync::run_singlethreaded(test)]
    async fn test_scale_new_adjustment() {
        let mut control = generate_control_struct(400, 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);
    }

    #[fasync::run_singlethreaded(test)]
    async fn test_set_brightness_slowly_send_value() {
        let control = generate_control_struct(400, 0.5).await;
        let (channel_sender, mut channel_receiver) = futures::channel::mpsc::unbounded::<f32>();
        control.current_sender_channel.lock().await.add_sender_channel(channel_sender).await;
        let set_brightness = |_| {};
        set_brightness_slowly(0.4, 0.5, set_brightness, 0.millis(), control.current_sender_channel)
            .await;

        assert_eq!(cmp_float(0.4, channel_receiver.next().await.unwrap()), true);
        assert_eq!(cmp_float(0.4, channel_receiver.next().await.unwrap()), true);
        for _i in 0..13 {
            channel_receiver.next().await;
        }
        assert_eq!(cmp_float(0.41, channel_receiver.next().await.unwrap()), true);
        for _i in 0..4 {
            channel_receiver.next().await;
        }
        assert_eq!(cmp_float(0.42, channel_receiver.next().await.unwrap()), true);
        for _i in 0..19 {
            channel_receiver.next().await;
        }
        assert_eq!(cmp_float(0.44, channel_receiver.next().await.unwrap()), true);
        for _i in 0..58 {
            channel_receiver.next().await;
        }
        assert_eq!(cmp_float(0.50, channel_receiver.next().await.unwrap()), true);
    }

    #[fasync::run_singlethreaded(test)]
    async fn test_set_brightness_slowly_in_range() {
        let control = generate_control_struct(400, 0.5).await;
        let mut result = Vec::new();
        let set_brightness = |nits| {
            result.push(nits as f32);
        };
        set_brightness_slowly(0.4, 0.8, set_brightness, 0.millis(), control.current_sender_channel)
            .await;
        assert_eq!(401, result.len(), "wrong length");
        assert_eq!(cmp_float(0.4, result[0]), true);
        assert_eq!(cmp_float(0.4, result[1]), true);
        assert_eq!(cmp_float(0.41, result[15]), true);
        assert_eq!(cmp_float(0.42, result[20]), true);
        assert_eq!(cmp_float(0.44, result[40]), true);
        assert_eq!(cmp_float(0.50, result[100]), true);
        assert_eq!(cmp_float(0.55, result[150]), true);
        assert_eq!(cmp_float(0.60, result[200]), true);
        assert_eq!(cmp_float(0.65, result[250]), true);
        assert_eq!(cmp_float(0.70, result[300]), true);
        assert_eq!(cmp_float(0.75, result[350]), true);
        assert_eq!(cmp_float(0.80, result[399]), true);
    }

    #[fasync::run_singlethreaded(test)]
    async fn test_set_brightness_slowly_min() {
        let control = generate_control_struct(400, 0.5).await;
        let mut result = Vec::new();
        let set_brightness = |nits| {
            result.push(nits as f32);
        };
        set_brightness_slowly(0.4, 0.0, set_brightness, 0.millis(), control.current_sender_channel)
            .await;
        assert_eq!(401, result.len(), "wrong length");
        assert_eq!(cmp_float(0.39, result[0]), true);
        assert_eq!(cmp_float(0.39, result[1]), true);
        assert_eq!(cmp_float(0.38, result[15]), true);
        assert_eq!(cmp_float(0.38, result[20]), true);
        assert_eq!(cmp_float(0.35, result[40]), true);
        assert_eq!(cmp_float(0.30, result[100]), true);
        assert_eq!(cmp_float(0.25, result[150]), true);
        assert_eq!(cmp_float(0.20, result[200]), true);
        assert_eq!(cmp_float(0.15, result[250]), true);
        assert_eq!(cmp_float(0.10, result[300]), true);
        assert_eq!(cmp_float(0.05, result[350]), true);
        assert_eq!(cmp_float(0.00, result[399]), true);
    }

    #[fasync::run_singlethreaded(test)]
    async fn test_set_brightness_slowly_max() {
        let control = generate_control_struct(400, 0.5).await;
        let mut result = Vec::new();
        let set_brightness = |nits| {
            result.push(nits as f32);
        };
        set_brightness_slowly(0.9, 1.2, set_brightness, 0.millis(), control.current_sender_channel)
            .await;
        assert_eq!(101, result.len(), "wrong length");
        assert_eq!(cmp_float(0.90, result[0]), true);
        assert_eq!(cmp_float(0.90, result[1]), true);
        assert_eq!(cmp_float(0.91, result[10]), true);
        assert_eq!(cmp_float(0.92, result[20]), true);
        assert_eq!(cmp_float(0.93, result[30]), true);
        assert_eq!(cmp_float(0.94, result[40]), true);
        assert_eq!(cmp_float(0.95, result[50]), true);
        assert_eq!(cmp_float(0.96, result[60]), true);
        assert_eq!(cmp_float(0.97, result[70]), true);
        assert_eq!(cmp_float(0.98, result[80]), true);
        assert_eq!(cmp_float(0.99, result[90]), true);
        assert_eq!(cmp_float(1.00, result[100]), true);
    }

    #[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, 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);
        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.5).await;
        let set_brightness_abort_handle = Arc::new(Mutex::new(None::<AbortHandle>));
        let (_sensor, backlight) = set_mocks(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
        // nits value from other tests if it has sufficient time.
        let backlight = backlight.lock().await;

        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.5).await;
        let (_sensor, backlight) = set_mocks(0, 0.0);
        let backlight_clone = backlight.clone();
        set_brightness_impl(0.3, backlight_clone, control.current_sender_channel).await;
        let backlight = backlight.lock().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.5).await;
        let (_sensor, backlight) = set_mocks_not_valid(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.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.5).await;
        control.set_manual_brightness_smooth(0.6, 4000000000).await;
        let duration = *BRIGHTNESS_CHANGE_DURATION.lock().await;
        assert_eq!(4000, duration.into_millis());
    }

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

        let func_fut1 = generate_control_struct(400, 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, 4000);
            futures::pin_mut!(func_fut2);
            exec.run_singlethreaded(&mut func_fut2);
        }
        let _ = exec.run_until_stalled(&mut future::pending::<()>());
        let func_fut3 = control.backlight.lock();
        futures::pin_mut!(func_fut3);
        let backlight = exec.run_singlethreaded(&mut func_fut3);
        let func_fut4 = backlight.get_brightness();
        futures::pin_mut!(func_fut4);
        let value = exec.run_singlethreaded(&mut func_fut4);
        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_STEP_SIZE);
        assert!((TARGET_BRIGHTNESS - ORIGINAL_BRIGHTNESS).abs() > BRIGHTNESS_MINIMUM_CHANGE);

        let mut exec = fasync::Executor::new().unwrap();
        let func_fut1 = generate_control_struct(400, 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, 4000);
            futures::pin_mut!(func_fut2);
            exec.run_singlethreaded(&mut func_fut2);
        }
        let _ = exec.run_until_stalled(&mut future::pending::<()>());
        let func_fut3 = control.backlight.lock();
        futures::pin_mut!(func_fut3);
        let backlight = exec.run_singlethreaded(&mut func_fut3);
        let func_fut4 = backlight.get_brightness();
        futures::pin_mut!(func_fut4);
        let value = exec.run_singlethreaded(&mut func_fut4);
        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.5).await;
        let max_brightness = control.get_max_absolute_brightness().await;
        assert_eq!(250.0, max_brightness.unwrap());
    }
}
