// 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::{Context as _, Error};
use fidl_fuchsia_testing_sl4f::{
    FacadeIteratorMarker, FacadeIteratorSynchronousProxy, FacadeProviderMarker, FacadeProviderProxy,
};
use fuchsia_component::client::connect_to_protocol;
use fuchsia_sync::RwLock;
use fuchsia_zircon as zx;
use maplit::{convert_args, hashmap};
use serde_json::{json, Value};
use std::collections::{HashMap, HashSet};
use std::sync::Arc;
use tracing::{error, info, warn};

// Standardized sl4f types and constants
use crate::{
    bluetooth::avrcp_facade::AvrcpFacade,
    server::sl4f_types::{
        AsyncCommandRequest, AsyncRequest, ClientData, CommandRequest, CommandResponse, Facade,
        MethodId, RequestId,
    },
};

// Audio related includes
use crate::audio::commands::AudioFacade;

// Session related includes
use crate::modular::facade::ModularFacade;

// Bluetooth related includes
use crate::bluetooth::a2dp_facade::A2dpFacade;
use crate::bluetooth::avdtp_facade::AvdtpFacade;
use crate::bluetooth::ble_advertise_facade::BleAdvertiseFacade;
use crate::bluetooth::bt_sys_facade::BluetoothSysFacade;
use crate::bluetooth::gatt_client_facade::GattClientFacade;
use crate::bluetooth::gatt_server_facade::GattServerFacade;
use test_call_manager::TestCallManager as HfpFacade;
use test_rfcomm_client::RfcommManager as RfcommFacade;

use crate::bluetooth::profile_server_facade::ProfileServerFacade;

// Common
use crate::common_utils::common::{read_json_from_vmo, write_json_to_vmo};
use crate::common_utils::error::Sl4fError;

// Component related includes
use crate::component::facade::ComponentFacade;

// Device related includes
use crate::device::facade::DeviceFacade;

// Diagnostics related includes
use crate::diagnostics::facade::DiagnosticsFacade;

// Factory reset related includes
use crate::factory_reset::facade::FactoryResetFacade;

// Factory related includes
use crate::factory_store::facade::FactoryStoreFacade;

// Feedback related includes
use crate::feedback_data_provider::facade::FeedbackDataProviderFacade;

// File related includes
use crate::file::facade::FileFacade;

use crate::flatland_example::facade::FlatlandExampleFacade;

// Device Manager related includes
use crate::hardware_power_statecontrol::facade::HardwarePowerStatecontrolFacade;

// Hwinfo related includes
use crate::hwinfo::facade::HwinfoFacade;

// Input related includes
use crate::input::facade::InputFacade;

// Location related includes
use crate::location::emergency_provider_facade::EmergencyProviderFacade;
use crate::location::regulatory_region_facade::RegulatoryRegionFacade;

// Logging related includes
use crate::logging::facade::LoggingFacade;

// Media session related includes
use crate::media_session::facade::MediaSessionFacade;

// Netstack related includes
use crate::netstack::facade::NetstackFacade;

// Paver related includes
use crate::paver::facade::PaverFacade;

// Power related includes
use crate::power::facade::PowerFacade;

// Proxy related includes
use crate::proxy::facade::ProxyFacade;

// Scenic related includes
use crate::scenic::facade::ScenicFacade;

// SetUi related includes
use crate::setui::facade::SetUiFacade;

// System Metrics related includes
use crate::system_metrics::facade::SystemMetricsFacade;

// Temperature related includes
use crate::temperature::facade::TemperatureFacade;

// Time related includes
use crate::time::facade::TimeFacade;

// Traceutil related includes
use crate::traceutil::facade::TraceutilFacade;

// Tracing related includes
use crate::tracing::facade::TracingFacade;

// Virtual Camera Device related includes
use crate::virtual_camera::facade::VirtualCameraFacade;

// Weave related includes
use crate::weave::facade::WeaveFacade;

// Webdriver related includes
use crate::webdriver::facade::WebdriverFacade;

// Wlan related includes
use crate::wlan::facade::WlanFacade;

// Wlan DeprecatedConfiguration related includes
use crate::wlan_deprecated::facade::WlanDeprecatedConfigurationFacade;

// WlanPhy related includes
use crate::wlan_phy::facade::WlanPhyFacade;

