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

#![recursion_limit = "256"]

mod client;
mod config;
mod config_manager;
mod device;
mod fuse_pending;
mod known_ess_store;
mod network_config;
mod policy;
mod shim;
mod stash;
mod state_machine;

use {
    crate::{config::Config, config_manager::SavedNetworksManager, known_ess_store::KnownEssStore},
    anyhow::{format_err, Context as _, Error},
    fidl_fuchsia_wlan_device_service::DeviceServiceMarker,
    fuchsia_async as fasync,
    fuchsia_component::server::ServiceFs,
    futures::{channel::mpsc, future::try_join, prelude::*, select},
    parking_lot::Mutex,
    pin_utils::pin_mut,
    std::sync::Arc,
    void::Void,
};

async fn serve_fidl(
    _client_ref: shim::ClientRef,
    ess_store: Arc<KnownEssStore>,
    saved_networks: Arc<SavedNetworksManager>,
) -> Result<Void, Error> {
    let mut fs = ServiceFs::new();
    let (listener_msg_sender, listener_msgs) = mpsc::unbounded();
    let listener_msg_sender1 = listener_msg_sender.clone();
    let listener_msg_sender2 = listener_msg_sender.clone();
    let saved_networks_clone = Arc::clone(&saved_networks);
    fs.dir("svc")
        .add_fidl_service(|stream| {
            let fut = shim::serve_legacy(
                stream,
                _client_ref.clone(),
                Arc::clone(&ess_store),
                Arc::clone(&saved_networks),
            )
            .unwrap_or_else(|e| eprintln!("error serving legacy wlan API: {}", e));
            fasync::spawn(fut)
        })
        .add_fidl_service(move |reqs| {
            policy::client::spawn_provider_server(
                Arc::new(Mutex::new(policy::client::Client::new_empty())),
                listener_msg_sender1.clone(),
                Arc::clone(&saved_networks_clone),
                reqs,
            )
        })
        .add_fidl_service(move |reqs| {
            policy::client::spawn_listener_server(listener_msg_sender2.clone(), reqs)
        });
    fs.take_and_serve_directory_handle()?;
    let service_fut = fs.collect::<()>().fuse();
    pin_mut!(service_fut);

    let serve_policy_listeners = policy::client::listener::serve(listener_msgs).fuse();
    pin_mut!(serve_policy_listeners);

    loop {
        select! {
            _ = service_fut => (),
            _ = serve_policy_listeners => (),
        }
    }
}

fn main() -> Result<(), Error> {
    let cfg = Config::load_from_file()?;

    let mut executor = fasync::Executor::new().context("error create event loop")?;
    let wlan_svc = fuchsia_component::client::connect_to_service::<DeviceServiceMarker>()
        .context("failed to connect to device service")?;

    let ess_store = Arc::new(KnownEssStore::new()?);
    let saved_networks = Arc::new(SavedNetworksManager::new()?);
    let legacy_client = shim::ClientRef::new();
    let fidl_fut =
        serve_fidl(legacy_client.clone(), Arc::clone(&ess_store), Arc::clone(&saved_networks));

    let (watcher_proxy, watcher_server_end) = fidl::endpoints::create_proxy()?;
    wlan_svc.watch_devices(watcher_server_end)?;
    let listener = device::Listener::new(wlan_svc, cfg, legacy_client);
    let fut = watcher_proxy
        .take_event_stream()
        .try_for_each(|evt| {
            device::handle_event(
                &listener,
                evt,
                Arc::clone(&ess_store),
                Arc::clone(&saved_networks),
            )
            .map(Ok)
        })
        .err_into()
        .and_then(|_| future::ready(Err(format_err!("Device watcher future exited unexpectedly"))));

    executor.run_singlethreaded(try_join(fidl_fut, fut)).map(|_: (Void, Void)| ())
}
