// 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::cobalt,
    fidl::endpoints::{create_proxy, ServerEnd},
    fidl_fuchsia_component as fcomponent, fidl_fuchsia_io as fio, fidl_fuchsia_session as fsession,
    fuchsia_async as fasync, fuchsia_zircon as zx,
    thiserror::Error,
    tracing::info,
};

/// Errors returned by calls startup functions.
#[derive(Debug, Error, Clone, PartialEq)]
pub enum StartupError {
    #[error("Existing session not destroyed at \"{}/{}\": {:?}", collection, name, err)]
    NotDestroyed { name: String, collection: String, err: fcomponent::Error },

    #[error("Session {} not created at \"{}/{}\": {:?}", url, collection, name, err)]
    NotCreated { name: String, collection: String, url: String, err: fcomponent::Error },

    #[error(
        "Exposed directory of session {} at \"{}/{}\" not opened: {:?}",
        url,
        collection,
        name,
        err
    )]
    ExposedDirNotOpened { name: String, collection: String, url: String, err: fcomponent::Error },

    #[error("Session {} not launched at \"{}/{}\": {:?}", url, collection, name, err)]
    NotLaunched { name: String, collection: String, url: String, err: fcomponent::Error },

    #[error("Attempt to restart a not running session")]
    NotRunning,
}

impl Into<fsession::LaunchError> for StartupError {
    fn into(self) -> fsession::LaunchError {
        match self {
            StartupError::NotDestroyed { .. } => fsession::LaunchError::DestroyComponentFailed,
            StartupError::NotCreated { err, .. } => match err {
                fcomponent::Error::InstanceCannotResolve => fsession::LaunchError::NotFound,
                _ => fsession::LaunchError::CreateComponentFailed,
            },
            StartupError::ExposedDirNotOpened { .. } => {
                fsession::LaunchError::CreateComponentFailed
            }
            StartupError::NotLaunched { .. } => fsession::LaunchError::CreateComponentFailed,
            StartupError::NotRunning => fsession::LaunchError::NotFound,
        }
    }
}

impl Into<fsession::RestartError> for StartupError {
    fn into(self) -> fsession::RestartError {
        match self {
            StartupError::NotDestroyed { .. } => fsession::RestartError::DestroyComponentFailed,
            StartupError::NotCreated { err, .. } => match err {
                fcomponent::Error::InstanceCannotResolve => fsession::RestartError::NotFound,
                _ => fsession::RestartError::CreateComponentFailed,
            },
            StartupError::ExposedDirNotOpened { .. } => {
                fsession::RestartError::CreateComponentFailed
            }
            StartupError::NotLaunched { .. } => fsession::RestartError::CreateComponentFailed,
            StartupError::NotRunning => fsession::RestartError::NotRunning,
        }
    }
}

impl Into<fsession::LifecycleError> for StartupError {
    fn into(self) -> fsession::LifecycleError {
        match self {
            StartupError::NotDestroyed { .. } => fsession::LifecycleError::DestroyComponentFailed,
            StartupError::NotCreated { err, .. } => match err {
                fcomponent::Error::InstanceCannotResolve => {
                    fsession::LifecycleError::ResolveComponentFailed
                }
                _ => fsession::LifecycleError::CreateComponentFailed,
            },
            StartupError::ExposedDirNotOpened { .. } => {
                fsession::LifecycleError::CreateComponentFailed
            }
            StartupError::NotLaunched { .. } => fsession::LifecycleError::CreateComponentFailed,
            StartupError::NotRunning => fsession::LifecycleError::NotFound,
        }
    }
}

/// The name of the session child component.
const SESSION_NAME: &str = "session";

/// The name of the child collection the session is added to, must match the declaration in
/// session_manager.cml.
const SESSION_CHILD_COLLECTION: &str = "session";

/// Launches the specified session.
///
/// Any existing session child will be destroyed prior to launching the new session.
///
/// Returns a controller for the session component, or an error.
///
/// # Parameters
/// - `session_url`: The URL of the session to launch.
/// - `exposed_dir`: The server end on which to serve the session's exposed directory.
/// - `realm`: The realm in which to launch the session.
///
/// # Errors
/// If there was a problem creating or binding to the session component instance.
pub async fn launch_session(
    session_url: &str,
    exposed_dir: ServerEnd<fio::DirectoryMarker>,
    realm: &fcomponent::RealmProxy,
) -> Result<fcomponent::ExecutionControllerProxy, StartupError> {
    info!(session_url, "Launching session");

    let start_time = zx::Time::get_monotonic();
    let controller = set_session(&session_url, realm, exposed_dir).await?;
    let end_time = zx::Time::get_monotonic();

    fasync::Task::local(async move {
        if let Ok(cobalt_logger) = cobalt::get_logger() {
            // The result is disregarded as there is not retry-logic if it fails, and the error is
            // not meant to be fatal.
            let _ = cobalt::log_session_launch_time(cobalt_logger, start_time, end_time).await;
        }
    })
    .detach();

    Ok(controller)
}

