// 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 failure::{bail, Error};
use fidl_fuchsia_bluetooth_gatt::{
    self as gatt, AttributePermissions, Characteristic, Descriptor,
    LocalServiceDelegateControlHandle, LocalServiceDelegateMarker,
    LocalServiceDelegateOnReadValueResponder, LocalServiceDelegateOnWriteValueResponder,
    LocalServiceDelegateRequestStream, LocalServiceMarker, LocalServiceProxy, SecurityRequirements,
    Server_Marker, Server_Proxy, ServiceInfo,
};
use fuchsia_async as fasync;
use fuchsia_bluetooth::error::Error as BTError;
use fuchsia_component as app;
use fuchsia_syslog::{self, fx_log_err, fx_log_info};
use fuchsia_zircon as zx;
use futures::stream::TryStreamExt;
use parking_lot::RwLock;
use serde_json::value::Value;
use std::collections::HashMap;

use crate::bluetooth::constants::{
    GATT_MAX_ATTRIBUTE_VALUE_LENGTH, PERMISSION_READ_ENCRYPTED, PERMISSION_READ_ENCRYPTED_MITM,
    PERMISSION_WRITE_ENCRYPTED, PERMISSION_WRITE_ENCRYPTED_MITM, PERMISSION_WRITE_SIGNED,
    PERMISSION_WRITE_SIGNED_MITM, PROPERTY_INDICATE, PROPERTY_NOTIFY,
};

#[derive(Debug)]
struct Counter {
    count: u64,
}

impl Counter {
    pub fn new() -> Counter {
        Counter { count: 0 }
    }

    fn next(&mut self) -> u64 {
        let id: u64 = self.count;
        self.count += 1;
        id
    }
}

#[derive(Debug)]
struct InnerGattServerFacade {
    /// attribute_value_mapping: A Hashmap that will be used for capturing
    /// and updating Characteristic and Descriptor values for each service.
    /// The bool value represents whether value size of the initial Characteristic
    /// Descriptor value should be enforced or not for prepared writes. True
    /// for enforce, false to allow the size to grow to max values.
    attribute_value_mapping: HashMap<u64, (Vec<u8>, bool)>,

    /// A generic counter GATT server attributes
    generic_id_counter: Counter,

    /// The current Gatt Server Proxy
    server_proxy: Option<Server_Proxy>,

    /// service_proxies: List of LocalServiceProxy objects in use
    service_proxies: Vec<LocalServiceProxy>,
}

/// Perform Gatt Server operations.
///
/// Note this object is shared among all threads created by server.
///
#[derive(Debug)]
pub struct GattServerFacade {
    inner: RwLock<InnerGattServerFacade>,
}

impl GattServerFacade {
    pub fn new() -> GattServerFacade {
        GattServerFacade {
            inner: RwLock::new(InnerGattServerFacade {
                attribute_value_mapping: HashMap::new(),
                generic_id_counter: Counter::new(),
                server_proxy: None,
                service_proxies: Vec::new(),
            }),
        }
    }

    pub fn create_server_proxy(&self) -> Result<Server_Proxy, Error> {
        let tag = "GattServerFacade::create_server_proxy:";
        match self.inner.read().server_proxy.clone() {
            Some(service) => {
                fx_log_info!(tag: &[tag, &line!().to_string()].join(""), "Current service proxy: {:?}", service);
                Ok(service)
            }
            None => {
                fx_log_info!(tag: &[tag, &line!().to_string()].join(""), "Setting new server proxy");
                let service = app::client::connect_to_service::<Server_Marker>();
                if let Err(err) = service {
                    fx_log_err!(tag: &[tag, &line!().to_string()].join(""), "Failed to create server proxy: {:?}", err);
                    bail!("Failed to create server proxy: {:?}", err);
                }
                service
            }
        }
    }

    /// Function to take the input attribute value and parse it to
    /// a byte array. Types can be Strings, u8, or generic Array.
    pub fn parse_attribute_value_to_byte_array(&self, value_to_parse: &Value) -> Vec<u8> {
        match value_to_parse {
            Value::String(obj) => String::from(obj.as_str()).into_bytes(),
            Value::Number(obj) => match obj.as_u64() {
                Some(num) => vec![num as u8],
                None => vec![],
            },
            Value::Array(obj) => {
                obj.into_iter().filter_map(|v| v.as_u64()).map(|v| v as u8).collect()
            }
            _ => vec![],
        }
    }