// Wlan Policy related includes
use crate::wlan_policy::ap_facade::WlanApPolicyFacade;
use crate::wlan_policy::facade::WlanPolicyFacade;

// Wpan related includes
use crate::wpan::facade::WpanFacade;

/// Sl4f stores state for all facades and has access to information for all connected clients.
///
/// To add support for a new Facade implementation, see the hashmap in `Sl4f::new`.
#[derive(Debug)]
pub struct Sl4f {
    // facades: Mapping of method prefix to object implementing that facade's API.
    facades: HashMap<String, Arc<dyn Facade>>,

    // NOTE: facade_provider and proxied_facades will eventually become a map from proxied facade
    // to `FacadeProvider` client once we have support for multiple `FacadeProvider` instances.
    // facade_provider: Channel to the `FacadeProvider` instance hosting private facades.
    facade_provider: FacadeProviderProxy,

    // proxied_facades: Set of facades hosted by facade_provider. May be empty.
    proxied_facades: HashSet<String>,

    // connected clients
    clients: Arc<RwLock<Sl4fClients>>,
}

impl Sl4f {
    pub fn new(clients: Arc<RwLock<Sl4fClients>>) -> Result<Sl4f, Error> {
        fn to_arc_trait_object<'a, T: Facade + 'a>(facade: T) -> Arc<dyn Facade + 'a> {
            Arc::new(facade) as Arc<dyn Facade>
        }
        // To add support for a new facade, define a new submodule with the Facade implementation
        // and construct an instance and include it in the mapping below. The key is used to route
        // requests to the appropriate Facade. Facade constructors should generally not fail, as a
        // facade that returns an error here will prevent sl4f from starting.
        let facades = convert_args!(
            keys = String::from,
            values = to_arc_trait_object,
            hashmap!(
                "a2dp_facade" => A2dpFacade::new(),
                "audio_facade" => AudioFacade::new()?,
                "avdtp_facade" => AvdtpFacade::new(),
                "avrcp_facade" => AvrcpFacade::new(),
                // TODO(https://fxbug.dev/42157579): Remove basemgr_facade in favor of modular_facade
                "basemgr_facade" => ModularFacade::new(),
                "modular_facade" => ModularFacade::new(),
                "ble_advertise_facade" => BleAdvertiseFacade::new(),
                "bt_sys_facade" => BluetoothSysFacade::new(),
                "component_facade" => ComponentFacade::new(),
                "diagnostics_facade" => DiagnosticsFacade::new(),
                "device_facade" => DeviceFacade::new(),
                "factory_reset_facade" => FactoryResetFacade::new(),
                "factory_store_facade" => FactoryStoreFacade::new(),
                "feedback_data_provider_facade" => FeedbackDataProviderFacade::new(),
                "file_facade" => FileFacade::new(),
                "flatland_example_facade" => FlatlandExampleFacade::new(),
                "gatt_client_facade" => GattClientFacade::new(),
                "gatt_server_facade" => GattServerFacade::new(),
                "hardware_power_statecontrol_facade" => HardwarePowerStatecontrolFacade::new(),
                "hfp_facade" => HfpFacade::new(),
                "hwinfo_facade" => HwinfoFacade::new(),
                "input_facade" => InputFacade::new(),
                "location_emergency_provider_facade" => EmergencyProviderFacade::new()?,
                "location_regulatory_region_facade" => RegulatoryRegionFacade::new()?,
                "logging_facade" => LoggingFacade::new(),
                "media_session_facade" => MediaSessionFacade::new(),
                "netstack_facade" => NetstackFacade::default(),
                "rfcomm_facade" => RfcommFacade::new()?,
                "paver" => PaverFacade::new(),
                "power_facade" => PowerFacade::new(),
                "profile_server_facade" => ProfileServerFacade::new(),
                "proxy_facade" => ProxyFacade::new(),
                "scenic_facade" => ScenicFacade::new(),
                "setui_facade" => SetUiFacade::new(),
                "system_metrics_facade" => SystemMetricsFacade::new(),
                "temperature_facade" => TemperatureFacade::new(),
                "time_facade" => TimeFacade::new(),
                "traceutil_facade" => TraceutilFacade::new(),
                "tracing_facade" => TracingFacade::new(),
                "virtual_camera_facade" => VirtualCameraFacade::new(),
                "weave_facade" => WeaveFacade::new(),
                "webdriver_facade" => WebdriverFacade::new(),
                "wlan" => WlanFacade::new()?,
                "wlan_ap_policy" => WlanApPolicyFacade::new()?,
                "wlan_deprecated" => WlanDeprecatedConfigurationFacade::new()?,
                "wlan_phy" => WlanPhyFacade::new()?,
                "wlan_policy" => WlanPolicyFacade::new()?,
                "wpan_facade" => WpanFacade::new(),
            )
        );

