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

#![deny(warnings)]
#![feature(async_await, await_macro, futures_api)]

use {
    failure::{format_err, Error, ResultExt},
    fidl::endpoints::{RequestStream, ServiceMarker},
    fidl_fidl_test_compatibility::{
        EchoEvent,
        EchoMarker,
        EchoProxy,
        EchoRequest,
        EchoRequestStream,
    },
    fuchsia_app::{
        client::Launcher,
        client::App,
        server::ServicesServer,
    },
    fuchsia_async as fasync,
    futures::TryStreamExt,
};

fn launch_and_connect_to_echo(launcher: &Launcher, url: String) -> Result<(EchoProxy, App), Error> {
    let app = launcher.launch(url, None)?;
    let echo = app.connect_to_service(EchoMarker)?;
    Ok((echo, app))
}

async fn echo_server(chan: fasync::Channel, launcher: &Launcher) -> Result<(), Error> {
    const CONCURRENT_REQ_LIMIT: Option<usize> = None;
    let handler = move |request| Box::pin(async move {
        match request {
            EchoRequest::EchoStruct { mut value, forward_to_server, responder } => {
                if !forward_to_server.is_empty() {
                    let (echo, app) = launch_and_connect_to_echo(launcher, forward_to_server)
                        .context("Error connecting to proxy")?;
                    value = await!(echo.echo_struct(&mut value, ""))
                        .context("Error calling echo_struct on proxy")?;
                    drop(app);
                }
                responder.send(&mut value)
                    .context("Error responding")?;
            }
            EchoRequest::EchoStructNoRetVal { mut value, forward_to_server, control_handle } => {
                if !forward_to_server.is_empty() {
                    let (echo, app) = launch_and_connect_to_echo(launcher, forward_to_server)
                        .context("Error connecting to proxy")?;
                    echo.echo_struct_no_ret_val(&mut value, "")
                        .context("Error sending echo_struct_no_ret_val to proxy")?;
                    let mut event_stream = echo.take_event_stream();
                    let EchoEvent::EchoEvent { value: response_val } =
                        await!(event_stream.try_next())
                            .context("Error getting event response from proxy")?
                            .ok_or_else(|| format_err!("Proxy sent no events"))?;
                    value = response_val;
                    drop(app);
                }
                control_handle.send_echo_event(&mut value)
                    .context("Error responding with event")?;
            }
        }
        Ok(())
    });

    let handle_requests_fut = EchoRequestStream::from_channel(chan)
        .err_into() // change error type from fidl::Error to failure::Error
        .try_for_each_concurrent(CONCURRENT_REQ_LIMIT, handler);

    await!(handle_requests_fut)
}

fn main() -> Result<(), Error> {
    let mut executor = fasync::Executor::new().context("Error creating executor")?;
    let launcher = Launcher::new().context("Error connecting to application launcher")?;

    let fut = ServicesServer::new()
        .add_service((EchoMarker::NAME, move |chan| {
            let launcher = launcher.clone();
            fasync::spawn(async move {
                if let Err(e) = await!(echo_server(chan, &launcher)) {
                    eprintln!("Closing echo server {:?}", e);
                }
            })
        }))
        .start()
        .context("Error starting compatibility echo ServicesServer")?;

    executor.run_singlethreaded(fut).context("failed to execute echo future")?;
    Ok(())
}
