// Copyright 2021 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use anyhow::{Context, Error};
use fidl_fuchsia_power_button::{Action, MonitorMarker, MonitorProxy};
use fuchsia_async::Task;
use fuchsia_syslog::fx_log_err;
use std::sync::{Arc, Mutex};

struct PowerButtonInner {
    proxy: MonitorProxy,
    inhibit_count: usize,
    orig_action: Action,
    release_task: Option<Task<()>>,
}

pub struct PowerButton {
    inner: Mutex<PowerButtonInner>,
}

impl PowerButton {
    pub fn new_from_namespace() -> Result<Arc<Self>, Error> {
        let proxy = fuchsia_component::client::connect_to_protocol::<MonitorMarker>()
            .context("Connecting to power button monitor")?;
        Ok(PowerButton::new(proxy))
    }

    pub fn new(proxy: MonitorProxy) -> Arc<Self> {
        Arc::new(PowerButton {
            inner: Mutex::new(PowerButtonInner {
                proxy,
                inhibit_count: 0,
                orig_action: Action::Shutdown,
                release_task: None,
            }),
        })
    }

    /// Make sure that the power button does nothing.
    pub async fn inhibit(self: Arc<Self>) -> Result<PowerButtonInhibitor, Error> {
        {
            // TODO: this variable triggered the `must_not_suspend` lint and may be held across an await
            // If this is the case, it is an error. See fxbug.dev/87757 for more details
            let mut inner = self.inner.lock().unwrap();
            if inner.inhibit_count == 0 {
                // Make sure the previous cancellation ran.
                if let Some(task) = inner.release_task.take() {
                    task.await;
                }
                let state = inner.proxy.get_action().await.context("Sending get_action")?;
                inner.orig_action = state;
                inner.proxy.set_action(Action::Ignore).await.context("Sending set_action")?;
            }
            inner.inhibit_count += 1;
        }
        Ok(PowerButtonInhibitor { button: self })
    }

    fn release(&self) {
        let mut inner = self.inner.lock().unwrap();
        inner.inhibit_count -= 1;
        if inner.inhibit_count == 0 {
            let proxy = inner.proxy.clone();
            assert_eq!(inner.release_task.is_none(), true);
            let action = inner.orig_action;
            inner.release_task = Some(fuchsia_async::Task::spawn(async move {
                proxy.set_action(action).await.unwrap_or_else(|e| {
                    fx_log_err!("Failed to restore power button action: {:?}", e);
                });
            }));
        }
    }
}

/// RAII struct returned by PowerButton.inhibit().
/// When it is dropped, the power button's state is restored.
#[must_use]
pub struct PowerButtonInhibitor {
    button: Arc<PowerButton>,
}

impl Drop for PowerButtonInhibitor {
    fn drop(&mut self) {
        self.button.release();
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use fidl_fuchsia_power_button::{Action, MonitorRequest};
    use futures::TryStreamExt;

    struct FakePowerButtonManager {
        action: Mutex<Action>,
    }

    impl FakePowerButtonManager {
        pub fn new() -> Arc<Self> {
            Arc::new(FakePowerButtonManager { action: Mutex::new(Action::Shutdown) })
        }

        pub fn serve(self: Arc<Self>) -> MonitorProxy {
            let (proxy, mut stream) =
                fidl::endpoints::create_proxy_and_stream::<MonitorMarker>().unwrap();

            Task::spawn(async move {
                while let Some(req) = stream.try_next().await.unwrap() {
                    match req {
                        MonitorRequest::GetAction { responder } => responder
                            .send(*self.action.lock().unwrap())
                            .expect("Replying to GetAction"),
                        MonitorRequest::SetAction { action, responder } => {
                            *self.action.lock().unwrap() = action;
                            responder.send().expect("Replying to SetAction");
                        }
                    }
                }
            })
            .detach();

            proxy
        }

        pub fn get_action(&self) -> Action {
            *self.action.lock().unwrap()
        }
    }

    #[fuchsia::test]
    async fn test_inhibit() {
        let manager = FakePowerButtonManager::new();
        let button = PowerButton::new(manager.clone().serve());

        {
            let _inhibitor = button.clone().inhibit().await.expect("Inhibit succeeds");
            assert_eq!(manager.get_action(), Action::Ignore);
        }

        // Make sure the async task is executed.
        match button.inner.lock().unwrap().release_task.take() {
            Some(task) => task.await,
            None => {}
        }
        assert_eq!(manager.get_action(), Action::Shutdown);
    }

    #[fuchsia::test]
    async fn test_inhibit_twice() {
        let manager = FakePowerButtonManager::new();
        let button = PowerButton::new(manager.clone().serve());

        {
            let _inhibitor = button.clone().inhibit().await.expect("Inhibit succeeds");
            assert_eq!(manager.get_action(), Action::Ignore);
            {
                let _inhibitor2 = button.clone().inhibit().await.expect("Second inhibit succeeds");
                assert_eq!(manager.get_action(), Action::Ignore);
            }
            // Shouldn't yet be trying to release.
            assert!(button.inner.lock().unwrap().release_task.is_none());
            assert_eq!(manager.get_action(), Action::Ignore);
        }

        // Make sure the async task is executed.
        match button.inner.lock().unwrap().release_task.take() {
            Some(task) => task.await,
            None => {}
        }
        assert_eq!(manager.get_action(), Action::Shutdown);
    }
}
