// 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::battery_manager::BatterySimulationStateObserver,
    anyhow::{format_err, Error},
    fidl_fuchsia_power as fpower, fidl_fuchsia_power_test as spower,
    futures::lock::Mutex,
    std::sync::{Arc, Weak},
};

// SimulatedBatteryInfoSource is another source of BatteryInfo for the
// BatteryManager. This BatteryInfo is modified through FIDL calls
pub(crate) struct SimulatedBatteryInfoSource {
    battery_info: Arc<Mutex<fpower::BatteryInfo>>,
    observer: Weak<dyn BatterySimulationStateObserver>,
}

impl SimulatedBatteryInfoSource {
    pub fn new(
        battery_info: fpower::BatteryInfo,
        observer: Weak<dyn BatterySimulationStateObserver>,
    ) -> Self {
        Self { battery_info: Arc::new(Mutex::new(battery_info)), observer }
    }

    pub async fn get_battery_info_copy(&self) -> fpower::BatteryInfo {
        let battery_info = self.battery_info.lock().await;
        (*battery_info).clone()
    }

    async fn set_battery_percentage(&self, level_percent: f32) -> Result<(), Error> {
        let mut battery_info = self.battery_info.lock().await;
        battery_info.level_percent = Some(level_percent);
        drop(battery_info);
        self.notify_battery_info_changed().await?;
        Ok(())
    }

    async fn set_charge_source(&self, charge_source: fpower::ChargeSource) -> Result<(), Error> {
        let mut battery_info = self.battery_info.lock().await;
        battery_info.charge_source = Some(charge_source);
        drop(battery_info);
        self.notify_battery_info_changed().await?;
        Ok(())
    }

    async fn set_level_status(&self, level_status: fpower::LevelStatus) -> Result<(), Error> {
        let mut battery_info = self.battery_info.lock().await;
        battery_info.level_status = Some(level_status);
        drop(battery_info);
        self.notify_battery_info_changed().await?;
        Ok(())
    }

    async fn set_charge_status(&self, charge_status: fpower::ChargeStatus) -> Result<(), Error> {
        let mut battery_info = self.battery_info.lock().await;
        battery_info.charge_status = Some(charge_status);
        drop(battery_info);
        self.notify_battery_info_changed().await?;
        Ok(())
    }

    async fn set_battery_status(&self, battery_status: fpower::BatteryStatus) -> Result<(), Error> {
        let mut battery_info = self.battery_info.lock().await;
        battery_info.status = Some(battery_status);
        drop(battery_info);
        self.notify_battery_info_changed().await?;
        Ok(())
    }

    async fn set_time_remaining(&self, time: i64) -> Result<(), Error> {
        let mut battery_info = self.battery_info.lock().await;
        if battery_info.charge_status.unwrap() == fpower::ChargeStatus::Charging {
            battery_info.time_remaining = Some(fpower::TimeRemaining::FullCharge(time));
        } else if battery_info.charge_status.unwrap() == fpower::ChargeStatus::Discharging
            || battery_info.charge_status.unwrap() == fpower::ChargeStatus::NotCharging
        {
            battery_info.time_remaining = Some(fpower::TimeRemaining::BatteryLife(time));
        } else {
            battery_info.time_remaining = Some(fpower::TimeRemaining::Indeterminate(time));
        }
        drop(battery_info);
        self.notify_battery_info_changed().await?;
        Ok(())
    }

    // Updates the simulated_battery_info in BatteryManager
    async fn notify_battery_info_changed(&self) -> Result<(), Error> {
        let observer = self.observer.upgrade().ok_or(format_err!("Observer not found"))?;
        observer.update_simulated_battery_info((*self.battery_info.lock().await).clone());
        Ok(())
    }

    // Updates BatteryManager as well as store the most up to date BatteryInfo
    pub async fn update_simulation(
        &self,
        is_simulating: bool,
        real_battery_info: fpower::BatteryInfo,
    ) -> Result<(), Error> {
        let observer = self.observer.upgrade().ok_or(format_err!("Observer not found"))?;
        observer.update_simulation(is_simulating);

        // Copy real_battery_info
        let mut battery_info = self.battery_info.lock().await;
        *battery_info = real_battery_info;
        drop(battery_info);
        self.notify_battery_info_changed().await?;
        Ok(())
    }