    pub fn on_characteristic_configuration(
        peer_id: String,
        notify: bool,
        indicate: bool,
        characteristic_id: u64,
        control_handle: LocalServiceDelegateControlHandle,
        service_proxy: &LocalServiceProxy,
    ) {
        let tag = "GattServerFacade::on_characteristic_configuration:";
        fx_log_info!(
            tag: &[tag, &line!().to_string()].join(""),
            "OnCharacteristicConfiguration: (notify: {}, indicate: {}, id: {})",
            notify,
            indicate,
            peer_id
        );
        control_handle.shutdown();
        let value = if indicate {
            [0x02, 0x00].to_vec()
        } else if notify {
            [0x01, 0x00].to_vec()
        } else {
            [0x00, 0x00].to_vec()
        };
        let confirm = true;
        let _result = service_proxy.notify_value(
            characteristic_id,
            &peer_id,
            &mut value.to_vec().into_iter(),
            confirm,
        );
    }

    pub fn on_read_value(
        id: u64,
        offset: i32,
        responder: LocalServiceDelegateOnReadValueResponder,
        value_in_mapping: Option<&(Vec<u8>, bool)>,
    ) {
        let tag = "GattServerFacade::on_read_value:";
        fx_log_info!(
            tag: &[tag, &line!().to_string()].join(""),
            "OnReadValue request at id: {:?}, with offset: {:?}",
            id,
            offset
        );
        match value_in_mapping {
            Some(v) => {
                let (value, _enforce_initial_attribute_length) = v;
                if value.len() < offset as usize {
                    let _result = responder.send(None, gatt::ErrorCode::InvalidOffset);
                } else {
                    let value_to_write = value.clone().split_off(offset as usize);
                    let _result = responder.send(
                        Some(&mut value_to_write.to_vec().into_iter()),
                        gatt::ErrorCode::NoError,
                    );
                }
            }
            None => {
                // ID doesn't exist in the database
                let _result = responder.send(None, gatt::ErrorCode::NotPermitted);
            }
        };
    }

    pub fn write_and_extend(value: &mut Vec<u8>, value_to_write: Vec<u8>, offset: usize) {
        let split_idx = (value.len() - offset).min(value_to_write.len());
        let (overlapping, extending) = value_to_write.split_at(split_idx);
        let end_of_overlap = offset + overlapping.len();
        value.splice(offset..end_of_overlap, overlapping.iter().cloned());
        value.extend_from_slice(extending);
    }

    pub fn on_write_value(
        id: u64,
        offset: u16,
        value_to_write: Vec<u8>,
        responder: LocalServiceDelegateOnWriteValueResponder,
        value_in_mapping: Option<&mut (Vec<u8>, bool)>,
    ) {
        let tag = "GattServerFacade::on_write_value:";
        fx_log_info!(
            tag: &[tag, &line!().to_string()].join(""),
            "OnWriteValue request at id: {:?}, with offset: {:?}, with value: {:?}",
            id,
            offset,
            value_to_write
        );

        match value_in_mapping {
            Some(v) => {
                let (value, enforce_initial_attribute_length) = v;
                let max_attribute_size: usize = match enforce_initial_attribute_length {
                    true => value.len(),
                    false => GATT_MAX_ATTRIBUTE_VALUE_LENGTH,
                };
                if max_attribute_size < (value_to_write.len() + offset as usize) {
                    let _result = responder.send(gatt::ErrorCode::InvalidValueLength);
                } else if value.len() < offset as usize {
                    let _result = responder.send(gatt::ErrorCode::InvalidOffset);
                } else {
                    &mut GattServerFacade::write_and_extend(value, value_to_write, offset as usize);
                    let _result = responder.send(gatt::ErrorCode::NoError);
                }
            }
            None => {
                // ID doesn't exist in the database
                let _result = responder.send(gatt::ErrorCode::NotPermitted);
            }
        }
    }

    pub fn on_write_without_response(
        id: u64,
        offset: u16,
        value_to_write: Vec<u8>,
        value_in_mapping: Option<&mut (Vec<u8>, bool)>,
    ) {
        let tag = "GattServerFacade::on_write_without_response:";
        fx_log_info!(
            tag: &[tag, &line!().to_string()].join(""),
            "OnWriteWithoutResponse request at id: {:?}, with offset: {:?}, with value: {:?}",
            id,
            offset,
            value_to_write
        );
        if let Some(v) = value_in_mapping {
            let (value, _enforce_initial_attribute_length) = v;
            &mut GattServerFacade::write_and_extend(value, value_to_write, offset as usize);
        }
    }