        // Attempt to connect to the single `FacadeProvider` instance.
        let mut proxied_facades = HashSet::<String>::new();
        let facade_provider = match connect_to_protocol::<FacadeProviderMarker>() {
            Ok(proxy) => proxy,
            Err(error) => {
                error!(%error, "Failed to connect to FacadeProvider");
                return Err(error.into());
            }
        };
        // Get the names of the facades hosted by the `FacadeProvider`.
        // NOTE: Due to the inability to actively verify that connection succeeds, there are
        // multiple layers of error checking at which a PEER_CLOSED means that there never was a
        // `FacadeProvider` to connect to.
        let (client_end, server_end) = fidl::endpoints::create_endpoints::<FacadeIteratorMarker>();
        match facade_provider.get_facades(server_end) {
            Ok(_) => {
                let facade_iter = FacadeIteratorSynchronousProxy::new(client_end.into_channel());
                loop {
                    match facade_iter.get_next(zx::Time::INFINITE) {
                        Ok(facades) if facades.is_empty() => break, // Indicates completion.
                        Ok(facades) => proxied_facades.extend(facades.into_iter()),
                        // A PEER_CLOSED error before any facades are read indicates that there was
                        // never a successful connection.
                        Err(error) if error.is_closed() && proxied_facades.is_empty() => {
                            break;
                        }
                        Err(error) => {
                            error!(%error, "Failed to get proxied facade list");
                            proxied_facades.clear();
                            break;
                        }
                    };
                }
            }
            // The channel's server end was closed due to no `FacadeProvider` instance.
            Err(error) if error.is_closed() => (),
            Err(error) => {
                error!(%error, "Failed to get FacadeIterator");
                return Err(error.into());
            }
        };

        Ok(Sl4f { facades, facade_provider, proxied_facades, clients })
    }

    /// Gets the facade registered with the given name, if one exists.
    pub fn get_facade(&self, name: &str) -> Option<Arc<dyn Facade>> {
        self.facades.get(name).map(Arc::clone)
    }

    /// Implement the Facade trait method cleanup() to clean up state when "/cleanup" is queried.
    pub async fn cleanup(&self) {
        for facade in self.facades.values() {
            facade.cleanup();
        }
        // If there are any proxied facades, make a synchronous request to cleanup transient state.
        if !self.proxied_facades.is_empty() {
            if let Err(error) = self.facade_provider.cleanup().await {
                error!(%error, "Failed to execute Cleanup()");
            }
        }
        self.clients.write().cleanup_clients();
    }

    pub fn print_clients(&self) {
        self.clients.read().print_clients();
    }

    /// Implement the Facade trait method print() to log state when "/print" is queried.
    pub async fn print(&self) {
        for facade in self.facades.values() {
            facade.print();
        }
        // If there are any proxied facades, make a synchronous request to print state.
        if !self.proxied_facades.is_empty() {
            if let Err(error) = self.facade_provider.print().await {
                error!(%error, "Failed to execute Print()");
            }
        }
    }

    /// Returns true if the facade with the given name is hosted by a registered `FacadeProvider`.
    /// # Arguments
    /// * 'name' - A string representing the name of the facade.
    pub fn has_proxy_facade(&self, name: &str) -> bool {
        self.proxied_facades.contains(name)
    }

    /// Sends a request on a facade hosted by a registered `FacadeProvider` and waits
    /// asynchronously for the response.
    /// # Arguments
    /// * 'facade' - A string representing the name of the facade.
    /// * 'command' - A string representing the command to execute on the facade.
    /// * 'args' - An arbitrary JSON Value containing any arguments to the command.
    pub async fn handle_proxy_request(
        &self,
        facade: String,
        command: String,
        args: Value,
    ) -> Result<Value, Error> {
        // Populate a new VMO with a JSON blob containing the arguments.
        let encode_params = async {
            let params_blob = zx::Vmo::create_with_opts(zx::VmoOptions::RESIZABLE, 0)?;
            write_json_to_vmo(&params_blob, &args)?;
            Ok::<zx::Vmo, Error>(params_blob)
        };
        let params_blob = match encode_params.await {
            Ok(params_blob) => params_blob,
            Err(error) => {
                return Err(
                    Sl4fError::new(&format!("Failed to write params with: {}", error)).into()
                );
            }
        };

        // Forward the request to the `FacadeProvider`.
        match self.facade_provider.execute(&facade, &command, params_blob).await {
            // Success with no response.
            Ok((None, None)) => Ok(Value::Null),
            // Success with response. The JSON blob must be read out from the returned VMO.
            Ok((Some(vmo), None)) => match read_json_from_vmo(&vmo) {
                Ok(result) => Ok(result),
                Err(error) => {
                    Err(Sl4fError::new(&format!("Failed to read result with: {}", error)).into())
                }
            },
            // The command failed. Return the error string.
            Ok((_, Some(string))) => Err(Sl4fError::new(&string).into()),
            Err(error) => {
                Err(Sl4fError::new(&format!("Failed to send command with {}", error)).into())
            }
        }
    }
}

