// Copyright 2018 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.

#![feature(async_await, await_macro, futures_api)]
#![deny(warnings)]

use failure::{Error, ResultExt};
use fidl::endpoints::{RequestStream, ServiceMarker};
use fidl_fuchsia_power::{BatteryStatus, PowerManagerMarker, PowerManagerRequest,
                         PowerManagerRequestStream, PowerManagerWatcherProxy,
                         Status as power_status};
use fuchsia_app::server::ServicesServer;
use fuchsia_async as fasync;
use fuchsia_syslog::{self as syslog, fx_log_err, fx_log_info, fx_vlog};
use fuchsia_vfs_watcher as vfs_watcher;
use fuchsia_zircon as zx;
use futures::prelude::*;
use parking_lot::Mutex;
use std::fs::File;
use std::path::PathBuf;
use std::sync::Arc;

mod power;

static POWER_DEVICE: &str = "/dev/class/power";

// Time to sleep between status update in seconds.
static SLEEP_TIME: i64 = 180;

struct BatteryStatusHelper {
    battery_status: BatteryStatus,
    watchers: Vec<PowerManagerWatcherProxy>,
}

#[inline]
fn get_current_time() -> i64 {
    let t = zx::Time::get(zx::ClockId::UTC);
    (t.nanos() / 1000) as i64
}

#[derive(Debug)]
enum WatchSuccess {
    Completed,
    BatteryAlreadyFound,
    AdapterAlreadyFound,
}

impl BatteryStatusHelper {
    pub fn new() -> BatteryStatusHelper {
        BatteryStatusHelper {
            battery_status: BatteryStatus {
                status: power_status::NotAvailable,
                battery_present: false,
                charging: false,
                discharging: false,
                critical: false,
                power_adapter_online: false,
                timestamp: get_current_time(),
                level: 0.0,
                remaining_battery_life: 0.0,
            },
            watchers: Vec::new(),
        }
    }

    // Adds and calls watcher
    fn add_watcher(&mut self, watcher: PowerManagerWatcherProxy) {
        match watcher.on_change_battery_status(&mut self.battery_status) {
            Ok(_) => self.watchers.push(watcher),
            Err(e) => fx_log_err!("did not add watcher: {:?}", e),
        }
    }

    fn run_watchers(&mut self) {
        let mut bs = &mut self.battery_status;
        self.watchers.retain(|w| {
            if let Err(e) = w.on_change_battery_status(&mut bs) {
                match e {
                    fidl::Error::ClientRead(zx::Status::PEER_CLOSED)
                    | fidl::Error::ClientWrite(zx::Status::PEER_CLOSED) => return false,
                    e => {
                        fx_log_err!("calling watcher: {:?}", e);
                        return true;
                    }
                }
            }
            return true;
        });
    }

    fn update_battery_status(
        &mut self, power_info: power::ioctl_power_get_info_t,
        battery_info: Option<power::ioctl_power_get_battery_info_t>,
    ) {
        let now = get_current_time();
        let old_battery_status = self.get_battery_status_copy();
        if let Some(bi) = battery_info {
            self.battery_status.battery_present = power_info.state & power::POWER_STATE_ONLINE != 0;
            self.battery_status.charging = power_info.state & power::POWER_STATE_CHARGING != 0;
            self.battery_status.discharging =
                power_info.state & power::POWER_STATE_DISCHARGING != 0;
            self.battery_status.critical = power_info.state & power::POWER_STATE_CRITICAL != 0;
            if self.battery_status.battery_present {
                self.battery_status.level =
                    (bi.remaining_capacity * 100) as f32 / bi.last_full_capacity as f32;
                if bi.present_rate < 0 {
                    self.battery_status.remaining_battery_life =
                        bi.remaining_capacity as f32 / (bi.present_rate * -1) as f32;
                } else {
                    self.battery_status.remaining_battery_life = -1.0;
                }
            }
        } else {
            self.battery_status.power_adapter_online = power_info.state == 0;
        }

        self.battery_status.status = power_status::Ok;
        fx_vlog!(1, "{:?}", self.battery_status);
        if old_battery_status != self.battery_status {
            self.battery_status.timestamp = now;
            self.run_watchers();
        }
    }

    // Updates the status
    fn update_status(&mut self, file: &File) -> Result<(), failure::Error> {
        let power_info = power::get_power_info(file).context("getting power_info")?;
        let mut battery_info: Option<power::ioctl_power_get_battery_info_t> = None;
        if power_info.power_type == power::POWER_TYPE_BATTERY {
            battery_info = Some(power::get_battery_info(file).context("getting battery_info")?);
        }
        self.update_battery_status(power_info, battery_info);
        Ok(())
    }