    pub async fn monitor_delegate_request_stream(
        stream: LocalServiceDelegateRequestStream,
        mut attribute_value_mapping: HashMap<u64, (Vec<u8>, bool)>,
        service_proxy: LocalServiceProxy,
    ) -> Result<(), Error> {
        use fidl_fuchsia_bluetooth_gatt::LocalServiceDelegateRequest::*;
        await!(stream
            .map_ok(move |request| match request {
                OnCharacteristicConfiguration {
                    peer_id,
                    notify,
                    indicate,
                    characteristic_id,
                    control_handle,
                } => {
                    GattServerFacade::on_characteristic_configuration(
                        peer_id,
                        notify,
                        indicate,
                        characteristic_id,
                        control_handle,
                        &service_proxy,
                    );
                }
                OnReadValue { id, offset, responder } => {
                    GattServerFacade::on_read_value(
                        id,
                        offset,
                        responder,
                        attribute_value_mapping.get(&id),
                    );
                }
                OnWriteValue { id, offset, value, responder } => {
                    GattServerFacade::on_write_value(
                        id,
                        offset,
                        value,
                        responder,
                        attribute_value_mapping.get_mut(&id),
                    );
                }
                OnWriteWithoutResponse { id, offset, value, .. } => {
                    GattServerFacade::on_write_without_response(
                        id,
                        offset,
                        value,
                        attribute_value_mapping.get_mut(&id),
                    );
                }
            })
            .try_collect::<()>())
        .map_err(|e| e.into())
    }

    /// Convert a number representing permissions into AttributePermissions.
    ///
    /// Fuchsia GATT Server uses a u32 as a property value and an AttributePermissions
    /// object to represent Characteristic and Descriptor permissions. In order to
    /// simplify the incomming json object the incoming permission value will be
    /// treated as a u32 and converted into the proper AttributePermission object.
    ///
    /// The incoming permissions number is represented by adding the numbers representing
    /// the permission level.
    /// Values:
    /// 0x001 - Allow read permission
    /// 0x002 - Allow encrypted read operations
    /// 0x004 - Allow reading with man-in-the-middle protection
    /// 0x010 - Allow write permission
    /// 0x020 - Allow encrypted writes
    /// 0x040 - Allow writing with man-in-the-middle protection
    /// 0x080 - Allow signed writes
    /// 0x100 - Allow signed write perations with man-in-the-middle protection
    ///
    /// Example input that allows read and write: 0x01 | 0x10 = 0x11
    /// This function will convert this to the proper AttributePermission permissions.
    pub fn permissions_and_properties_from_raw_num(
        &self,
        permissions: u32,
        properties: u32,
    ) -> AttributePermissions {
        let mut read_encryption_required = false;
        let mut read_authentication_required = false;
        let mut read_authorization_required = false;

        let mut write_encryption_required = false;
        let mut write_authentication_required = false;
        let mut write_authorization_required = false;

        let mut update_encryption_required = false;
        let mut update_authentication_required = false;
        let mut update_authorization_required = false;

        if permissions & PERMISSION_READ_ENCRYPTED != 0 {
            read_encryption_required = true;
        }

        if permissions & PERMISSION_READ_ENCRYPTED_MITM != 0 {
            read_encryption_required = true;
            read_authentication_required = true;
            read_authorization_required = true;
        }

        if permissions & PERMISSION_WRITE_ENCRYPTED != 0 {
            write_encryption_required = true;
            update_encryption_required = true;
        }

        if permissions & PERMISSION_WRITE_ENCRYPTED_MITM != 0 {
            write_encryption_required = true;
            write_authentication_required = true;
            write_authorization_required = true;
            update_encryption_required = true;
            update_authentication_required = true;
            update_authorization_required = true;
        }

        if permissions & PERMISSION_WRITE_SIGNED != 0 {
            write_authorization_required = true;
        }

        if permissions & PERMISSION_WRITE_SIGNED_MITM != 0 {
            write_encryption_required = true;
            write_authentication_required = true;
            write_authorization_required = true;
            update_encryption_required = true;
            update_authentication_required = true;
            update_authorization_required = true;
        }

        // Update Security Requirements only required if notify or indicate
        // properties set.
        let update_sec_requirement = if properties & (PROPERTY_NOTIFY | PROPERTY_INDICATE) != 0 {
            Some(Box::new(SecurityRequirements {
                encryption_required: update_encryption_required,
                authentication_required: update_authentication_required,
                authorization_required: update_authorization_required,
            }))
        } else {
            None
        };

        let read_sec_requirement = SecurityRequirements {
            encryption_required: read_encryption_required,
            authentication_required: read_authentication_required,
            authorization_required: read_authorization_required,
        };

        let write_sec_requirement = SecurityRequirements {
            encryption_required: write_encryption_required,
            authentication_required: write_authentication_required,
            authorization_required: write_authorization_required,
        };

        AttributePermissions {
            read: Some(Box::new(read_sec_requirement)),
            write: Some(Box::new(write_sec_requirement)),
            update: update_sec_requirement,
        }
    }

