# Copyright 2021-2022 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# -----------------------------------------------------------------------------
# Imports
# -----------------------------------------------------------------------------
import asyncio
import sys
import os
import logging

from bumble.device import Device, Connection
from bumble.transport import open_transport_or_link
from bumble.att import (
    ATT_Error,
    ATT_INSUFFICIENT_ENCRYPTION_ERROR
)
from bumble.gatt import (
    Service,
    Characteristic,
    CharacteristicValue,
    Descriptor,
    GATT_CHARACTERISTIC_USER_DESCRIPTION_DESCRIPTOR,
    GATT_MANUFACTURER_NAME_STRING_CHARACTERISTIC,
    GATT_DEVICE_INFORMATION_SERVICE
)


# -----------------------------------------------------------------------------
class Listener(Device.Listener, Connection.Listener):
    def __init__(self, device):
        self.device = device

    def on_connection(self, connection):
        print(f'=== Connected to {connection}')
        connection.listener = self

    def on_disconnection(self, reason):
        print(f'### Disconnected, reason={reason}')


def my_custom_read(connection):
    print('----- READ from', connection)
    return bytes(f'Hello {connection}', 'ascii')


def my_custom_write(connection, value):
    print(f'----- WRITE from {connection}: {value}')


def my_custom_read_with_error(connection):
    print('----- READ from', connection, '[returning error]')
    if connection.is_encrypted:
        return bytes([123])
    else:
        raise ATT_Error(ATT_INSUFFICIENT_ENCRYPTION_ERROR)


def my_custom_write_with_error(connection, value):
    print(f'----- WRITE from {connection}: {value}', '[returning error]')
    if not connection.is_encrypted:
        raise ATT_Error(ATT_INSUFFICIENT_ENCRYPTION_ERROR)


# -----------------------------------------------------------------------------
async def main():
    if len(sys.argv) < 3:
        print('Usage: run_gatt_server.py <device-config> <transport-spec> [<bluetooth-address>]')
        print('example: run_gatt_server.py device1.json usb:0 E1:CA:72:48:C4:E8')
        return

    print('<<< connecting to HCI...')
    async with await open_transport_or_link(sys.argv[2]) as (hci_source, hci_sink):
        print('<<< connected')

        # Create a device to manage the host
        device = Device.from_config_file_with_hci(sys.argv[1], hci_source, hci_sink)
        device.listener = Listener(device)

        # Add a few entries to the device's GATT server
        descriptor = Descriptor(GATT_CHARACTERISTIC_USER_DESCRIPTION_DESCRIPTOR, Descriptor.READABLE, 'My Description')
        manufacturer_name_characteristic = Characteristic(
            GATT_MANUFACTURER_NAME_STRING_CHARACTERISTIC,
            Characteristic.READ,
            Characteristic.READABLE,
            'Fitbit',
            [descriptor]
        )
        device_info_service = Service(GATT_DEVICE_INFORMATION_SERVICE, [
            manufacturer_name_characteristic
        ])
        custom_service1 = Service(
            '50DB505C-8AC4-4738-8448-3B1D9CC09CC5',
            [
                Characteristic(
                    'D901B45B-4916-412E-ACCA-376ECB603B2C',
                    Characteristic.READ | Characteristic.WRITE,
                    Characteristic.READABLE | Characteristic.WRITEABLE,
                    CharacteristicValue(read=my_custom_read, write=my_custom_write)
                ),
                Characteristic(
                    '552957FB-CF1F-4A31-9535-E78847E1A714',
                    Characteristic.READ | Characteristic.WRITE,
                    Characteristic.READABLE | Characteristic.WRITEABLE,
                    CharacteristicValue(read=my_custom_read_with_error, write=my_custom_write_with_error)
                ),
                Characteristic(
                    '486F64C6-4B5F-4B3B-8AFF-EDE134A8446A',
                    Characteristic.READ | Characteristic.NOTIFY,
                    Characteristic.READABLE,
                    'hello'
                )
            ]
        )
        device.add_services([device_info_service, custom_service1])

        # Debug print
        for attribute in device.gatt_server.attributes:
            print(attribute)

        # Get things going
        await device.power_on()

        # Connect to a peer
        if len(sys.argv) > 3:
            target_address = sys.argv[3]
            print(f'=== Connecting to {target_address}...')
            await device.connect(target_address)
        else:
            await device.start_advertising(auto_restart=True)

        await hci_source.wait_for_termination()

# -----------------------------------------------------------------------------
logging.basicConfig(level = os.environ.get('BUMBLE_LOGLEVEL', 'DEBUG').upper())
asyncio.run(main())