    fn get_battery_status_copy(&self) -> BatteryStatus {
        return BatteryStatus {
            ..self.battery_status
        };
    }
}

struct PowerManagerServer {
    battery_status_helper: Arc<Mutex<BatteryStatusHelper>>,
}

fn process_watch_event(
    filepath: &PathBuf, bsh: Arc<Mutex<BatteryStatusHelper>>, battery_device_found: &mut bool,
    adapter_device_found: &mut bool,
) -> Result<WatchSuccess, failure::Error> {
    let file = File::open(&filepath)?;
    let powerbuffer = power::get_power_info(&file).context("getting power_info")?;

    if powerbuffer.power_type == power::POWER_TYPE_BATTERY && *battery_device_found {
        return Ok(WatchSuccess::BatteryAlreadyFound);
    } else if powerbuffer.power_type == power::POWER_TYPE_AC && *adapter_device_found {
        return Ok(WatchSuccess::AdapterAlreadyFound);
    }
    let bsh2 = bsh.clone();
    power::add_listener(&file, move |file: &File| {
        let mut bsh2 = bsh2.lock();
        if let Err(e) = bsh2.update_status(&file) {
            fx_log_err!("{}", e);
        }
    }).context("adding listener")?;
    {
        let mut bsh = bsh.lock();
        bsh.update_status(&file).context("adding watch events")?;
    }

    if powerbuffer.power_type == power::POWER_TYPE_BATTERY {
        *battery_device_found = true;
        let bsh = bsh.clone();
        let mut timer = fasync::Interval::new(zx::Duration::from_seconds(SLEEP_TIME));
        fasync::spawn(async move {
            while let Some(()) = await!(timer.next()) {
                let mut bsh = bsh.lock();
                if let Err(e) = bsh.update_status(&file) {
                    fx_log_err!("{}", e);
                }
            }
        });
    } else {
        *adapter_device_found = true;
    }
    Ok(WatchSuccess::Completed)
}

async fn watch_power_device(bsh: Arc<Mutex<BatteryStatusHelper>>) -> Result<(), Error> {
    let file = File::open(POWER_DEVICE).context("cannot find power device")?;
    let mut watcher = vfs_watcher::Watcher::new(&file).context("error watching power device")?;
    let mut adapter_device_found = false;
    let mut battery_device_found = false;
    while let Some(msg) = await!(watcher.try_next())? {
        if battery_device_found && adapter_device_found {
           continue;
        }
        let mut filepath = PathBuf::from(POWER_DEVICE);
        filepath.push(msg.filename);
        match process_watch_event(
            &filepath,
            bsh.clone(),
            &mut battery_device_found,
            &mut adapter_device_found,
            ) {
            Ok(WatchSuccess::Completed) => {}
            Ok(early_return) => {
                let device_type = match early_return {
                    WatchSuccess::Completed => unreachable!(),
                    WatchSuccess::BatteryAlreadyFound => "battery",
                    WatchSuccess::AdapterAlreadyFound => "adapter",
                };
                fx_log_info!(
                    "Skip '{:?}' as {} device already found",
                    filepath,
                    device_type
                    );
            }
            Err(err) => {
                fx_log_err!(
                    "error for file while adding watch event '{:?}': {}",
                    filepath,
                    err
                    );
            }
        }
    }
    Ok(())
}

fn spawn_power_manager(pm: PowerManagerServer, chan: fasync::Channel) {
    fasync::spawn(async move {
        let mut stream = PowerManagerRequestStream::from_channel(chan);
        while let Some(req) = await!(stream.try_next())? {
            match req {
                PowerManagerRequest::GetBatteryStatus { responder, .. } => {
                    fx_log_info!("get_battery_status called");
                    let mut bsh = pm.battery_status_helper.lock();
                    if let Err(e) = responder.send(&mut bsh.battery_status) {
                        fx_log_err!("sending battery status: {:?}", e);
                    }
                }
                PowerManagerRequest::Watch { watcher, .. } => {
                    fx_log_info!("watch called");
                    match watcher.into_proxy() {
                        Err(e) => {
                            fx_log_err!("getting watcher proxy: {:?}", e);
                        }
                        Ok(w) => {
                            let mut bsh = pm.battery_status_helper.lock();
                            bsh.add_watcher(w);
                        }
                    }
                }
            }
        }
        Ok(())
    }.unwrap_or_else(|e: failure::Error| fx_log_err!("{:?}", e)));
}