    pub fn generate_descriptors(
        &self,
        descriptor_list_json: &Value,
    ) -> Result<Vec<Descriptor>, Error> {
        let mut descriptors: Vec<Descriptor> = Vec::new();
        // Fuchsia will automatically setup these descriptors and manage them.
        // Skip setting them up if found in the input descriptor list.
        let banned_descriptor_uuids = [
            "00002900-0000-1000-8000-00805f9b34fb".to_string(), // CCC Descriptor
            "00002902-0000-1000-8000-00805f9b34fb".to_string(), // Client Configuration Descriptor
            "00002903-0000-1000-8000-00805f9b34fb".to_string(), // Server Configuration Descriptor
        ];

        if descriptor_list_json.is_null() {
            return Ok(descriptors);
        }

        let descriptor_list = match descriptor_list_json.as_array() {
            Some(d) => d,
            None => bail!("Attribute 'descriptors' is not a parseable list."),
        };

        for descriptor in descriptor_list.into_iter() {
            let descriptor_uuid = match descriptor["uuid"].as_str() {
                Some(uuid) => uuid.to_string(),
                None => bail!("Descriptor uuid was unable to cast to str."),
            };
            let descriptor_value = self.parse_attribute_value_to_byte_array(&descriptor["value"]);

            let raw_enforce_enforce_initial_attribute_length =
                descriptor["enforce_initial_attribute_length"].as_bool().unwrap_or(false);

            // No properties for descriptors.
            let properties = 0u32;

            if banned_descriptor_uuids.contains(&descriptor_uuid) {
                continue;
            }

            let raw_descriptor_permissions = match descriptor["permissions"].as_u64() {
                Some(permissions) => permissions as u32,
                None => bail!("Descriptor permissions was unable to cast to u64."),
            };

            let desc_permission_attributes = self
                .permissions_and_properties_from_raw_num(raw_descriptor_permissions, properties);

            let descriptor_id = self.inner.write().generic_id_counter.next();
            self.inner.write().attribute_value_mapping.insert(
                descriptor_id,
                (descriptor_value, raw_enforce_enforce_initial_attribute_length),
            );
            let descriptor_obj = Descriptor {
                id: descriptor_id,
                type_: descriptor_uuid.clone(),
                permissions: Some(Box::new(desc_permission_attributes)),
            };

            descriptors.push(descriptor_obj);
        }
        Ok(descriptors)
    }

