// 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::error::PowerManagerError;
use crate::log_if_err;
use crate::message::{Message, MessageReturn};
use crate::node::Node;
use anyhow::{format_err, Error};
use async_trait::async_trait;
use fidl_fuchsia_feedback as fidl_feedback;
use fuchsia_async as fasync;
use futures::channel::mpsc;
use futures::stream::StreamExt;
use std::cell::RefCell;
use std::rc::Rc;

/// Node: CrashReportHandler
///
/// Summary: Provides a mechanism for filing crash reports.
///
/// Handles Messages:
///     - FileCrashReport
///
/// Sends Messages: N/A
///
/// FIDL dependencies:
///     - fuchsia.feedback.CrashReporter: the node uses this protocol to communicate with the
///       CrashReporter service in order to file crash reports.
///

type GetProxyFn = Box<dyn Fn() -> Result<fidl_feedback::CrashReporterProxy, anyhow::Error>>;

/// The maximum number of pending crash report requests. This is needed because the FIDL API to file
/// a crash report does not return until the crash report has been fully generated, which can take
/// upwards of 30 seconds or more. Supporting pending crash reports means the PowerManager can file
/// a new crash report for any other reason within that window, but the CrashReportHandler will
/// handle rate limiting to the CrashReporter service.
const MAX_PENDING_CRASH_REPORTS: usize = 5;

/// A builder for constructing the CrashReportHandler node.
pub struct CrashReportHandlerBuilder {
    get_proxy_fn: GetProxyFn,
    max_pending_crash_reports: usize,
}

impl CrashReportHandlerBuilder {
    pub fn new() -> Self {
        Self {
            get_proxy_fn: Box::new(default_get_proxy_fn),
            max_pending_crash_reports: MAX_PENDING_CRASH_REPORTS,
        }
    }

    #[cfg(test)]
    pub fn with_proxy_fn(mut self, proxy: GetProxyFn) -> Self {
        self.get_proxy_fn = proxy;
        self
    }

    #[cfg(test)]
    pub fn with_max_pending_crash_reports(mut self, max: usize) -> Self {
        self.max_pending_crash_reports = max;
        self
    }

    pub fn build(self) -> Result<Rc<CrashReportHandler>, Error> {
        // Set up the crash report sender that runs asynchronously
        let (channel, receiver) = mpsc::channel(self.max_pending_crash_reports);

        // Connect to Crash Reporter service only on demand - when there is a thermal event
        CrashReportHandler::begin_crash_report_sender(self.get_proxy_fn, receiver);
        Ok(Rc::new(CrashReportHandler { crash_report_sender: RefCell::new(channel) }))
    }
}

pub fn default_get_proxy_fn() -> Result<fidl_feedback::CrashReporterProxy, anyhow::Error> {
    fuchsia_component::client::connect_to_protocol::<fidl_feedback::CrashReporterMarker>()
}

pub struct CrashReportHandler {
    /// The channel to send new crash report requests to the asynchronous crash report sender
    /// future. The maximum pending crash reports are implicitly enforced by the channel length.
    crash_report_sender: RefCell<mpsc::Sender<String>>,
}

impl CrashReportHandler {
    /// Default name to use for `program_name` in the crash report. Using "device" here to align
    /// with other device/hardware crash types that use the same name (brownout, hardware watchdog
    /// timeout, power cycles, etc.).
    const DEFAULT_PROGRAM_NAME: &'static str = "device";

    /// Handle a FileCrashReport message by sending the specified crash report signature over the
    /// channel to the crash report sender.
    fn handle_file_crash_report(
        &self,
        signature: String,
    ) -> Result<MessageReturn, PowerManagerError> {
        // Try to send the crash report signature over the channel. If the channel is full, return
        // an error
        match self.crash_report_sender.borrow_mut().try_send(signature) {
            Ok(()) => Ok(MessageReturn::FileCrashReport),
            Err(e) if e.is_full() => Err(PowerManagerError::OutOfSpace(format!(
                "Pending crash reports exceeds max ({})",
                MAX_PENDING_CRASH_REPORTS
            ))),
            Err(e) => Err(PowerManagerError::GenericError(e.into())),
        }
    }