fn main() {
    syslog::init_with_tags(&["power_manager"]).expect("Can't init logger");
    fx_log_info!("start");
    if let Err(e) = main_pm() {
        fx_log_err!("{:?}", e);
    }
    fx_log_info!("stop");
}

fn main_pm() -> Result<(), Error> {
    let mut executor = fasync::Executor::new().context("unable to create executor")?;
    let bsh = Arc::new(Mutex::new(BatteryStatusHelper::new()));
    let bsh2 = bsh.clone();
    let f = watch_power_device(bsh2);

    fasync::spawn(f.unwrap_or_else(|e| {
        fx_log_err!("watch_power_device failed {:?}", e);
    }));

    let server_fut = ServicesServer::new()
        .add_service((PowerManagerMarker::NAME, move |chan| {
            let pm = PowerManagerServer {
                battery_status_helper: bsh.clone(),
            };
            spawn_power_manager(pm, chan);
        })).start()
        .map_err(|e| e.context("starting service server"))?;
    Ok(executor.run(server_fut, 2).context("running server")?) // 2 threads
}

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

    macro_rules! cmp_fields {
        ($got:ident, $want:ident, [$($field:ident,)*], $test_no:expr) => { $(
            assert_eq!($got.$field, $want.$field, "test no: {}", $test_no);
        )* }
    }

    fn check_status(got: &BatteryStatus, want: &BatteryStatus, updated: bool, test_no: u32) {
        if updated {
            cmp_fields!(
                want,
                got,
                [
                    status,
                    battery_present,
                    charging,
                    critical,
                    power_adapter_online,
                    remaining_battery_life,
                ],
                test_no
            );
        } else {
            assert_eq!(want, got, "test: {}", test_no);
        }
    }

    fn get_default_battery_info() -> power::ioctl_power_get_battery_info_t {
        let mut battery_info = power::ioctl_power_get_battery_info_t::new();
        battery_info.last_full_capacity = 3000;
        battery_info.present_rate = -1000;
        battery_info.remaining_capacity = 2000;
        return battery_info;
    }

    #[test]
    fn update_battery_status() {
        let mut bsh = BatteryStatusHelper::new();
        let mut power_info = power::ioctl_power_get_info_t {
            power_type: power::POWER_TYPE_AC,
            state: 0,
        };
        let mut want = bsh.get_battery_status_copy();
        want.status = power_status::Ok;
        want.power_adapter_online = true;
        bsh.update_battery_status(power_info.clone(), None);
        check_status(&bsh.battery_status, &want, true, 1);

        let want = bsh.get_battery_status_copy();
        bsh.update_battery_status(power_info.clone(), None); // should not be updated
        check_status(&bsh.battery_status, &want, false, 2);

        let mut want = bsh.get_battery_status_copy();
        want.battery_present = true;
        want.level = 200.0 / 3.0;
        want.remaining_battery_life = 2.0;
        power_info.power_type = power::POWER_TYPE_BATTERY;
        power_info.state = 1;
        let battery_info = get_default_battery_info();
        bsh.update_battery_status(power_info.clone(), Some(battery_info.clone()));
        check_status(&bsh.battery_status, &want, true, 3);

        let mut want = bsh.get_battery_status_copy();
        power_info.state = 3;
        want.discharging = true;
        bsh.update_battery_status(power_info.clone(), Some(battery_info.clone()));
        check_status(&bsh.battery_status, &want, true, 4);

        let mut want = bsh.get_battery_status_copy();
        power_info.state = 5;
        want.discharging = false;
        want.charging = true;
        bsh.update_battery_status(power_info.clone(), Some(battery_info.clone()));
        check_status(&bsh.battery_status, &want, true, 5);

        let mut want = bsh.get_battery_status_copy();
        power_info.state = 13;
        want.discharging = false;
        want.charging = true;
        want.critical = true;
        bsh.update_battery_status(power_info.clone(), Some(battery_info.clone()));
        check_status(&bsh.battery_status, &want, true, 6);

        let mut want = bsh.get_battery_status_copy();
        power_info.state = 11;
        want.discharging = true;
        want.charging = false;
        want.critical = true;
        bsh.update_battery_status(power_info.clone(), Some(battery_info.clone()));
        check_status(&bsh.battery_status, &want, true, 7);
    }
}