    pub(crate) async fn handle_request(
        &self,
        request: spower::BatterySimulatorRequest,
    ) -> Result<(), Error> {
        async move {
            match request {
                spower::BatterySimulatorRequest::GetBatteryInfo { responder, .. } => {
                    let info = self.get_battery_info_copy();
                    responder.send(info.await).map_err(|e| format_err!("{}", e))?;
                }
                spower::BatterySimulatorRequest::SetChargeStatus { charge_status, .. } => {
                    self.set_charge_status(charge_status).await?;
                }
                spower::BatterySimulatorRequest::SetBatteryStatus { battery_status, .. } => {
                    self.set_battery_status(battery_status).await?;
                }
                spower::BatterySimulatorRequest::SetChargeSource { charge_source, .. } => {
                    self.set_charge_source(charge_source).await?;
                }
                spower::BatterySimulatorRequest::SetBatteryPercentage { percent, .. } => {
                    self.set_battery_percentage(percent).await?;
                }
                spower::BatterySimulatorRequest::SetLevelStatus { level_status, .. } => {
                    self.set_level_status(level_status).await?;
                }
                spower::BatterySimulatorRequest::SetTimeRemaining { duration, .. } => {
                    self.set_time_remaining(duration).await?;
                }
                spower::BatterySimulatorRequest::DisconnectRealBattery { .. } => {
                    Err(format_err!("Unexpected Disconnect request called"))?
                }
                spower::BatterySimulatorRequest::ReconnectRealBattery { .. } => {
                    Err(format_err!("Unexpected  Reconnect request called"))?
                }
                spower::BatterySimulatorRequest::IsSimulating { responder: _, .. } => {
                    Err(format_err!("Unexpected Simulating requested called"))?
                }
            }
            Ok::<(), Error>(())
        }
        .await?;

        Ok(())
    }
}

// TODO(rminocha): investigate ways to make unit tests linear
#[cfg(test)]
mod tests {
    use super::*;
    use crate::battery_manager::BatteryManager;
    use fidl::endpoints::create_request_stream;
    use fidl_fuchsia_power as fpower;
    use fuchsia_async::futures::TryStreamExt;
    use futures::future::*;

    #[fuchsia_async::run_until_stalled(test)]
    async fn test_observer_relationship() {
        let (watcher_client_end, mut stream) =
            create_request_stream::<fpower::BatteryInfoWatcherMarker>().unwrap();
        let watcher = watcher_client_end.into_proxy().unwrap();

        let battery_manager = Arc::new(BatteryManager::new());
        battery_manager.add_watcher(watcher).await;

        let mut battery_info: fpower::BatteryInfo = battery_manager.get_battery_info_copy();
        battery_info.level_percent = Some(50.0);

        let simulated_battery_info_source = SimulatedBatteryInfoSource::new(
            battery_manager.get_battery_info_copy(),
            Arc::downgrade(&battery_manager) as Weak<dyn BatterySimulationStateObserver>,
        );

        let serve_fut = async move {
            let request = stream.try_next().await.unwrap();
            if let Some(fpower::BatteryInfoWatcherRequest::OnChangeBatteryInfo {
                info,
                responder,
            }) = request
            {
                let level = info.level_percent.unwrap().round() as u8;
                assert_eq!(level, 50);
                responder.send().unwrap();
            } else {
                panic!("Unexpected message received");
            };

            let request = stream.try_next().await.unwrap();
            if let Some(fpower::BatteryInfoWatcherRequest::OnChangeBatteryInfo {
                info,
                responder,
            }) = request
            {
                let level = info.level_percent.unwrap().round() as u8;
                assert_eq!(level, 60);
                responder.send().unwrap();
            } else {
                panic!("Unexpected message received");
            };
        };

        let request_fut = async move {
            // Update_simulation requires a battery_info since that holds the updated simulated
            // battery info object.
            let res =
                simulated_battery_info_source.update_simulation(true, battery_info.clone()).await;
            assert!(!res.is_err(), "Update simulation failed");
            battery_info.level_percent = Some(60.0);
            let res =
                simulated_battery_info_source.update_simulation(true, battery_info.clone()).await;
            assert!(!res.is_err(), "Update simulation failed");
        };

        join(serve_fut, request_fut).await;
    }
}