    /// Spawn an infinite future that receives crash report signatures over the channel and uses the
    /// proxy to send a File FIDL request to the CrashReporter service with the specified
    /// signatures.
    fn begin_crash_report_sender(
        get_proxy_fn: GetProxyFn,
        mut receive_channel: mpsc::Receiver<String>,
    ) {
        fasync::Task::local(async move {
            while let Some(signature) = receive_channel.next().await {
                log_if_err!(
                    Self::send_crash_report(&get_proxy_fn, signature).await,
                    "Failed to file crash report"
                );
            }
        })
        .detach();
    }

    /// Send a File request to the CrashReporter service with the specified crash report signature.
    async fn send_crash_report(get_proxy_fn: &GetProxyFn, signature: String) -> Result<(), Error> {
        let report = fidl_feedback::CrashReport {
            program_name: Some(CrashReportHandler::DEFAULT_PROGRAM_NAME.to_string()),
            crash_signature: Some(signature),
            is_fatal: Some(false),
            ..fidl_feedback::CrashReport::EMPTY
        };
        let result =
            get_proxy_fn()?.file(report).await.map_err(|e| format_err!("IPC error: {}", e))?;
        result.map_err(|e| format_err!("Service error: {}", e))
    }
}

#[async_trait(?Send)]
impl Node for CrashReportHandler {
    fn name(&self) -> String {
        "CrashReportHandler".to_string()
    }

