// Copyright 2019 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::{format_err, Context, Error},
    fidl_fuchsia_metrics::{MetricEventLoggerFactoryMarker, MetricEventLoggerProxy, ProjectSpec},
    fuchsia_async as fasync,
    fuchsia_component::client::connect_to_protocol,
    fuchsia_zircon as zx,
    session_framework_metrics_registry::cobalt_registry as metrics,
    tracing::warn,
};

/// Creates a LoggerProxy connected to Cobalt.
///
/// The connection is performed in a Future run on the global executor, but the `LoggerProxy`
/// can be used immediately.
///
/// # Returns
/// `LoggerProxy` for log messages to be sent to.
pub fn get_logger() -> Result<MetricEventLoggerProxy, Error> {
    let (logger_proxy, server_end) =
        fidl::endpoints::create_proxy().context("Failed to create endpoints")?;
    let logger_factory = connect_to_protocol::<MetricEventLoggerFactoryMarker>()
        .context("Failed to connect to the Cobalt MetricEventLoggerFactory")?;

    fasync::Task::spawn(async move {
        if let Err(err) = logger_factory
            .create_metric_event_logger(
                &ProjectSpec { project_id: Some(metrics::PROJECT_ID), ..Default::default() },
                server_end,
            )
            .await
        {
            warn!(%err, "Failed to create Cobalt logger");
        }
    })
    .detach();

    Ok(logger_proxy)
}

/// Reports the time elapsed while launching a session.
///
/// # Parameters
/// - `logger_proxy`: The cobalt logger.
/// - `start_time`: The time when session_manager starts launching a session.
/// - `end_time`: The time when session_manager has bound to a session. This must be strictly after
///               `start_time`.
///
/// # Returns
/// `Ok` if the time elapsed was logged successfully.
pub async fn log_session_launch_time(
    logger_proxy: MetricEventLoggerProxy,
    start_time: zx::Time,
    end_time: zx::Time,
) -> Result<(), Error> {
    let elapsed_time = (end_time - start_time).into_micros();
    if elapsed_time < 0 {
        return Err(format_err!("End time must be after start time."));
    }

    logger_proxy
        .log_integer(
            metrics::SESSION_LAUNCH_TIME_MIGRATED_METRIC_ID,
            elapsed_time,
            &[metrics::SessionLaunchTimeMigratedMetricDimensionStatus::Success as u32],
        )
        .await
        .context("Could not log session launch time.")?
        .map_err(|e| format_err!("Logging session launch time returned an error: {:?}", e))?;

    Ok(())
}

#[cfg(test)]
mod tests {
    use {
        super::*,
        fidl::endpoints::create_proxy_and_stream,
        fidl_fuchsia_metrics::{MetricEventLoggerMarker, MetricEventLoggerRequest},
        futures::TryStreamExt,
    };

    /// Tests that the right payload is sent to Cobalt when logging the session launch time.
    #[fasync::run_singlethreaded(test)]
    async fn test_log_session_launch_time() {
        let (logger_proxy, mut logger_server) =
            create_proxy_and_stream::<MetricEventLoggerMarker>()
                .expect("Failed to create Logger FIDL.");
        let start_time = zx::Time::from_nanos(0);
        let end_time = zx::Time::from_nanos(5000);

        fasync::Task::spawn(async move {
            let _ = log_session_launch_time(logger_proxy, start_time, end_time).await;
        })
        .detach();

        if let Some(log_request) = logger_server.try_next().await.unwrap() {
            if let MetricEventLoggerRequest::LogInteger {
                metric_id,
                value,
                event_codes,
                responder: _,
            } = log_request
            {
                assert_eq!(metric_id, metrics::SESSION_LAUNCH_TIME_MIGRATED_METRIC_ID);
                assert_eq!(
                    event_codes,
                    vec![metrics::SessionLaunchTimeMigratedMetricDimensionStatus::Success as u32]
                );
                assert_eq!(value, 5);
            } else {
                assert!(false);
            }
        } else {
            assert!(false);
        }
    }

    /// Tests that an error is raised if end_time < start_time.
    #[fasync::run_singlethreaded(test)]
    async fn test_log_session_launch_time_swap_start_end_time() {
        let (logger_proxy, _logger_server) = create_proxy_and_stream::<MetricEventLoggerMarker>()
            .expect("Failed to create Logger FIDL.");
        let start_time = zx::Time::from_nanos(0);
        let end_time = zx::Time::from_nanos(5000);

        assert!(log_session_launch_time(logger_proxy, end_time, start_time).await.is_err());
    }
}
