/*
 *
 *    Copyright (c) 2024 Project CHIP Authors
 *
 *    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
 *
 *        http://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.
 */

#include "BluezObjectManager.h"

#include <algorithm>
#include <memory>
#include <string>
#include <string_view>

#include <gio/gio.h>
#include <glib-object.h>
#include <glib.h>

#include <ble/Ble.h>
#include <lib/support/CodeUtils.h>
#include <lib/support/logging/CHIPLogging.h>
#include <platform/ConfigurationManager.h>
#include <platform/GLibTypeDeleter.h>
#include <platform/Linux/dbus/bluez/DbusBluez.h>
#include <platform/PlatformManager.h>

#include "Types.h"

namespace chip {
namespace DeviceLayer {
namespace Internal {

namespace {

const char * GetAdapterObjectPath(BluezAdapter1 * aAdapter)
{
    return g_dbus_proxy_get_object_path(reinterpret_cast<GDBusProxy *>(aAdapter));
}

} // namespace

CHIP_ERROR BluezObjectManager::Init()
{
    return PlatformMgrImpl().GLibMatterContextInvokeSync(
        +[](BluezObjectManager * self) {
            ReturnErrorOnFailure(self->SetupDBusConnection());
            ReturnErrorOnFailure(self->SetupObjectManager());
            return CHIP_NO_ERROR;
        },
        this);
}

void BluezObjectManager::Shutdown()
{
    // Run endpoint cleanup on the CHIPoBluez thread. This is necessary because the
    // cleanup function releases the D-Bus manager client object, which handles D-Bus
    // signals. Otherwise, we will face race condition when the D-Bus signal is in
    // the middle of being processed when the cleanup function is called.
    PlatformMgrImpl().GLibMatterContextInvokeSync(
        +[](BluezObjectManager * self) {
            self->mConnection.reset();
            self->mObjectManager.reset();
            return CHIP_NO_ERROR;
        },
        this);
}

BluezAdapter1 * BluezObjectManager::GetAdapter(unsigned int aAdapterId)
{
    char expectedPath[32];
    snprintf(expectedPath, sizeof(expectedPath), BLUEZ_PATH "/hci%u", aAdapterId);

    for (BluezObject & object : GetObjects())
    {
        GAutoPtr<BluezAdapter1> adapter(bluez_object_get_adapter1(&object));
        if (adapter && strcmp(g_dbus_proxy_get_object_path(reinterpret_cast<GDBusProxy *>(adapter.get())), expectedPath) == 0)
        {
            SetupAdapter(adapter.get());
            return adapter.release();
        }
    }

    return nullptr;
}

BluezAdapter1 * BluezObjectManager::GetAdapter(const char * aAdapterAddress)
{
    for (BluezObject & object : GetObjects())
    {
        GAutoPtr<BluezAdapter1> adapter(bluez_object_get_adapter1(&object));
        if (adapter && strcmp(bluez_adapter1_get_address(adapter.get()), aAdapterAddress) == 0)
        {
            SetupAdapter(adapter.get());
            return adapter.release();
        }
    }

    return nullptr;
}

CHIP_ERROR BluezObjectManager::SubscribeDeviceNotifications(BluezAdapter1 * aAdapter,
                                                            BluezObjectManagerAdapterNotificationsDelegate * aDelegate)
{
    std::lock_guard<std::mutex> lock(mSubscriptionsMutex);
    mSubscriptions.emplace_back(GetAdapterObjectPath(aAdapter), aDelegate);
    return CHIP_NO_ERROR;
}

CHIP_ERROR BluezObjectManager::UnsubscribeDeviceNotifications(BluezAdapter1 * aAdapter,
                                                              BluezObjectManagerAdapterNotificationsDelegate * aDelegate)
{
    std::lock_guard<std::mutex> lock(mSubscriptionsMutex);
    const auto item = std::make_pair(std::string(GetAdapterObjectPath(aAdapter)), aDelegate);
    mSubscriptions.erase(std::remove(mSubscriptions.begin(), mSubscriptions.end(), item), mSubscriptions.end());
    return CHIP_NO_ERROR;
}

CHIP_ERROR BluezObjectManager::SetupAdapter(BluezAdapter1 * aAdapter)
{
    // Make sure the adapter is powered on.
    bluez_adapter1_set_powered(aAdapter, TRUE);
    // Setting "Discoverable" to False on the adapter and to True on the advertisement convinces
    // BlueZ to set "BR/EDR Not Supported" flag. BlueZ doesn't provide API to do that explicitly
    // and the flag is necessary to force using LE transport.
    bluez_adapter1_set_discoverable(aAdapter, FALSE);
    return CHIP_NO_ERROR;
}

void BluezObjectManager::NotifyAdapterAdded(BluezAdapter1 * aAdapter)
{
    unsigned int adapterId = 0;
    sscanf(GetAdapterObjectPath(aAdapter), BLUEZ_PATH "/hci%u", &adapterId);
    // Notify the application that new adapter has been just added
    BLEManagerImpl::NotifyBLEAdapterAdded(adapterId, bluez_adapter1_get_address(aAdapter));
}

void BluezObjectManager::NotifyAdapterRemoved(BluezAdapter1 * aAdapter)
{
    unsigned int adapterId = 0;
    sscanf(GetAdapterObjectPath(aAdapter), BLUEZ_PATH "/hci%u", &adapterId);
    // Notify the application that the adapter is no longer available
    BLEManagerImpl::NotifyBLEAdapterRemoved(adapterId, bluez_adapter1_get_address(aAdapter));
}

void BluezObjectManager::RemoveAdapterSubscriptions(BluezAdapter1 * aAdapter)
{
    std::lock_guard<std::mutex> lock(mSubscriptionsMutex);
    const auto adapterPath = GetAdapterObjectPath(aAdapter);
    // Remove all device notification subscriptions for the given adapter
    mSubscriptions.erase(std::remove_if(mSubscriptions.begin(), mSubscriptions.end(),
                                        [adapterPath](const auto & subscription) { return subscription.first == adapterPath; }),
                         mSubscriptions.end());
}

CHIP_ERROR BluezObjectManager::SetupDBusConnection()
{
    GAutoPtr<GError> err;
    mConnection.reset(g_bus_get_sync(G_BUS_TYPE_SYSTEM, nullptr, &err.GetReceiver()));
    VerifyOrReturnError(mConnection != nullptr, CHIP_ERROR_INTERNAL,
                        ChipLogError(DeviceLayer, "FAIL: Get D-Bus system bus: %s", err->message));
    return CHIP_NO_ERROR;
}

BluezObjectManager::NotificationsDelegates BluezObjectManager::GetDeviceNotificationsDelegates(BluezDevice1 * device)
{
    const char * deviceAdapterPath = bluez_device1_get_adapter(device);
    NotificationsDelegates delegates;

    std::lock_guard<std::mutex> lock(mSubscriptionsMutex);
    for (auto & [adapterPath, delegate] : mSubscriptions)
    {
        if (adapterPath == deviceAdapterPath)
        {
            delegates.push_back(delegate);
        }
    }

    return delegates;
}

void BluezObjectManager::OnObjectAdded(GDBusObjectManager * aMgr, BluezObject * aObj)
{
    GAutoPtr<BluezAdapter1> adapter(bluez_object_get_adapter1(aObj));
    // Verify that the adapter is properly initialized - the class property must be set.
    // BlueZ can export adapter objects on the bus before it is fully initialized. Such
    // adapter objects are not usable and must be ignored.
    //
    // TODO: Find a better way to determine whether the adapter interface exposed by
    //       BlueZ D-Bus service is fully functional. The current approach is based on
    //       the assumption that the class property is non-zero, which is true only
    //       for BR/EDR + LE adapters. LE-only adapters do not have HCI command to read
    //       the class property and BlueZ sets it to 0 as a default value.
    if (adapter && bluez_adapter1_get_class(adapter.get()) != 0)
    {
        NotifyAdapterAdded(adapter.get());
        return;
    }

    GAutoPtr<BluezDevice1> device(bluez_object_get_device1(aObj));
    if (device)
    {
        for (auto delegate : GetDeviceNotificationsDelegates(device.get()))
        {
            delegate->OnDeviceAdded(*device.get());
        }
    }
}

void BluezObjectManager::OnObjectRemoved(GDBusObjectManager * aMgr, BluezObject * aObj)
{
    GAutoPtr<BluezAdapter1> adapter(bluez_object_get_adapter1(aObj));
    if (adapter)
    {
        RemoveAdapterSubscriptions(adapter.get());
        NotifyAdapterRemoved(adapter.get());
        return;
    }

    GAutoPtr<BluezDevice1> device(bluez_object_get_device1(aObj));
    if (device)
    {
        for (auto delegate : GetDeviceNotificationsDelegates(device.get()))
        {
            delegate->OnDeviceRemoved(*device.get());
        }
    }
}

void BluezObjectManager::OnInterfacePropertiesChanged(GDBusObjectManagerClient * aMgr, BluezObject * aObj, GDBusProxy * aIface,
                                                      GVariant * aChangedProps, const char * const * aInvalidatedProps)
{
    uint32_t classValue = 0;
    GAutoPtr<BluezAdapter1> adapter(bluez_object_get_adapter1(aObj));
    // When the adapter's readonly class property is set, it means that the adapter has been
    // fully initialized and is ready to be used. It's most likely that the adapter has been
    // previously ignored in the OnObjectAdded callback, so now we can notify the application
    // about the new adapter.
    if (adapter && g_variant_lookup(aChangedProps, "Class", "u", &classValue) && classValue != 0)
    {
        NotifyAdapterAdded(adapter.get());
        return;
    }

    GAutoPtr<BluezDevice1> device(bluez_object_get_device1(aObj));
    if (device)
    {
        for (auto delegate : GetDeviceNotificationsDelegates(device.get()))
        {
            delegate->OnDevicePropertyChanged(*device.get(), aChangedProps, aInvalidatedProps);
        }
    }
}

CHIP_ERROR BluezObjectManager::SetupObjectManager()
{
    // When connecting to signals, the thread default context must be initialized. Otherwise,
    // all D-Bus signals will be delivered to the GLib global default main context.
    VerifyOrDie(g_main_context_get_thread_default() != nullptr);

    GAutoPtr<GError> err;
    mObjectManager.reset(g_dbus_object_manager_client_new_sync(
        mConnection.get(), G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_NONE, BLUEZ_INTERFACE, "/",
        bluez_object_manager_client_get_proxy_type, nullptr /* unused user data in the proxy type func */,
        nullptr /* destroy notify */, nullptr /* cancellable */, &err.GetReceiver()));
    VerifyOrReturnError(mObjectManager, CHIP_ERROR_INTERNAL,
                        ChipLogError(DeviceLayer, "FAIL: Get D-Bus object manager client: %s", err->message));

    g_signal_connect(mObjectManager.get(), "object-added",
                     G_CALLBACK(+[](GDBusObjectManager * mgr, GDBusObject * obj, BluezObjectManager * self) {
                         return self->OnObjectAdded(mgr, reinterpret_cast<BluezObject *>(obj));
                     }),
                     this);
    g_signal_connect(mObjectManager.get(), "object-removed",
                     G_CALLBACK(+[](GDBusObjectManager * mgr, GDBusObject * obj, BluezObjectManager * self) {
                         return self->OnObjectRemoved(mgr, reinterpret_cast<BluezObject *>(obj));
                     }),
                     this);
    g_signal_connect(mObjectManager.get(), "interface-proxy-properties-changed",
                     G_CALLBACK(+[](GDBusObjectManagerClient * mgr, GDBusObjectProxy * obj, GDBusProxy * iface, GVariant * changed,
                                    const char * const * invalidated, BluezObjectManager * self) {
                         return self->OnInterfacePropertiesChanged(mgr, reinterpret_cast<BluezObject *>(obj), iface, changed,
                                                                   invalidated);
                     }),
                     this);

    return CHIP_NO_ERROR;
}

CHIP_ERROR BluezCallToChipError(const GError * aError)
{
    switch (aError->code)
    {
    // BlueZ crashed or the D-Bus connection is broken in both cases adapter is not available.
    case G_DBUS_ERROR_NO_REPLY:
    // BlueZ service is not available on the bus, hence the adapter is not available too.
    case G_DBUS_ERROR_SERVICE_UNKNOWN:
    // Requested D-Bus object is not available on the given path. This happens when the adapter
    // was unplugged and unregistered from the BlueZ object manager.
    case G_DBUS_ERROR_UNKNOWN_OBJECT:
        return BLE_ERROR_ADAPTER_UNAVAILABLE;
    default:
        return CHIP_ERROR_INTERNAL;
    }
}

} // namespace Internal
} // namespace DeviceLayer
} // namespace chip