/// Metadata for clients utilizing the /init API.
#[derive(Debug)]
pub struct Sl4fClients {
    // clients: map of clients that are connected to the sl4f server.
    // key = session_id (unique for every ACTS instance) and value = Data about client (see
    // sl4f_types.rs)
    clients: HashMap<String, Vec<ClientData>>,
}

impl Sl4fClients {
    pub fn new() -> Self {
        Self { clients: HashMap::new() }
    }

    /// Registers a new connected client. Returns true if the client was already initialized.
    fn init_client(&mut self, id: String) -> bool {
        use std::collections::hash_map::Entry::*;
        match self.clients.entry(id) {
            Occupied(entry) => {
                warn!(tag = "client_init", "Key: {:?} already exists in clients. ", entry.key());
                true
            }
            Vacant(entry) => {
                entry.insert(Vec::new());
                info!(tag = "client_init", "Updated clients: {:?}", self.clients);
                false
            }
        }
    }

    fn cleanup_clients(&mut self) {
        self.clients.clear();
    }

    fn print_clients(&self) {
        info!("SL4F Clients: {:?}", self.clients);
    }
}

fn json<T>(content: &T) -> hyper::Response<hyper::Body>
where
    T: serde::Serialize,
{
    use std::convert::TryInto as _;

    let application_json = "application/json".try_into().expect("json header value");
    let data = serde_json::to_string(content).expect("encode json");

    let mut response = hyper::Response::new(data.into());
    assert_eq!(response.headers_mut().insert(hyper::header::CONTENT_TYPE, application_json), None);
    response
}

/// Handles all incoming requests to SL4F server, routes accordingly
pub async fn serve(
    request: hyper::Request<hyper::Body>,
    clients: Arc<RwLock<Sl4fClients>>,
    sender: async_channel::Sender<AsyncRequest>,
) -> hyper::Response<hyper::Body> {
    use hyper::Method;

    match (request.method(), request.uri().path()) {
        (&Method::GET, "/") => {
            // Parse the command request
            info!(tag = "serve", "Received command request via GET.");
            client_request(request, &sender).await
        }
        (&Method::POST, "/") => {
            // Parse the command request
            info!(tag = "serve", "Received command request via POST.");
            client_request(request, &sender).await
        }
        (&Method::GET, "/init") => {
            // Initialize a client
            info!(tag = "serve", "Received init request.");
            client_init(request, &clients).await
        }
        (&Method::GET, "/print_clients") => {
            // Print information about all clients
            info!(tag = "serve", "Received print client request.");
            const PRINT_ACK: &str = "Successfully printed clients.";
            json(&PRINT_ACK)
        }
        (&Method::GET, "/cleanup") => {
            info!(tag = "serve", "Received server cleanup request.");
            server_cleanup(request, &sender).await
        }
        _ => {
            error!(tag = "serve", "Received unknown server request.");
            const FAIL_REQUEST_ACK: &str = "Unknown GET request.";
            let res = CommandResponse::new(json!(""), None, Some(FAIL_REQUEST_ACK.to_string()));
            json(&res)
        }
    }
}