/// Stops the current session, if any.
///
/// # Parameters
/// - `realm`: The realm in which the session exists.
///
/// # Errors
/// `StartupError::NotDestroyed` if the session component could not be destroyed.
pub async fn stop_session(realm: &fcomponent::RealmProxy) -> Result<(), StartupError> {
    realm_management::destroy_child_component(SESSION_NAME, SESSION_CHILD_COLLECTION, realm)
        .await
        .map_err(|err| StartupError::NotDestroyed {
            name: SESSION_NAME.to_string(),
            collection: SESSION_CHILD_COLLECTION.to_string(),
            err,
        })
}

/// Sets the currently active session.
///
/// If an existing session is running, the session's component instance will be destroyed prior to
/// creating the new session, effectively replacing the session.
///
/// # Parameters
/// - `session_url`: The URL of the session to instantiate.
/// - `realm`: The realm in which to create the session.
/// - `exposed_dir`: The server end on which the session's exposed directory will be served.
///
/// # Errors
/// Returns an error if any of the realm operations fail, or the realm is unavailable.
async fn set_session(
    session_url: &str,
    realm: &fcomponent::RealmProxy,
    exposed_dir: ServerEnd<fio::DirectoryMarker>,
) -> Result<fcomponent::ExecutionControllerProxy, StartupError> {
    realm_management::destroy_child_component(SESSION_NAME, SESSION_CHILD_COLLECTION, realm)
        .await
        .or_else(|err: fcomponent::Error| match err {
            // Since the intent is simply to clear out the existing session child if it exists,
            // related errors are disregarded.
            fcomponent::Error::InvalidArguments
            | fcomponent::Error::InstanceNotFound
            | fcomponent::Error::CollectionNotFound => Ok(()),
            _ => Err(err),
        })
        .map_err(|err| StartupError::NotDestroyed {
            name: SESSION_NAME.to_string(),
            collection: SESSION_CHILD_COLLECTION.to_string(),
            err,
        })?;

    let (controller, controller_server_end) =
        create_proxy::<fcomponent::ControllerMarker>().unwrap();
    let create_child_args = fcomponent::CreateChildArgs {
        controller: Some(controller_server_end),
        ..Default::default()
    };
    realm_management::create_child_component(
        SESSION_NAME,
        &session_url,
        SESSION_CHILD_COLLECTION,
        create_child_args,
        realm,
    )
    .await
    .map_err(|err| StartupError::NotCreated {
        name: SESSION_NAME.to_string(),
        collection: SESSION_CHILD_COLLECTION.to_string(),
        url: session_url.to_string(),
        err,
    })?;

    realm_management::open_child_component_exposed_dir(
        SESSION_NAME,
        SESSION_CHILD_COLLECTION,
        realm,
        exposed_dir,
    )
    .await
    .map_err(|err| StartupError::ExposedDirNotOpened {
        name: SESSION_NAME.to_string(),
        collection: SESSION_CHILD_COLLECTION.to_string(),
        url: session_url.to_string(),
        err,
    })?;

    // Start the component.
    let (execution_controller, execution_controller_server_end) =
        create_proxy::<fcomponent::ExecutionControllerMarker>().unwrap();
    controller
        .start(fcomponent::StartChildArgs::default(), execution_controller_server_end)
        .await
        .map_err(|_| fcomponent::Error::Internal)
        .and_then(std::convert::identity)
        .map_err(|_err| StartupError::NotLaunched {
            name: SESSION_NAME.to_string(),
            collection: SESSION_CHILD_COLLECTION.to_string(),
            url: session_url.to_string(),
            err: fcomponent::Error::InstanceCannotStart,
        })?;

    Ok(execution_controller)
}

#[cfg(test)]
mod tests {
    use {
        super::{set_session, stop_session, SESSION_CHILD_COLLECTION, SESSION_NAME},
        anyhow::Error,
        fidl::endpoints::{create_endpoints, spawn_stream_handler},
        fidl_fuchsia_component as fcomponent, fidl_fuchsia_io as fio,
        lazy_static::lazy_static,
        session_testing::{spawn_directory_server, spawn_server},
        test_util::Counter,
    };