    pub fn generate_characteristics(
        &self,
        characteristic_list_json: &Value,
    ) -> Result<Vec<Characteristic>, Error> {
        let mut characteristics: Vec<Characteristic> = Vec::new();
        if characteristic_list_json.is_null() {
            return Ok(characteristics);
        }

        let characteristic_list = match characteristic_list_json.as_array() {
            Some(c) => c,
            None => bail!("Attribute 'characteristics' is not a parseable list."),
        };

        for characteristic in characteristic_list.into_iter() {
            let characteristic_uuid = match characteristic["uuid"].as_str() {
                Some(uuid) => uuid.to_string(),
                None => bail!("Characteristic uuid was unable to cast to str."),
            };

            let characteristic_properties = match characteristic["properties"].as_u64() {
                Some(properties) => properties as u32,
                None => bail!("Characteristic properties was unable to cast to u64."),
            };

            let raw_characteristic_permissions = match characteristic["permissions"].as_u64() {
                Some(permissions) => permissions as u32,
                None => bail!("Characteristic permissions was unable to cast to u64."),
            };

            let characteristic_value =
                self.parse_attribute_value_to_byte_array(&characteristic["value"]);

            let raw_enforce_enforce_initial_attribute_length =
                characteristic["enforce_initial_attribute_length"].as_bool().unwrap_or(false);

            let descriptor_list = &characteristic["descriptors"];
            let descriptors = self.generate_descriptors(descriptor_list)?;

            let characteristic_permissions = self.permissions_and_properties_from_raw_num(
                raw_characteristic_permissions,
                characteristic_properties,
            );

            let characteristic_id = self.inner.write().generic_id_counter.next();
            self.inner.write().attribute_value_mapping.insert(
                characteristic_id,
                (characteristic_value, raw_enforce_enforce_initial_attribute_length),
            );
            let characteristic_obj = Characteristic {
                id: characteristic_id,
                type_: characteristic_uuid,
                properties: characteristic_properties,
                permissions: Some(Box::new(characteristic_permissions)),
                descriptors: Some(descriptors),
            };

            characteristics.push(characteristic_obj);
        }
        Ok(characteristics)
    }

    pub fn generate_service(&self, service_json: &Value) -> Result<ServiceInfo, Error> {
        // Determine if the service is primary or not.
        let service_id = self.inner.write().generic_id_counter.next();
        let service_type = &service_json["type"];
        let is_service_primary = match service_type.as_i64() {
            Some(val) => match val {
                0 => true,
                1 => false,
                _ => bail!("Invalid Service type. Expected 0 or 1."),
            },
            None => bail!("Service type was unable to cast to i64."),
        };

        // Get the service UUID.
        let service_uuid = match service_json["uuid"].as_str() {
            Some(s) => s,
            None => bail!("Service uuid was unable to cast to str."),
        };

        //Get the Characteristics from the service.
        let characteristics = self.generate_characteristics(&service_json["characteristics"])?;

        // Includes: TBD
        let includes = None;

        Ok(ServiceInfo {
            id: service_id,
            primary: is_service_primary,
            type_: service_uuid.to_string(),
            characteristics: Some(characteristics),
            includes: includes,
        })
    }

    pub async fn publish_service(
        &self,
        mut service_info: ServiceInfo,
        service_uuid: String,
    ) -> Result<(), Error> {
        let tag = "GattServerFacade::publish_service:";
        let (service_local, service_remote) = zx::Channel::create()?;
        let service_local = fasync::Channel::from_channel(service_local)?;
        let service_proxy = LocalServiceProxy::new(service_local);

        let (delegate_client, delegate_request_stream) =
            fidl::endpoints::create_request_stream::<LocalServiceDelegateMarker>()?;

        let service_server = fidl::endpoints::ServerEnd::<LocalServiceMarker>::new(service_remote);

        self.inner.write().service_proxies.push(service_proxy.clone());

        match &self.inner.read().server_proxy {
            Some(server) => {
                let status = await!(server.publish_service(
                    &mut service_info,
                    delegate_client,
                    service_server
                ))?;
                match status.error {
                    None => fx_log_info!( tag: &[tag, &line!().to_string()].join(""),
                        "Successfully published GATT service with uuid {:?}",
                        service_uuid
                    ),
                    Some(e) => bail!("Failed to create GATT Service: {}", BTError::from(*e)),
                }
            }
            None => bail!("No Server Proxy created."),
        }
        let monitor_delegate_fut = GattServerFacade::monitor_delegate_request_stream(
            delegate_request_stream,
            self.inner.read().attribute_value_mapping.clone(),
            service_proxy,
        );
        let fut = async {
            let result = await!(monitor_delegate_fut);
            if let Err(err) = result {
                fx_log_err!(tag: "publish_service",
                    "Failed to create or monitor the gatt service delegate: {:?}", err);
            }
        };
        fasync::spawn(fut);
        Ok(())
    }

