// 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::Error;
#[cfg(test)]
use fidl_fuchsia_cobalt::CobaltEvent;
use fuchsia_cobalt::{CobaltConnector, CobaltSender, ConnectionType};
use futures::prelude::*;
use log::info;
use omaha_client::metrics::{Metrics, MetricsReporter};

/// A MetricsReporter trait implementation that send metrics to Cobalt.
pub struct CobaltMetricsReporter {
    cobalt_sender: CobaltSender,
}

impl CobaltMetricsReporter {
    pub fn new() -> (Self, impl Future<Output = ()>) {
        let (cobalt_sender, fut) = CobaltConnector::default()
            .serve(ConnectionType::project_id(mos_metrics_registry::PROJECT_ID));
        (CobaltMetricsReporter { cobalt_sender }, fut)
    }

    #[cfg(test)]
    fn new_mock() -> (Self, futures::channel::mpsc::Receiver<CobaltEvent>) {
        let (sender, receiver) = futures::channel::mpsc::channel(1);
        let cobalt_sender = CobaltSender::new(sender);
        (CobaltMetricsReporter { cobalt_sender }, receiver)
    }
}

impl MetricsReporter for CobaltMetricsReporter {
    fn report_metrics(&mut self, metrics: Metrics) -> Result<(), Error> {
        info!("Reporting metrics to Cobalt: {:?}", metrics);
        match metrics {
            Metrics::UpdateCheckResponseTime(duration) => {
                self.cobalt_sender.log_elapsed_time(
                    mos_metrics_registry::UPDATE_CHECK_RESPONSE_TIME_METRIC_ID,
                    mos_metrics_registry::UpdateCheckResponseTimeMetricDimensionResult::Success
                        as u32,
                    duration.as_micros() as i64,
                );
            }
            Metrics::UpdateCheckInterval(duration) => {
                self.cobalt_sender.log_elapsed_time(
                    mos_metrics_registry::UPDATE_CHECK_INTERVAL_METRIC_ID,
                    mos_metrics_registry::UpdateCheckIntervalMetricDimensionResult::Success as u32,
                    duration.as_micros() as i64,
                );
            }
            Metrics::SuccessfulUpdateDuration(duration) => {
                self.cobalt_sender.log_elapsed_time(
                    mos_metrics_registry::UPDATE_DURATION_METRIC_ID,
                    mos_metrics_registry::UpdateDurationMetricDimensionResult::Success as u32,
                    duration.as_micros() as i64,
                );
            }
            Metrics::FailedUpdateDuration(duration) => {
                self.cobalt_sender.log_elapsed_time(
                    mos_metrics_registry::UPDATE_DURATION_METRIC_ID,
                    mos_metrics_registry::UpdateDurationMetricDimensionResult::Failed as u32,
                    duration.as_micros() as i64,
                );
            }
            Metrics::SuccessfulUpdateFromFirstSeen(duration) => {
                self.cobalt_sender.log_elapsed_time(
                    mos_metrics_registry::UPDATE_DURATION_FROM_FIRST_SEEN_METRIC_ID,
                    mos_metrics_registry::UpdateDurationFromFirstSeenMetricDimensionResult::Success
                        as u32,
                    duration.as_micros() as i64,
                );
            }
            Metrics::UpdateCheckFailureReason(reason) => {
                self.cobalt_sender
                    .log_event(mos_metrics_registry::UPDATE_CHECK_FAILURE_METRIC_ID, reason as u32);
            }
            Metrics::UpdateCheckRetries(count) => {
                self.cobalt_sender.log_event_count(
                    mos_metrics_registry::UPDATE_CHECK_RETRIES_METRIC_ID,
                    mos_metrics_registry::UpdateCheckRetriesMetricDimensionResult::Success as u32,
                    0,
                    count as i64,
                );
            }
            Metrics::AttemptsToSucceed(count) => {
                self.cobalt_sender.log_event_count(
                    mos_metrics_registry::ATTEMPTS_TO_SUCCEED_METRIC_ID,
                    mos_metrics_registry::AttemptsToSucceedMetricDimensionResult::Success as u32,
                    0,
                    count as i64,
                );
            }
            Metrics::WaitedForRebootDuration(duration) => {
                self.cobalt_sender.log_elapsed_time(
                    mos_metrics_registry::WAITED_FOR_REBOOT_DURATION_METRIC_ID,
                    mos_metrics_registry::WaitedForRebootDurationMetricDimensionResult::Success
                        as u32,
                    duration.as_micros() as i64,
                );
            }
            Metrics::FailedBootAttempts(count) => {
                self.cobalt_sender.log_event_count(
                    mos_metrics_registry::FAILED_BOOT_ATTEMPTS_METRIC_ID,
                    mos_metrics_registry::FailedBootAttemptsMetricDimensionResult::Success as u32,
                    0,
                    count as i64,
                );
            }
        }
        Ok(())
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use fidl_fuchsia_cobalt::{CountEvent, EventPayload};
    use omaha_client::metrics::UpdateCheckFailureReason;
    use std::time::Duration;

    #[test]
    fn test_report_update_check_response_time() {
        let (mut reporter, mut receiver) = CobaltMetricsReporter::new_mock();
        reporter
            .report_metrics(Metrics::UpdateCheckResponseTime(Duration::from_millis(10)))
            .unwrap();
        assert_eq!(
            receiver.try_next().unwrap().unwrap(),
            CobaltEvent {
                metric_id: mos_metrics_registry::UPDATE_CHECK_RESPONSE_TIME_METRIC_ID,
                event_codes: vec![
                    mos_metrics_registry::UpdateCheckResponseTimeMetricDimensionResult::Success
                        as u32
                ],
                component: None,
                payload: EventPayload::ElapsedMicros(10 * 1000),
            }
        );
    }

    #[test]
    fn test_report_update_check_failure_reason() {
        let (mut reporter, mut receiver) = CobaltMetricsReporter::new_mock();
        reporter
            .report_metrics(Metrics::UpdateCheckFailureReason(
                UpdateCheckFailureReason::Configuration,
            ))
            .unwrap();
        assert_eq!(
            receiver.try_next().unwrap().unwrap(),
            CobaltEvent {
                metric_id: mos_metrics_registry::UPDATE_CHECK_FAILURE_METRIC_ID,
                event_codes: vec![
                    mos_metrics_registry::UpdateCheckFailureMetricDimensionReason::Configuration
                        as u32
                ],
                component: None,
                payload: EventPayload::Event(fidl_fuchsia_cobalt::Event),
            }
        );
    }

    #[test]
    fn test_report_update_check_retries() {
        let (mut reporter, mut receiver) = CobaltMetricsReporter::new_mock();
        reporter.report_metrics(Metrics::UpdateCheckRetries(3)).unwrap();
        assert_eq!(
            receiver.try_next().unwrap().unwrap(),
            CobaltEvent {
                metric_id: mos_metrics_registry::UPDATE_CHECK_RETRIES_METRIC_ID,
                event_codes: vec![
                    mos_metrics_registry::UpdateCheckRetriesMetricDimensionResult::Success as u32
                ],
                component: None,
                payload: EventPayload::EventCount(CountEvent {
                    period_duration_micros: 0,
                    count: 3
                }),
            }
        );
    }
}
