// 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 crate::apply::Initiator;
use crate::config::Config;
use crate::update_manager::{TargetChannelUpdater, UpdateApplier, UpdateChecker, UpdateManager};
use crate::update_monitor::StateChangeCallback;
use fidl_fuchsia_update::CheckStartedResult;
use fuchsia_async as fasync;
use fuchsia_syslog::fx_log_info;
use futures::prelude::*;
use std::sync::Arc;

pub fn run_periodic_update_check<T, C, A, S>(
    manager: Arc<UpdateManager<T, C, A, S>>,
    config: &Config,
) -> impl Future<Output = ()>
where
    T: TargetChannelUpdater,
    C: UpdateChecker,
    A: UpdateApplier,
    S: StateChangeCallback,
{
    let timer = config.poll_frequency().map(|duration| fasync::Interval::new(duration.into()));

    async move {
        let mut timer = match timer {
            Some(timer) => timer,
            None => return,
        };

        while let Some(()) = timer.next().await {
            match manager.try_start_update(Initiator::Automatic, None) {
                CheckStartedResult::Started => {}
                CheckStartedResult::Throttled => {
                    fx_log_info!("Automatic update check throttled");
                }
                CheckStartedResult::InProgress => {
                    fx_log_info!("Update in progress, automatic update check skipped");
                }
            }
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::config::ConfigBuilder;
    use crate::update_manager::tests::{
        FakeTargetChannelUpdater, FakeUpdateChecker, StateChangeCollector,
        UnreachableStateChangeCallback, UnreachableUpdateApplier,
    };
    use fidl_fuchsia_update::ManagerState;
    use fuchsia_async::DurationExt;
    use fuchsia_zircon::DurationNum;
    use futures::task::Poll;

    #[test]
    fn test_disabled_periodic_update_check() {
        let mut executor = fasync::Executor::new_with_fake_time().unwrap();

        let checker = FakeUpdateChecker::new_up_to_date();
        let manager: UpdateManager<_, _, _, UnreachableStateChangeCallback> =
            UpdateManager::from_checker_and_applier(
                FakeTargetChannelUpdater::new(),
                checker.clone(),
                UnreachableUpdateApplier,
            );

        let mut cron = run_periodic_update_check(Arc::new(manager), &Config::default()).boxed();

        assert_eq!(Poll::Ready(()), executor.run_until_stalled(&mut cron));
        assert_eq!(checker.call_count(), 0);
        assert_eq!(None, executor.wake_next_timer());
    }

    #[test]
    fn test_periodic_update_check() {
        let mut executor = fasync::Executor::new_with_fake_time().unwrap();

        let checker = FakeUpdateChecker::new_up_to_date();
        let callback = StateChangeCollector::new();
        let manager = UpdateManager::from_checker_and_applier(
            FakeTargetChannelUpdater::new(),
            checker.clone(),
            UnreachableUpdateApplier,
        );
        manager.add_permanent_callback(callback.clone());

        let period = 10.minutes();
        let config = ConfigBuilder::new().poll_frequency(period).build();
        let mut cron = run_periodic_update_check(Arc::new(manager), &config).boxed();

        // Let the cron task set up the timer, but nothing interesting happens until time advances.
        assert_eq!(Poll::Pending, executor.run_until_stalled(&mut cron));
        assert_eq!(callback.take_states(), vec![ManagerState::Idle.into()]);

        // Not time yet.
        executor.set_fake_time(8.minutes().after_now());
        assert!(!executor.wake_expired_timers());
        assert_eq!(Poll::Pending, executor.run_until_stalled(&mut cron));
        assert_eq!(callback.take_states(), vec![]);

        // Verify the timer performs the correct operations after elapsing.
        executor.set_fake_time(2.minutes().after_now());
        assert!(executor.wake_expired_timers());
        assert_eq!(Poll::Pending, executor.run_until_stalled(&mut cron));
        assert_eq!(checker.call_count(), 1);
        assert_eq!(
            callback.take_states(),
            vec![ManagerState::CheckingForUpdates.into(), ManagerState::Idle.into()]
        );

        // Verify the timer fires more than once.
        executor.set_fake_time(period.after_now());
        assert!(executor.wake_expired_timers());
        assert_eq!(Poll::Pending, executor.run_until_stalled(&mut cron));
        assert_eq!(checker.call_count(), 2);
        assert_eq!(
            callback.take_states(),
            vec![ManagerState::CheckingForUpdates.into(), ManagerState::Idle.into()]
        );
    }

    #[test]
    fn test_simultaneous_user_update_check_and_periodic_update_check() {
        let mut executor = fasync::Executor::new_with_fake_time().unwrap();

        let checker = FakeUpdateChecker::new_up_to_date();
        let update_blocked = checker.block().unwrap();
        let callback = StateChangeCollector::new();
        let manager = UpdateManager::from_checker_and_applier(
            FakeTargetChannelUpdater::new(),
            checker.clone(),
            UnreachableUpdateApplier,
        );
        let manager = Arc::new(manager);
        manager.add_permanent_callback(callback.clone());

        let period = 24.hours();
        let config = ConfigBuilder::new().poll_frequency(period).build();
        let mut cron = run_periodic_update_check(Arc::clone(&manager), &config).boxed();

        // Let the cron task set up the timer, but nothing interesting happens until time advances.
        assert_eq!(Poll::Pending, executor.run_until_stalled(&mut cron));

        // User wins, and only 1 update check happens.
        assert_eq!(manager.try_start_update(Initiator::Manual, None), CheckStartedResult::Started);
        // The automatic update is skipped because an update is already in progress.
        executor.set_fake_time(period.after_now());
        assert!(executor.wake_expired_timers());
        assert_eq!(Poll::Pending, executor.run_until_stalled(&mut cron));
        // Let the user-initiated update check complete. The update does not run.
        std::mem::drop(update_blocked);
        assert_eq!(Poll::Pending, executor.run_until_stalled(&mut cron));

        assert_eq!(checker.call_count(), 1);
        assert_eq!(
            callback.take_states(),
            vec![
                ManagerState::Idle.into(),
                ManagerState::CheckingForUpdates.into(),
                ManagerState::Idle.into()
            ]
        );
    }
}