    /// Publish a GATT Server.
    ///
    /// The input is a JSON object representing the attributes of the GATT
    /// server Database to setup. This function will also start listening for
    /// incoming requests to Characteristics and Descriptors in each Service.
    ///
    /// This is primarially using the same input syntax as in the Android AOSP
    /// ACTS test framework at:
    /// <aosp_root>/tools/test/connectivity/acts/framework/acts/test_utils/bt/gatt_test_database.py
    ///
    ///
    /// Example python dictionary that's turned into JSON (sub dic values can be found
    /// in <aosp_root>/tools/test/connectivity/acts/framework/acts/test_utils/bt/bt_constants.py:
    ///
    /// SMALL_DATABASE = {
    ///     'services': [{
    ///         'uuid': '00001800-0000-1000-8000-00805f9b34fb',
    ///         'type': gatt_service_types['primary'],
    ///         'characteristics': [{
    ///             'uuid': gatt_char_types['device_name'],
    ///             'properties': gatt_characteristic['property_read'],
    ///             'permissions': gatt_characteristic['permission_read'],
    ///             'handle': 0x0003,
    ///             'value_type': gatt_characteristic_value_format['string'],
    ///             'value': 'Test Database'
    ///         }, {
    ///             'uuid': gatt_char_types['appearance'],
    ///             'properties': gatt_characteristic['property_read'],
    ///             'permissions': gatt_characteristic['permission_read'],
    ///             'handle': 0x0005,
    ///             'value_type': gatt_characteristic_value_format['sint32'],
    ///             'offset': 0,
    ///             'value': 17
    ///         }, {
    ///             'uuid': gatt_char_types['peripheral_pref_conn'],
    ///             'properties': gatt_characteristic['property_read'],
    ///             'permissions': gatt_characteristic['permission_read'],
    ///             'handle': 0x0007
    ///         }]
    ///     }, {
    ///         'uuid': '00001801-0000-1000-8000-00805f9b34fb',
    ///         'type': gatt_service_types['primary'],
    ///         'characteristics': [{
    ///             'uuid': gatt_char_types['service_changed'],
    ///             'properties': gatt_characteristic['property_indicate'],
    ///             'permissions': gatt_characteristic['permission_read'] |
    ///             gatt_characteristic['permission_write'],
    ///             'handle': 0x0012,
    ///             'value_type': gatt_characteristic_value_format['byte'],
    ///             'value': [0x0000],
    ///             'descriptors': [{
    ///                 'uuid': gatt_char_desc_uuids['client_char_cfg'],
    ///                 'permissions': gatt_descriptor['permission_read'] |
    ///                 gatt_descriptor['permission_write'],
    ///                 'value': [0x0000]
    ///             }]
    ///         }, {
    ///             'uuid': '0000b004-0000-1000-8000-00805f9b34fb',
    ///             'properties': gatt_characteristic['property_read'],
    ///             'permissions': gatt_characteristic['permission_read'],
    ///             'handle': 0x0015,
    ///             'value_type': gatt_characteristic_value_format['byte'],
    ///             'value': [0x04]
    ///         }]
    ///     }]
    /// }
    pub async fn publish_server(&self, args: Value) -> Result<(), Error> {
        let tag = "GattServerFacade::publish_server:";
        fx_log_info!(tag: &[tag, &line!().to_string()].join(""), "Publishing service");
        let server_proxy = self.create_server_proxy()?;
        self.inner.write().server_proxy = Some(server_proxy);
        let database = args.get("database");
        let services = match database {
            Some(d) => match d.get("services") {
                Some(s) => s,
                None => bail!("No services found."),
            },
            None => bail!("Could not find the 'services' key in the json database."),
        };

        let service_list = match services.as_array() {
            Some(s) => s,
            None => bail!("Attribute 'service' is not a parseable list."),
        };

        for service in service_list.into_iter() {
            self.inner.write().attribute_value_mapping.clear();
            let service_info = self.generate_service(service)?;
            let service_uuid = &service["uuid"];
            await!(self.publish_service(service_info, service_uuid.to_string()))?;
        }
        Ok(())
    }

    pub async fn close_server(&self) {
        self.inner.write().server_proxy = None
    }

    // GattServerFacade for cleaning up objects in use.
    pub fn cleanup(&self) {
        let tag = "GattServerFacade::cleanup:";
        fx_log_info!(tag: &[tag, &line!().to_string()].join(""), "Cleanup GATT server objects");
        let mut inner = self.inner.write();
        inner.server_proxy = None;
        inner.service_proxies.clear();
    }

    // GattServerFacade for printing useful information pertaining to the facade for
    // debug purposes.
    pub fn print(&self) {
        let tag = "GattServerFacade::print:";
        fx_log_info!(tag: &[tag, &line!().to_string()].join(""), "Unimplemented print function");
    }
}