/// Given the request, map the test request to a FIDL query and execute
/// asynchronously
async fn client_request(
    request: hyper::Request<hyper::Body>,
    sender: &async_channel::Sender<AsyncRequest>,
) -> hyper::Response<hyper::Body> {
    const FAIL_TEST_ACK: &str = "Command failed";

    let (request_id, method_id, method_params) = match parse_request(request).await {
        Ok(res) => res,
        Err(error) => {
            error!(tag = "client_request", ?error, "Failed to parse request");
            return json(&FAIL_TEST_ACK);
        }
    };

    // Create channel for async thread to respond to
    // Package response and ship over JSON RPC
    let (async_sender, receiver) = futures::channel::oneshot::channel();
    let req = AsyncCommandRequest::new(async_sender, method_id.clone(), method_params);
    sender.send(AsyncRequest::Command(req)).await.expect("Failed to send request to async thread.");
    let resp = receiver.await.expect("Async thread dropped responder.");

    info!(
        tag = "client_request",
        method = ?method_id.method,
        response = ?resp,
        "Received async thread response"
    );

    // If the response has a return value, package into response, otherwise use error code
    match resp.result {
        Some(async_res) => {
            let res = CommandResponse::new(request_id.into_response_id(), Some(async_res), None);
            json(&res)
        }
        None => {
            let res = CommandResponse::new(request_id.into_response_id(), None, resp.error);
            json(&res)
        }
    }
}

/// Initializes a new client, adds to clients.
async fn client_init(
    request: hyper::Request<hyper::Body>,
    clients: &Arc<RwLock<Sl4fClients>>,
) -> hyper::Response<hyper::Body> {
    const INIT_ACK: &str = "Recieved init request.";
    const FAIL_INIT_ACK: &str = "Failed to init client.";

    let (_, _, method_params) = match parse_request(request).await {
        Ok(res) => res,
        Err(_) => return json(&FAIL_INIT_ACK),
    };

    let client_id_raw = match method_params.get("client_id") {
        Some(id) => Some(id).unwrap().clone(),
        None => return json(&FAIL_INIT_ACK),
    };

    // Initialize client with key = id, val = client data
    let client_id = client_id_raw.as_str().map(String::from).unwrap();

    if clients.write().init_client(client_id) {
        json(&FAIL_INIT_ACK)
    } else {
        json(&INIT_ACK)
    }
}

/// Given a request, grabs the method id, name, and parameters
/// Return Sl4fError if fail
async fn parse_request(
    request: hyper::Request<hyper::Body>,
) -> Result<(RequestId, MethodId, Value), Error> {
    use bytes::Buf as _;

    let body = hyper::body::aggregate(request.into_body()).await.context("read request")?;

    // Ignore the json_rpc field
    let request_data: CommandRequest = match serde_json::from_reader(body.reader()) {
        Ok(tdata) => tdata,
        Err(_) => return Err(Sl4fError::new("Failed to unpack request data.").into()),
    };

    let request_id_raw = request_data.id;
    let method_id_raw = request_data.method;
    let method_params = request_data.params;
    info!(tag = "parse_request",
        request_id = ?request_id_raw,
        name = ?method_id_raw,
        args = ?method_params
    );

    let request_id = RequestId::new(request_id_raw);
    // Separate the method_name field of the request into the method type (e.g bluetooth) and the
    // actual method name itself, defaulting to an empty method id if not formatted properly.
    let method_id = method_id_raw.parse().unwrap_or_default();
    Ok((request_id, method_id, method_params))
}

async fn server_cleanup(
    request: hyper::Request<hyper::Body>,
    sender: &async_channel::Sender<AsyncRequest>,
) -> hyper::Response<hyper::Body> {
    const FAIL_CLEANUP_ACK: &str = "Failed to cleanup SL4F resources.";
    const CLEANUP_ACK: &str = "Successful cleanup of SL4F resources.";

    info!(tag = "server_cleanup", "Cleaning up server state");
    let (request_id, _, _) = match parse_request(request).await {
        Ok(res) => res,
        Err(_) => return json(&FAIL_CLEANUP_ACK),
    };

    // Create channel for async thread to respond to
    let (async_sender, receiver) = futures::channel::oneshot::channel();

    // Cleanup all resources associated with sl4f
    sender
        .send(AsyncRequest::Cleanup(async_sender))
        .await
        .expect("Failed to send request to async thread.");
    let () = receiver.await.expect("Async thread dropped responder.");

    let ack = CommandResponse::new(request_id.into_response_id(), Some(json!(CLEANUP_ACK)), None);
    json(&ack)
}
