// 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.

mod apply;
mod channel;
mod channel_handler;
mod check;
mod config;
mod connect;
mod errors;
mod last_update_storage;
mod poller;
mod rate_limiter;
mod update_manager;
mod update_monitor;
mod update_service;

use {
    crate::{
        apply::Initiator,
        channel_handler::ChannelHandler,
        config::Config,
        poller::run_periodic_update_check,
        update_service::{RealUpdateManager, RealUpdateService},
    },
    anyhow::{anyhow, Context as _, Error},
    fidl_fuchsia_update_channel::ProviderRequestStream,
    fidl_fuchsia_update_channelcontrol::ChannelControlRequestStream,
    forced_fdr::perform_fdr_if_necessary,
    fuchsia_async as fasync,
    fuchsia_component::server::ServiceFs,
    fuchsia_inspect as finspect,
    fuchsia_syslog::{fx_log_err, fx_log_warn},
    futures::{prelude::*, stream::FuturesUnordered},
    std::{sync::Arc, time::Duration},
};

const MAX_CONCURRENT_CONNECTIONS: usize = 100;

#[fasync::run(1)]
async fn main() -> Result<(), Error> {
    fuchsia_syslog::init_with_tags(&["system-update-checker"]).context("syslog init failed")?;

    let config = Config::load_from_config_data_or_default();
    if let Some(url) = config.update_package_url() {
        fx_log_warn!("Ignoring custom update package url: {}", url);
    }

    let inspector = finspect::Inspector::new();

    let target_channel_manager =
        channel::TargetChannelManager::new(connect::ServiceConnector, "/misc/ota");
    if let Err(e) = target_channel_manager.update().await {
        fx_log_err!("while updating the target channel: {:#}", anyhow!(e));
    }
    let target_channel_manager = Arc::new(target_channel_manager);

    let futures = FuturesUnordered::new();

    let (current_channel_manager, current_channel_notifier) =
        channel::build_current_channel_manager_and_notifier(
            connect::ServiceConnector,
            "/misc/ota",
        )?;
    futures.push(current_channel_notifier.run().boxed());
    let current_channel_manager = Arc::new(current_channel_manager);

    let update_manager = RealUpdateManager::new(
        Arc::clone(&target_channel_manager),
        Arc::clone(&current_channel_manager),
        inspector.root().create_child("update-manager"),
    )
    .await;
    let update_manager = Arc::new(update_manager);

    let mut fs = ServiceFs::new();
    let update_manager_clone = Arc::clone(&update_manager);
    let channel_handler =
        Arc::new(ChannelHandler::new(current_channel_manager, target_channel_manager));
    let channel_handler_clone = Arc::clone(&channel_handler);
    let channel_handler_provider_clone = Arc::clone(&channel_handler);

    fs.dir("svc")
        .add_fidl_service(move |stream| {
            IncomingServices::Manager(
                stream,
                RealUpdateService::new(Arc::clone(&update_manager_clone)),
            )
        })
        .add_fidl_service(move |stream| {
            IncomingServices::Provider(stream, Arc::clone(&channel_handler_provider_clone))
        })
        .add_fidl_service(move |stream| {
            IncomingServices::ChannelControl(stream, Arc::clone(&channel_handler_clone))
        });

    inspector.serve(&mut fs)?;

    fs.take_and_serve_directory_handle().context("ServiceFs::take_and_serve_directory_handle")?;
    futures.push(
        fs.for_each_concurrent(MAX_CONCURRENT_CONNECTIONS, |incoming_service| {
            handle_incoming_service(incoming_service).unwrap_or_else(|e| {
                fx_log_err!("error handling client connection: {:#}", anyhow!(e))
            })
        })
        .boxed(),
    );

    futures.push(run_periodic_update_check(update_manager.clone(), &config).boxed());

    futures.push(
        async move {
            if config.poll_frequency().is_some() {
                fasync::Timer::new(fasync::Time::after(Duration::from_secs(60).into())).await;
                if let Err(e) =
                    update_manager.try_start_update(Initiator::Automatic, None, None).await
                {
                    fx_log_warn!("Update check failed with error: {:?}", e);
                }
            }
        }
        .boxed(),
    );

    futures.push(perform_fdr_if_necessary().boxed());

    futures.push(check_and_set_system_health().boxed());

    futures.collect::<()>().await;

    Ok(())
}

enum IncomingServices {
    Manager(fidl_fuchsia_update::ManagerRequestStream, RealUpdateService),
    Provider(ProviderRequestStream, Arc<ChannelHandler>),
    ChannelControl(ChannelControlRequestStream, Arc<ChannelHandler>),
}

async fn handle_incoming_service(incoming_service: IncomingServices) -> Result<(), Error> {
    match incoming_service {
        IncomingServices::Manager(request_stream, update_service) => {
            update_service.handle_request_stream(request_stream).await
        }
        IncomingServices::Provider(request_stream, handler) => {
            handler.handle_provider_request_stream(request_stream).await
        }
        IncomingServices::ChannelControl(request_stream, handler) => {
            handler.handle_control_request_stream(request_stream).await
        }
    }
}

async fn check_and_set_system_health() {
    if let Err(err) = check_and_set_system_health_impl().await {
        fx_log_err!("error during system health check: {:#}", anyhow!(err));
    }
}

async fn check_and_set_system_health_impl() -> Result<(), Error> {
    system_health_check::check_system_health().await?;
    Ok(system_health_check::set_active_configuration_healthy().await)
}
