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

use {
    anyhow::{format_err, Context as _, Error},
    fidl_fuchsia_netemul_environment::ManagedEnvironmentMarker,
    fidl_fuchsia_netemul_sync::{BusMarker, BusProxy, Event, SyncManagerMarker},
    fuchsia_async as fasync,
    fuchsia_component::client,
    fuchsia_zircon as zx,
    futures::TryStreamExt,
    structopt::StructOpt,
};

#[derive(StructOpt, Debug)]
struct Opt {
    #[structopt(short = "f")]
    fail: bool,
    #[structopt(short = "n", default_value = "root")]
    name: String,
    #[structopt(short = "w")]
    wait: Option<u64>,
    #[structopt(short = "p")]
    publish: Option<i32>,
    #[structopt(short = "e")]
    event: Option<i32>,
    #[structopt(short = "P")]
    check_path: Option<String>,
    #[structopt(short = "s")]
    service: Option<String>,
    #[structopt(short = "l")]
    log: Option<String>,
}

const BUS_NAME: &str = "test-bus";

pub struct BusConnection {
    bus: BusProxy,
}

impl BusConnection {
    pub fn new(client: &str) -> Result<BusConnection, Error> {
        let busm = client::connect_to_service::<SyncManagerMarker>()
            .context("SyncManager not available")?;
        let (bus, busch) = fidl::endpoints::create_proxy::<BusMarker>()?;
        busm.bus_subscribe(BUS_NAME, client, busch)?;
        Ok(BusConnection { bus })
    }

    pub async fn publish_code(&self, code: i32) -> Result<(), Error> {
        let () = self
            .bus
            .ensure_publish(Event {
                code: Some(code),
                message: None,
                arguments: None,
                ..Event::EMPTY
            })
            .await?;
        Ok(())
    }

    pub async fn wait_for_event(&self, code: i32) -> Result<(), Error> {
        let mut stream = self.bus.take_event_stream().try_filter_map(|event| match event {
            fidl_fuchsia_netemul_sync::BusEvent::OnBusData { data } => match data.code {
                Some(rcv_code) => {
                    if rcv_code == code {
                        futures::future::ok(Some(()))
                    } else {
                        futures::future::ok(None)
                    }
                }
                None => futures::future::ok(None),
            },
            fidl_fuchsia_netemul_sync::BusEvent::OnClientAttached { client: _ }
            | fidl_fuchsia_netemul_sync::BusEvent::OnClientDetached { client: _ } => {
                futures::future::ok(None)
            }
        });
        let () = stream.try_next().await?.context("event stream ended unexpectedly")?;
        Ok(())
    }

    pub async fn perform_bus_ops(
        &self,
        publish: Option<i32>,
        wait: Option<i32>,
    ) -> Result<(), Error> {
        if let Some(code) = wait {
            let () = self.wait_for_event(code).await?;
        }
        if let Some(code) = publish {
            let () = self.publish_code(code).await?;
        }
        Ok(())
    }
}

#[fasync::run_singlethreaded]
async fn main() -> Result<(), Error> {
    let opt = Opt::from_args();

    // Attempt to connect to the bus early on so that we do not miss any events.
    //
    // We won't actually unwrap `bus` until later in case this
    // test does not actually need the bus.
    let bus = BusConnection::new(&opt.name);

    if let Some(log) = opt.log {
        println!("Initing syslog...");
        let () = fuchsia_syslog::init().context("cannot init logger")?;

        println!("Logging to syslog: {}", log);
        log::info!("{}", log);
    }

    if let Some(svc) = opt.service {
        println!("Connecting to service [{}]...", svc);
        let env = client::connect_to_service::<ManagedEnvironmentMarker>()?;
        let (_dummy, server) = zx::Channel::create()?;
        env.connect_to_service(&svc, server)?;
    }

    if let Some(wait) = opt.wait {
        println!("Sleeping for {}...", wait);
        std::thread::sleep(std::time::Duration::from_millis(wait));
    }

    if let Some(path) = opt.check_path {
        println!("Checking path existence {}...", &path);
        if !std::path::Path::new(&path).exists() {
            return Err(format_err!("{} is not in namespace", &path));
        }
    }

    if opt.publish != None || opt.event != None {
        // Unwrap the `bus` which should be an error
        // if the test requires publish or event waiting operations.
        let bus = bus.context("Failed to connect to bus")?;

        println!("Publishing: {:?} | Waiting for event: {:?}", opt.publish, opt.event);
        let () = bus.perform_bus_ops(opt.publish, opt.event).await?;
    }

    if opt.fail {
        Err(format_err!("Failing because was asked to."))
    } else {
        println!("All done!");
        Ok(())
    }
}
