// 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 crate::view::{NewViewParams, ViewAssistantPtr, ViewController, ViewControllerPtr, ViewKey};
use failure::{Error, ResultExt};
use fidl::endpoints::{RequestStream, ServerEnd, ServiceMarker};
use fidl_fuchsia_ui_app as viewsv2;
use fidl_fuchsia_ui_viewsv1::{
    ViewManagerMarker, ViewManagerProxy, ViewProviderMarker, ViewProviderRequest::CreateView,
    ViewProviderRequestStream,
};
use fidl_fuchsia_ui_viewsv1token::ViewOwnerMarker;
use fuchsia_app::{self as component, client::connect_to_service, server::FdioServer};
use fuchsia_async as fasync;
use fuchsia_scenic::SessionPtr;
use fuchsia_zircon::EventPair;
use futures::{TryFutureExt, TryStreamExt};
use lazy_static::lazy_static;
use parking_lot::Mutex;
use std::{any::Any, collections::BTreeMap, sync::Arc};

/// Trait that a mod author must implement. Currently responsible for creating
/// a view assistant when the Fuchsia view framework requests that the mod create
/// a view.
pub trait AppAssistant: Send {
    /// This method is responsible for setting up the AppAssistant implementation.
    /// _It's not clear if this is going to so useful, as anything that isn't
    /// initialized in the creation of the structure implementing AppAssistant
    /// is going to have to be represented as an `Option`, which is awkward._
    fn setup(&mut self) -> Result<(), Error>;

    /// Called when the Fuchsia view system requests that a view be created.
    fn create_view_assistant(&mut self, session: &SessionPtr) -> Result<ViewAssistantPtr, Error>;
}

pub type AppAssistantPtr = Mutex<Box<dyn AppAssistant>>;

/// Struct that implements module-wide responsibilties, currently limited
/// to creating views on request.
pub struct App {
    pub(crate) view_manager: ViewManagerProxy,
    view_controllers: BTreeMap<ViewKey, ViewControllerPtr>,
    next_key: ViewKey,
    assistant: Option<AppAssistantPtr>,
}

/// Reference to the singleton app. _This type is likely to change in the future so
/// using this type alias might make for easier forward migration._
pub type AppPtr = Arc<Mutex<App>>;

lazy_static! {
    /// Singleton reference to the running application
    pub static ref APP: AppPtr = App::new().expect("Failed to create app");
}

impl App {
    fn new() -> Result<AppPtr, Error> {
        let view_manager = connect_to_service::<ViewManagerMarker>()?;
        Ok(Arc::new(Mutex::new(App {
            view_manager,
            view_controllers: BTreeMap::new(),
            next_key: 0,
            assistant: None,
        })))
    }

    /// Starts an application based on fuchsia-ui. The `assistant` parameter will
    /// be used to create new views when asked to do so by the Fuchsia view system.
    pub fn run(assistant: Box<AppAssistant>) -> Result<(), Error> {
        let mut executor = fasync::Executor::new().context("Error creating executor")?;

        APP.lock().set_assistant(Mutex::new(assistant));

        let fut = Self::start_services(&APP)?;

        APP.lock().assistant.as_ref().unwrap().lock().setup()?;

        executor.run_singlethreaded(fut)?;

        Ok(())
    }

    fn set_assistant(&mut self, assistant: AppAssistantPtr) {
        self.assistant = Some(assistant);
    }

    /// Method for app and view assistants to use from closures in
    /// order to reconnect with a specific `ViewController`.
    pub fn find_view_controller(&self, key: ViewKey) -> Option<&ViewControllerPtr> {
        self.view_controllers.get(&key)
    }

    /// Send a message to a specific view controller. Messages not handled by the ViewController
    /// will be forwarded to the `ViewControllerAssistant`.
    pub fn send_message(&mut self, target: ViewKey, msg: &Any) {
        if let Some(view) = self.view_controllers.get(&target) {
            view.lock().send_message(msg);
        }
    }

    pub(crate) fn create_view_assistant(
        &mut self, session: &SessionPtr,
    ) -> Result<ViewAssistantPtr, Error> {
        Ok(self
            .assistant
            .as_ref()
            .unwrap()
            .lock()
            .create_view_assistant(session)?)
    }

    fn create_view(&mut self, req: ServerEnd<ViewOwnerMarker>) -> Result<(), Error> {
        let view_controller = ViewController::new(self, NewViewParams::V1(req), self.next_key)?;
        self.view_controllers.insert(self.next_key, view_controller);
        self.next_key += 1;
        Ok(())
    }

    fn create_view2(&mut self, view_token: EventPair) -> Result<(), Error> {
        let view_controller =
            ViewController::new(self, NewViewParams::V2(view_token), self.next_key)?;
        self.view_controllers.insert(self.next_key, view_controller);
        self.next_key += 1;
        Ok(())
    }

    fn spawn_view_provider_server(chan: fasync::Channel, app: &AppPtr) {
        let app = app.clone();
        fasync::spawn(
            ViewProviderRequestStream::from_channel(chan)
                .try_for_each(move |req| {
                    let CreateView { view_owner, .. } = req;
                    app.lock()
                        .create_view(view_owner)
                        .unwrap_or_else(|e| eprintln!("create_view error: {:?}", e));
                    futures::future::ready(Ok(()))
                })
                .unwrap_or_else(|e| eprintln!("error running view_provider server: {:?}", e)),
        )
    }

    fn spawn_v2_view_provider_server(chan: fasync::Channel, app: &AppPtr) {
        let app = app.clone();
        fasync::spawn(
            viewsv2::ViewProviderRequestStream::from_channel(chan)
                .try_for_each(move |req| {
                    let viewsv2::ViewProviderRequest::CreateView { token, .. } = req;
                    app.lock()
                        .create_view2(token)
                        .unwrap_or_else(|e| eprintln!("create_view2 error: {:?}", e));
                    futures::future::ready(Ok(()))
                })
                .unwrap_or_else(|e| eprintln!("error running V2 view_provider server: {:?}", e)),
        )
    }

    fn start_services(app: &AppPtr) -> Result<FdioServer, Error> {
        let app_view_provider = app.clone();
        let app_view_provider2 = app.clone();
        let services_server = component::server::ServicesServer::new();
        let services_server = services_server
            .add_service((ViewProviderMarker::NAME, move |channel| {
                Self::spawn_view_provider_server(channel, &app_view_provider);
            }))
            .add_service((viewsv2::ViewProviderMarker::NAME, move |channel| {
                Self::spawn_v2_view_provider_server(channel, &app_view_provider2);
            }));
        Ok(services_server.start()?)
    }
}