    async fn handle_message(&self, msg: &Message) -> Result<MessageReturn, PowerManagerError> {
        match msg {
            Message::FileCrashReport(signature) => {
                self.handle_file_crash_report(signature.to_string())
            }
            _ => Err(PowerManagerError::Unsupported),
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use assert_matches::assert_matches;
    use futures::{poll, TryStreamExt};
    use std::task::Poll;

    /// Tests that the node responds to the FileCrashReport message and that the expected crash
    /// report is received by the CrashReporter service.
    #[fasync::run_singlethreaded(test)]
    async fn test_crash_report_content() {
        // The crash report signature to use and verify against
        let crash_report_signature = "TestCrashReportSignature";

        // Set up the CrashReportHandler node
        let (proxy, mut stream) =
            fidl::endpoints::create_proxy_and_stream::<fidl_feedback::CrashReporterMarker>()
                .unwrap();
        let crash_report_handler = CrashReportHandlerBuilder::new()
            .with_proxy_fn(Box::new(move || Ok(proxy.clone())))
            .build()
            .unwrap();

        // File a crash report
        crash_report_handler
            .handle_message(&Message::FileCrashReport(crash_report_signature.to_string()))
            .await
            .unwrap();

        // Verify the fake service receives the crash report with expected data
        if let Ok(Some(fidl_feedback::CrashReporterRequest::File { responder: _, report })) =
            stream.try_next().await
        {
            assert_eq!(
                report,
                fidl_feedback::CrashReport {
                    program_name: Some("device".to_string()),
                    crash_signature: Some(crash_report_signature.to_string()),
                    is_fatal: Some(false),
                    ..fidl_feedback::CrashReport::EMPTY
                }
            );
        } else {
            panic!("Did not receive a crash report");
        }
    }

    /// Tests that the number of pending crash reports is correctly bounded.
    #[test]
    fn test_crash_report_pending_reports() {
        let mut exec = fasync::TestExecutor::new().unwrap();

        // Set up the proxy/stream and node outside of the large future used below. This way we can
        // still poll the stream after the future completes.
        let (proxy, mut stream) =
            fidl::endpoints::create_proxy_and_stream::<fidl_feedback::CrashReporterMarker>()
                .unwrap();
        let crash_report_handler = CrashReportHandlerBuilder::new()
            .with_proxy_fn(Box::new(move || Ok(proxy.clone())))
            .with_max_pending_crash_reports(1)
            .build()
            .unwrap();

        // Run most of the test logic inside a top level future for better ergonomics
        exec.run_singlethreaded(async {
            // Set up the CrashReportHandler node. The request stream is never serviced, so when the
            // node makes the FIDL call to file the crash report, the call will block indefinitely.
            // This lets us test the pending crash report counts.

            // The first FileCrashReport should succeed
            assert_matches!(
                crash_report_handler
                    .handle_message(&Message::FileCrashReport("TestCrash1".to_string()))
                    .await,
                Ok(MessageReturn::FileCrashReport)
            );

            // The second FileCrashReport should also succeed because since the first is now in
            // progress, this is now the first "pending" report request
            assert_matches!(
                crash_report_handler
                    .handle_message(&Message::FileCrashReport("TestCrash2".to_string()))
                    .await,
                Ok(MessageReturn::FileCrashReport)
            );

            // Since the first request has not completed, and there is already one pending request,
            // this request should fail
            assert_matches!(
                crash_report_handler
                    .handle_message(&Message::FileCrashReport("TestCrash3".to_string()))
                    .await,
                Err(PowerManagerError::OutOfSpace(_))
            );

            // Verify the signature of the first crash report
            if let Ok(Some(fidl_feedback::CrashReporterRequest::File { responder, report })) =
                stream.try_next().await
            {
                // Send a reply to allow the node to process the next crash report
                let _ = responder.send(&mut Ok(()));
                assert_eq!(
                    report,
                    fidl_feedback::CrashReport {
                        program_name: Some("device".to_string()),
                        crash_signature: Some("TestCrash1".to_string()),
                        is_fatal: Some(false),
                        ..fidl_feedback::CrashReport::EMPTY
                    }
                );
            } else {
                panic!("Did not receive a crash report");
            }

            // Verify the signature of the second crash report
            if let Ok(Some(fidl_feedback::CrashReporterRequest::File { responder, report })) =
                stream.try_next().await
            {
                // Send a reply to allow the node to process the next crash report
                let _ = responder.send(&mut Ok(()));
                assert_eq!(
                    report,
                    fidl_feedback::CrashReport {
                        program_name: Some("device".to_string()),
                        crash_signature: Some("TestCrash2".to_string()),
                        is_fatal: Some(false),
                        ..fidl_feedback::CrashReport::EMPTY
                    }
                );
            } else {
                panic!("Did not receive a crash report");
            }
        });

        // Verify there are no more crash reports. Use `run_until_stalled` because `next` is
        // expected to block until a new crash report is ready, which shouldn't happen here.
        assert!(exec.run_until_stalled(&mut stream.next()).is_pending());
    }

    #[fasync::run_singlethreaded(test)]
    async fn test_crash_report_channel_closure() {
        let (proxy, mut stream) =
            fidl::endpoints::create_proxy_and_stream::<fidl_feedback::CrashReporterMarker>()
                .unwrap();
        let crash_report_handler = CrashReportHandlerBuilder::new()
            .with_proxy_fn(Box::new(move || Ok(proxy.clone())))
            .build()
            .unwrap();

        // File a crash report
        crash_report_handler
            .handle_message(&Message::FileCrashReport(
                "TestCrashReportSvcChannelClosure".to_string(),
            ))
            .await
            .unwrap();

        // Verify the fake service receives the crash report with expected data
        if let Ok(Some(fidl_feedback::CrashReporterRequest::File { responder: _, report })) =
            stream.try_next().await
        {
            assert_eq!(
                report,
                fidl_feedback::CrashReport {
                    program_name: Some("device".to_string()),
                    crash_signature: Some("TestCrashReportSvcChannelClosure".to_string()),
                    is_fatal: Some(false),
                    ..fidl_feedback::CrashReport::EMPTY
                }
            );
        } else {
            panic!("Did not receive a crash report");
        }

        // verify channel is closed
        let poll_result = poll!(stream.next());
        match poll_result {
            Poll::Ready(None) => {}
            Poll::Pending => panic!("channel expected to be closed"),
            Poll::Ready(_) => panic!("channel expected to be closed"),
        }
    }
}