    #[fuchsia::test]
    async fn set_session_calls_realm_methods_in_appropriate_order() -> Result<(), Error> {
        lazy_static! {
            // The number of realm calls which have been made so far.
            static ref NUM_REALM_REQUESTS: Counter = Counter::new(0);
        }

        let session_url = "session";

        let directory_request_handler = move |directory_request| match directory_request {
            fio::DirectoryRequest::Open { path: _, .. } => {
                assert_eq!(NUM_REALM_REQUESTS.get(), 4);
            }
            _ => panic!("Directory handler received an unexpected request"),
        };

        let realm = spawn_stream_handler(move |realm_request| async move {
            match realm_request {
                fcomponent::RealmRequest::DestroyChild { child, responder } => {
                    assert_eq!(NUM_REALM_REQUESTS.get(), 0);
                    assert_eq!(child.collection, Some(SESSION_CHILD_COLLECTION.to_string()));
                    assert_eq!(child.name, SESSION_NAME);

                    let _ = responder.send(Ok(()));
                }
                fcomponent::RealmRequest::CreateChild { collection, decl, args, responder } => {
                    assert_eq!(NUM_REALM_REQUESTS.get(), 1);
                    assert_eq!(decl.url.unwrap(), session_url);
                    assert_eq!(decl.name.unwrap(), SESSION_NAME);
                    assert_eq!(&collection.name, SESSION_CHILD_COLLECTION);

                    spawn_server(args.controller.unwrap(), move |controller_request| {
                        match controller_request {
                            fcomponent::ControllerRequest::Start { responder, .. } => {
                                let _ = responder.send(Ok(()));
                            }
                            fcomponent::ControllerRequest::IsStarted { .. } => unimplemented!(),
                            fcomponent::ControllerRequest::GetExposedDictionary { .. } => {
                                unimplemented!()
                            }
                            fcomponent::ControllerRequest::_UnknownMethod { .. } => {
                                unimplemented!()
                            }
                        }
                    });

                    let _ = responder.send(Ok(()));
                }
                fcomponent::RealmRequest::OpenExposedDir { child, exposed_dir, responder } => {
                    assert_eq!(NUM_REALM_REQUESTS.get(), 2);
                    assert_eq!(child.collection, Some(SESSION_CHILD_COLLECTION.to_string()));
                    assert_eq!(child.name, SESSION_NAME);

                    spawn_directory_server(exposed_dir, directory_request_handler);
                    let _ = responder.send(Ok(()));
                }
                _ => panic!("Realm handler received an unexpected request"),
            };
            NUM_REALM_REQUESTS.inc();
        })?;

        let (_exposed_dir, exposed_dir_server_end) = create_endpoints::<fio::DirectoryMarker>();
        let _controller = set_session(session_url, &realm, exposed_dir_server_end).await?;

        Ok(())
    }

    #[fuchsia::test]
    async fn set_session_starts_component() -> Result<(), Error> {
        lazy_static! {
            static ref NUM_START_CALLS: Counter = Counter::new(0);
        }

        let session_url = "session";

        let realm = spawn_stream_handler(move |realm_request| async move {
            match realm_request {
                fcomponent::RealmRequest::DestroyChild { responder, .. } => {
                    let _ = responder.send(Ok(()));
                }
                fcomponent::RealmRequest::CreateChild { args, responder, .. } => {
                    spawn_server(args.controller.unwrap(), move |controller_request| {
                        match controller_request {
                            fcomponent::ControllerRequest::Start { responder, .. } => {
                                NUM_START_CALLS.inc();
                                let _ = responder.send(Ok(()));
                            }
                            fcomponent::ControllerRequest::IsStarted { .. } => unimplemented!(),
                            fcomponent::ControllerRequest::GetExposedDictionary { .. } => {
                                unimplemented!()
                            }
                            fcomponent::ControllerRequest::_UnknownMethod { .. } => {
                                unimplemented!()
                            }
                        }
                    });
                    let _ = responder.send(Ok(()));
                }
                fcomponent::RealmRequest::OpenExposedDir { responder, .. } => {
                    let _ = responder.send(Ok(()));
                }
                _ => panic!("Realm handler received an unexpected request"),
            };
        })?;

        let (_exposed_dir, exposed_dir_server_end) = create_endpoints::<fio::DirectoryMarker>();
        let _controller = set_session(session_url, &realm, exposed_dir_server_end).await?;
        assert_eq!(NUM_START_CALLS.get(), 1);

        Ok(())
    }

    #[fuchsia::test]
    async fn stop_session_calls_destroy_child() -> Result<(), Error> {
        lazy_static! {
            static ref NUM_DESTROY_CHILD_CALLS: Counter = Counter::new(0);
        }

        let realm = spawn_stream_handler(move |realm_request| async move {
            match realm_request {
                fcomponent::RealmRequest::DestroyChild { child, responder } => {
                    assert_eq!(NUM_DESTROY_CHILD_CALLS.get(), 0);
                    assert_eq!(child.collection, Some(SESSION_CHILD_COLLECTION.to_string()));
                    assert_eq!(child.name, SESSION_NAME);

                    let _ = responder.send(Ok(()));
                }
                _ => panic!("Realm handler received an unexpected request"),
            };
            NUM_DESTROY_CHILD_CALLS.inc();
        })?;

        stop_session(&realm).await?;
        assert_eq!(NUM_DESTROY_CHILD_CALLS.get(), 1);

        Ok(())
    }
}
