/*
 *
 *    Copyright (c) 2020-2022 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 <platform/internal/CHIPDeviceLayerInternal.h>
#include <platform/internal/DeviceNetworkInfo.h>

#include <app/AttributeAccessInterface.h>
#include <lib/support/CodeUtils.h>
#include <lib/support/logging/CHIPLogging.h>
#include <platform/Linux/NetworkCommissioningDriver.h>
#include <platform/PlatformManager.h>
#include <platform/ThreadStackManager.h>

#include <nlbyteorder.hpp>
#include <nlio-byteorder.hpp>
#include <nlio.hpp>

using namespace ::chip::app;
using namespace ::chip::app::Clusters;
using namespace chip::DeviceLayer::NetworkCommissioning;

namespace chip {
namespace DeviceLayer {

ThreadStackManagerImpl ThreadStackManagerImpl::sInstance;

constexpr char ThreadStackManagerImpl::kDBusOpenThreadService[];
constexpr char ThreadStackManagerImpl::kDBusOpenThreadObjectPath[];

constexpr char ThreadStackManagerImpl::kOpenthreadDeviceRoleDisabled[];
constexpr char ThreadStackManagerImpl::kOpenthreadDeviceRoleDetached[];
constexpr char ThreadStackManagerImpl::kOpenthreadDeviceRoleChild[];
constexpr char ThreadStackManagerImpl::kOpenthreadDeviceRoleRouter[];
constexpr char ThreadStackManagerImpl::kOpenthreadDeviceRoleLeader[];

constexpr char ThreadStackManagerImpl::kPropertyDeviceRole[];

namespace {

struct SetActiveDatasetContext
{
    OpenthreadIoOpenthreadBorderRouter * proxy;
    ByteSpan netInfo;
};

CHIP_ERROR GLibMatterContextSetActiveDataset(SetActiveDatasetContext * context)
{
    // When creating D-Bus proxy object, 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);

    std::unique_ptr<GBytes, GBytesDeleter> bytes(g_bytes_new(context->netInfo.data(), context->netInfo.size()));
    if (!bytes)
        return CHIP_ERROR_NO_MEMORY;
    std::unique_ptr<GVariant, GVariantDeleter> value(g_variant_new_from_bytes(G_VARIANT_TYPE_BYTESTRING, bytes.release(), true));
    if (!value)
        return CHIP_ERROR_NO_MEMORY;
    openthread_io_openthread_border_router_set_active_dataset_tlvs(context->proxy, value.release());
    return CHIP_NO_ERROR;
}

} // namespace

ThreadStackManagerImpl::ThreadStackManagerImpl() : mAttached(false) {}

CHIP_ERROR ThreadStackManagerImpl::GLibMatterContextInitThreadStack(ThreadStackManagerImpl * self)
{
    // When creating D-Bus proxy object, 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);

    std::unique_ptr<GError, GErrorDeleter> err;
    self->mProxy.reset(openthread_io_openthread_border_router_proxy_new_for_bus_sync(
        G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, kDBusOpenThreadService, kDBusOpenThreadObjectPath, nullptr,
        &MakeUniquePointerReceiver(err).Get()));
    VerifyOrReturnError(
        self->mProxy != nullptr, CHIP_ERROR_INTERNAL,
        ChipLogError(DeviceLayer, "openthread: failed to create openthread dbus proxy %s", err ? err->message : "unknown error"));

    g_signal_connect(self->mProxy.get(), "g-properties-changed", G_CALLBACK(OnDbusPropertiesChanged), self);

    return CHIP_NO_ERROR;
}

CHIP_ERROR ThreadStackManagerImpl::_InitThreadStack()
{
    CHIP_ERROR err;

    err = PlatformMgrImpl().GLibMatterContextInvokeSync(GLibMatterContextInitThreadStack, this);
    VerifyOrReturnError(err == CHIP_NO_ERROR, err, ChipLogError(DeviceLayer, "openthread: failed to init dbus proxy"));

    // If get property is called inside dbus thread (we are going to make it so), XXX_get_XXX can be used instead of XXX_dup_XXX
    // which is a little bit faster and the returned object doesn't need to be freed. Same for all following get properties.
    std::unique_ptr<gchar, GFree> role(openthread_io_openthread_border_router_dup_device_role(mProxy.get()));
    if (role)
    {
        ThreadDeviceRoleChangedHandler(role.get());
    }

    return CHIP_NO_ERROR;
}

void ThreadStackManagerImpl::OnDbusPropertiesChanged(OpenthreadIoOpenthreadBorderRouter * proxy, GVariant * changed_properties,
                                                     const gchar * const * invalidated_properties, gpointer user_data)
{
    ThreadStackManagerImpl * me = reinterpret_cast<ThreadStackManagerImpl *>(user_data);
    if (g_variant_n_children(changed_properties) > 0)
    {
        const gchar * key;
        GVariant * value;

        std::unique_ptr<GVariantIter, GVariantIterDeleter> iter;
        g_variant_get(changed_properties, "a{sv}", &MakeUniquePointerReceiver(iter).Get());
        if (!iter)
            return;
        while (g_variant_iter_loop(iter.get(), "{&sv}", &key, &value))
        {
            if (key == nullptr || value == nullptr)
                continue;
            // ownership of key and value is still holding by the iter
            DeviceLayer::SystemLayer().ScheduleLambda([me]() { me->_UpdateNetworkStatus(); });

            if (strcmp(key, kPropertyDeviceRole) == 0)
            {
                const gchar * value_str = g_variant_get_string(value, nullptr);
                if (value_str == nullptr)
                    continue;
                ChipLogProgress(DeviceLayer, "Thread role changed to: %s", StringOrNullMarker(value_str));
                me->ThreadDeviceRoleChangedHandler(value_str);
            }
        }
    }
}

void ThreadStackManagerImpl::ThreadDeviceRoleChangedHandler(const gchar * role)
{
    bool attached = strcmp(role, kOpenthreadDeviceRoleDetached) != 0 && strcmp(role, kOpenthreadDeviceRoleDisabled) != 0;

    ChipDeviceEvent event = ChipDeviceEvent{};

    if (attached != mAttached)
    {
        event.Type = DeviceEventType::kThreadConnectivityChange;
        event.ThreadConnectivityChange.Result =
            attached ? ConnectivityChange::kConnectivity_Established : ConnectivityChange::kConnectivity_Lost;
        CHIP_ERROR status = PlatformMgr().PostEvent(&event);
        if (status != CHIP_NO_ERROR)
        {
            ChipLogError(DeviceLayer, "Failed to post thread connectivity change: %" CHIP_ERROR_FORMAT, status.Format());
        }
    }
    mAttached = attached;

    event.Type                          = DeviceEventType::kThreadStateChange;
    event.ThreadStateChange.RoleChanged = true;
    CHIP_ERROR status                   = PlatformMgr().PostEvent(&event);
    if (status != CHIP_NO_ERROR)
    {
        ChipLogError(DeviceLayer, "Failed to post thread state change: %" CHIP_ERROR_FORMAT, status.Format());
    }
}

void ThreadStackManagerImpl::_ProcessThreadActivity() {}

bool ThreadStackManagerImpl::_HaveRouteToAddress(const Inet::IPAddress & destAddr)
{
    if (!mProxy || !_IsThreadAttached())
    {
        return false;
    }
    if (destAddr.IsIPv6LinkLocal())
    {
        return true;
    }

    std::unique_ptr<GVariant, GVariantDeleter> routes(openthread_io_openthread_border_router_dup_external_routes(mProxy.get()));
    if (!routes)
        return false;

    if (g_variant_n_children(routes.get()) > 0)
    {
        std::unique_ptr<GVariantIter, GVariantIterDeleter> iter;
        g_variant_get(routes.get(), "av", &MakeUniquePointerReceiver(iter).Get());
        if (!iter)
            return false;

        GVariant * route;
        while (g_variant_iter_loop(iter.get(), "&v", &route))
        {
            if (route == nullptr)
                continue;
            std::unique_ptr<GVariant, GVariantDeleter> prefix;
            guint16 rloc16;
            guchar preference;
            gboolean stable;
            gboolean nextHopIsThisDevice;
            g_variant_get(route, "(&vqybb)", &MakeUniquePointerReceiver(prefix).Get(), &rloc16, &preference, &stable,
                          &nextHopIsThisDevice);
            if (!prefix)
                continue;

            std::unique_ptr<GVariant, GVariantDeleter> address;
            guchar prefixLength;
            g_variant_get(prefix.get(), "(&vy)", &MakeUniquePointerReceiver(address).Get(), &prefixLength);
            if (!address)
                continue;

            GBytes * bytes = g_variant_get_data_as_bytes(address.get()); // the ownership still hold by address
            if (bytes == nullptr)
                continue;
            gsize size;
            gconstpointer data = g_bytes_get_data(bytes, &size);
            if (data == nullptr)
                continue;
            if (size != sizeof(struct in6_addr))
                continue;

            Inet::IPPrefix p;
            p.IPAddr = Inet::IPAddress(*reinterpret_cast<const struct in6_addr *>(data));
            p.Length = prefixLength;

            if (p.MatchAddress(destAddr))
            {
                return true;
            }
        }
    }

    return false;
}

void ThreadStackManagerImpl::_OnPlatformEvent(const ChipDeviceEvent * event)
{
    (void) event;
    // The otbr-agent processes the Thread state handling by itself so there
    // isn't much to do in the Chip stack.
}

CHIP_ERROR ThreadStackManagerImpl::_SetThreadProvision(ByteSpan netInfo)
{
    VerifyOrReturnError(mProxy, CHIP_ERROR_INCORRECT_STATE);
    VerifyOrReturnError(Thread::OperationalDataset::IsValid(netInfo), CHIP_ERROR_INVALID_ARGUMENT);

    SetActiveDatasetContext context = { mProxy.get(), netInfo };
    CHIP_ERROR err                  = PlatformMgrImpl().GLibMatterContextInvokeSync(GLibMatterContextSetActiveDataset, &context);
    VerifyOrReturnError(err == CHIP_NO_ERROR, err, ChipLogError(DeviceLayer, "openthread: failed to set active dataset"));

    // post an event alerting other subsystems about change in provisioning state
    ChipDeviceEvent event;
    event.Type                                           = DeviceEventType::kServiceProvisioningChange;
    event.ServiceProvisioningChange.IsServiceProvisioned = true;
    return PlatformMgr().PostEvent(&event);
}

CHIP_ERROR ThreadStackManagerImpl::_GetThreadProvision(Thread::OperationalDataset & dataset)
{
    VerifyOrReturnError(mProxy, CHIP_ERROR_INCORRECT_STATE);

    {
        std::unique_ptr<GError, GErrorDeleter> err;

        std::unique_ptr<GVariant, GVariantDeleter> response(
            g_dbus_proxy_call_sync(G_DBUS_PROXY(mProxy.get()), "org.freedesktop.DBus.Properties.Get",
                                   g_variant_new("(ss)", "io.openthread.BorderRouter", "ActiveDatasetTlvs"), G_DBUS_CALL_FLAGS_NONE,
                                   -1, nullptr, &MakeUniquePointerReceiver(err).Get()));

        if (err)
        {
            ChipLogError(DeviceLayer, "openthread: failed to read ActiveDatasetTlvs property: %s", err->message);
            return CHIP_ERROR_INTERNAL;
        }

        // Note: The actual value is wrapped by a GVariant container, wrapped in another GVariant with tuple type.

        if (response == nullptr)
        {
            return CHIP_ERROR_KEY_NOT_FOUND;
        }

        std::unique_ptr<GVariant, GVariantDeleter> tupleContent(g_variant_get_child_value(response.get(), 0));

        if (tupleContent == nullptr)
        {
            return CHIP_ERROR_KEY_NOT_FOUND;
        }

        std::unique_ptr<GVariant, GVariantDeleter> value(g_variant_get_variant(tupleContent.get()));

        if (value == nullptr)
        {
            return CHIP_ERROR_KEY_NOT_FOUND;
        }

        gsize size;
        const uint8_t * data = reinterpret_cast<const uint8_t *>(g_variant_get_fixed_array(value.get(), &size, sizeof(guchar)));
        ReturnErrorOnFailure(mDataset.Init(ByteSpan(data, size)));
    }

    dataset.Init(mDataset.AsByteSpan());

    return CHIP_NO_ERROR;
}

bool ThreadStackManagerImpl::_IsThreadProvisioned()
{
    return static_cast<Thread::OperationalDataset &>(mDataset).IsCommissioned();
}

void ThreadStackManagerImpl::_ErasePersistentInfo()
{
    static_cast<Thread::OperationalDataset &>(mDataset).Clear();
}

bool ThreadStackManagerImpl::_IsThreadEnabled()
{
    VerifyOrReturnError(mProxy, false);

    std::unique_ptr<GError, GErrorDeleter> err;

    std::unique_ptr<GVariant, GVariantDeleter> response(
        g_dbus_proxy_call_sync(G_DBUS_PROXY(mProxy.get()), "org.freedesktop.DBus.Properties.Get",
                               g_variant_new("(ss)", "io.openthread.BorderRouter", "DeviceRole"), G_DBUS_CALL_FLAGS_NONE, -1,
                               nullptr, &MakeUniquePointerReceiver(err).Get()));

    if (err)
    {
        ChipLogError(DeviceLayer, "openthread: failed to read DeviceRole property: %s", err->message);
        return false;
    }

    if (response == nullptr)
    {
        return false;
    }

    std::unique_ptr<GVariant, GVariantDeleter> tupleContent(g_variant_get_child_value(response.get(), 0));

    if (tupleContent == nullptr)
    {
        return false;
    }

    std::unique_ptr<GVariant, GVariantDeleter> value(g_variant_get_variant(tupleContent.get()));

    if (value == nullptr)
    {
        return false;
    }

    const gchar * role = g_variant_get_string(value.get(), nullptr);

    if (role == nullptr)
    {
        return false;
    }

    return (strcmp(role, kOpenthreadDeviceRoleDisabled) != 0);
}

bool ThreadStackManagerImpl::_IsThreadAttached() const
{
    return mAttached;
}

CHIP_ERROR ThreadStackManagerImpl::GLibMatterContextCallAttach(ThreadStackManagerImpl * self)
{
    VerifyOrDie(g_main_context_get_thread_default() != nullptr);
    openthread_io_openthread_border_router_call_attach(self->mProxy.get(), nullptr, _OnThreadBrAttachFinished, self);
    return CHIP_NO_ERROR;
}

CHIP_ERROR ThreadStackManagerImpl::_SetThreadEnabled(bool val)
{
    VerifyOrReturnError(mProxy, CHIP_ERROR_INCORRECT_STATE);
    if (val)
    {
        CHIP_ERROR err = PlatformMgrImpl().GLibMatterContextInvokeSync(GLibMatterContextCallAttach, this);
        VerifyOrReturnError(err == CHIP_NO_ERROR, err, ChipLogError(DeviceLayer, "openthread: failed to attach"));
    }
    else
    {
        std::unique_ptr<GError, GErrorDeleter> err;
        gboolean result =
            openthread_io_openthread_border_router_call_reset_sync(mProxy.get(), nullptr, &MakeUniquePointerReceiver(err).Get());
        if (err)
        {
            ChipLogError(DeviceLayer, "openthread: _SetThreadEnabled calling %s failed: %s", "Reset", err->message);
            return CHIP_ERROR_INTERNAL;
        }

        if (!result)
        {
            ChipLogError(DeviceLayer, "openthread: _SetThreadEnabled calling %s failed: %s", "Reset", "return false");
            return CHIP_ERROR_INTERNAL;
        }
    }
    return CHIP_NO_ERROR;
}

void ThreadStackManagerImpl::_OnThreadBrAttachFinished(GObject * source_object, GAsyncResult * res, gpointer user_data)
{
    ThreadStackManagerImpl * this_ = reinterpret_cast<ThreadStackManagerImpl *>(user_data);
    std::unique_ptr<GVariant, GVariantDeleter> attachRes;
    std::unique_ptr<GError, GErrorDeleter> err;
    {
        gboolean result = openthread_io_openthread_border_router_call_attach_finish(this_->mProxy.get(), res,
                                                                                    &MakeUniquePointerReceiver(err).Get());
        if (!result)
        {
            ChipLogError(DeviceLayer, "Failed to perform finish Thread network scan: %s",
                         err == nullptr ? "unknown error" : err->message);
            DeviceLayer::SystemLayer().ScheduleLambda([this_]() {
                if (this_->mpConnectCallback != nullptr)
                {
                    // TODO: Replace this with actual thread attach result.
                    this_->mpConnectCallback->OnResult(NetworkCommissioning::Status::kUnknownError, CharSpan(), 0);
                    this_->mpConnectCallback = nullptr;
                }
            });
        }
        else
        {
            DeviceLayer::SystemLayer().ScheduleLambda([this_]() {
                if (this_->mpConnectCallback != nullptr)
                {
                    // TODO: Replace this with actual thread attach result.
                    this_->mpConnectCallback->OnResult(NetworkCommissioning::Status::kSuccess, CharSpan(), 0);
                    this_->mpConnectCallback = nullptr;
                }
            });
        }
    }
}

ConnectivityManager::ThreadDeviceType ThreadStackManagerImpl::_GetThreadDeviceType()
{
    ConnectivityManager::ThreadDeviceType type = ConnectivityManager::ThreadDeviceType::kThreadDeviceType_NotSupported;
    if (!mProxy)
    {
        ChipLogError(DeviceLayer, "Cannot get device role with Thread api client: %s", "");
        return ConnectivityManager::ThreadDeviceType::kThreadDeviceType_NotSupported;
    }

    std::unique_ptr<gchar, GFree> role(openthread_io_openthread_border_router_dup_device_role(mProxy.get()));
    if (!role)
        return ConnectivityManager::ThreadDeviceType::kThreadDeviceType_NotSupported;
    if (strcmp(role.get(), kOpenthreadDeviceRoleDetached) == 0 || strcmp(role.get(), kOpenthreadDeviceRoleDisabled) == 0)
    {
        return ConnectivityManager::ThreadDeviceType::kThreadDeviceType_NotSupported;
    }
    if (strcmp(role.get(), kOpenthreadDeviceRoleChild) == 0)
    {
        std::unique_ptr<GVariant, GVariantDeleter> linkMode(openthread_io_openthread_border_router_dup_link_mode(mProxy.get()));
        if (!linkMode)
            return ConnectivityManager::ThreadDeviceType::kThreadDeviceType_NotSupported;
        gboolean rx_on_when_idle;
        gboolean device_type;
        gboolean network_data;
        g_variant_get(linkMode.get(), "(bbb)", &rx_on_when_idle, &device_type, &network_data);
        if (!rx_on_when_idle)
        {
            type = ConnectivityManager::ThreadDeviceType::kThreadDeviceType_SleepyEndDevice;
        }
        else
        {
            type = device_type ? ConnectivityManager::ThreadDeviceType::kThreadDeviceType_FullEndDevice
                               : ConnectivityManager::ThreadDeviceType::kThreadDeviceType_MinimalEndDevice;
        }
        return type;
    }
    if (strcmp(role.get(), kOpenthreadDeviceRoleLeader) == 0 || strcmp(role.get(), kOpenthreadDeviceRoleRouter) == 0)
    {
        return ConnectivityManager::ThreadDeviceType::kThreadDeviceType_Router;
    }

    ChipLogError(DeviceLayer, "Unknown Thread role: %s", role.get());
    return ConnectivityManager::ThreadDeviceType::kThreadDeviceType_NotSupported;
}

CHIP_ERROR ThreadStackManagerImpl::_SetThreadDeviceType(ConnectivityManager::ThreadDeviceType deviceType)
{
    gboolean rx_on_when_idle = true;
    gboolean device_type     = true;
    gboolean network_data    = true;
    VerifyOrReturnError(mProxy, CHIP_ERROR_INCORRECT_STATE);
    if (deviceType == ConnectivityManager::ThreadDeviceType::kThreadDeviceType_MinimalEndDevice)
    {
        network_data = false;
    }
    else if (deviceType == ConnectivityManager::ThreadDeviceType::kThreadDeviceType_SleepyEndDevice)
    {
        rx_on_when_idle = false;
        network_data    = false;
    }

    if (!network_data)
    {
        std::unique_ptr<GVariant, GVariantDeleter> linkMode(g_variant_new("(bbb)", rx_on_when_idle, device_type, network_data));
        if (!linkMode)
            return CHIP_ERROR_NO_MEMORY;
        openthread_io_openthread_border_router_set_link_mode(mProxy.get(), linkMode.release());
    }

    return CHIP_NO_ERROR;
}

#if CHIP_DEVICE_CONFIG_ENABLE_SED
CHIP_ERROR ThreadStackManagerImpl::_GetSEDIntervalsConfig(ConnectivityManager::SEDIntervalsConfig & intervalsConfig)
{
    (void) intervalsConfig;

    ChipLogError(DeviceLayer, "SED intervals config is not supported on linux");
    return CHIP_ERROR_NOT_IMPLEMENTED;
}

CHIP_ERROR ThreadStackManagerImpl::_SetSEDIntervalsConfig(const ConnectivityManager::SEDIntervalsConfig & intervalsConfig)
{
    (void) intervalsConfig;

    ChipLogError(DeviceLayer, "SED intervals config is not supported on linux");
    return CHIP_ERROR_NOT_IMPLEMENTED;
}

CHIP_ERROR ThreadStackManagerImpl::_RequestSEDActiveMode(bool onOff, bool delayIdle)
{
    (void) onOff;
    (void) delayIdle;

    ChipLogError(DeviceLayer, "SED intervals config is not supported on linux");
    return CHIP_ERROR_NOT_IMPLEMENTED;
}
#endif

bool ThreadStackManagerImpl::_HaveMeshConnectivity()
{
    // TODO: Remove Weave legacy APIs
    // For a leader with a child, the child is considered to have mesh connectivity
    // and the leader is not, which is a very confusing definition.
    // This API is Weave legacy and should be removed.

    ChipLogError(DeviceLayer, "HaveMeshConnectivity has confusing behavior and shouldn't be called");
    return false;
}

CHIP_ERROR ThreadStackManagerImpl::_GetAndLogThreadStatsCounters()
{
    // TODO: Remove Weave legacy APIs
    return CHIP_ERROR_NOT_IMPLEMENTED;
}

CHIP_ERROR ThreadStackManagerImpl::_GetAndLogThreadTopologyMinimal()
{
    // TODO: Remove Weave legacy APIs
    return CHIP_ERROR_NOT_IMPLEMENTED;
}

CHIP_ERROR ThreadStackManagerImpl::_GetAndLogThreadTopologyFull()
{
    // TODO: Remove Weave legacy APIs
    return CHIP_ERROR_NOT_IMPLEMENTED;
}

CHIP_ERROR ThreadStackManagerImpl::_GetPrimary802154MACAddress(uint8_t * buf)
{
    VerifyOrReturnError(mProxy, CHIP_ERROR_INCORRECT_STATE);
    guint64 extAddr = openthread_io_openthread_border_router_get_extended_address(mProxy.get());

    for (size_t i = 0; i < sizeof(extAddr); i++)
    {
        buf[sizeof(uint64_t) - i - 1] = (extAddr & UINT8_MAX);
        extAddr >>= CHAR_BIT;
    }

    return CHIP_NO_ERROR;
}

CHIP_ERROR ThreadStackManagerImpl::_GetExternalIPv6Address(chip::Inet::IPAddress & addr)
{
    // TODO: Remove Weave legacy APIs
    return CHIP_ERROR_NOT_IMPLEMENTED;
}

CHIP_ERROR ThreadStackManagerImpl::_GetPollPeriod(uint32_t & buf)
{
    // TODO: Remove Weave legacy APIs
    return CHIP_ERROR_NOT_IMPLEMENTED;
}

CHIP_ERROR ThreadStackManagerImpl::_JoinerStart()
{
    // TODO: Remove Weave legacy APIs
    return CHIP_ERROR_NOT_IMPLEMENTED;
}

void ThreadStackManagerImpl::_SetRouterPromotion(bool val)
{
    // Set Router Promotion is not supported on linux
}

CHIP_ERROR ThreadStackManagerImpl::GLibMatterContextCallScan(ThreadStackManagerImpl * self)
{
    VerifyOrDie(g_main_context_get_thread_default() != nullptr);
    openthread_io_openthread_border_router_call_scan(self->mProxy.get(), nullptr, _OnNetworkScanFinished, self);
    return CHIP_NO_ERROR;
}

CHIP_ERROR ThreadStackManagerImpl::_StartThreadScan(ThreadDriver::ScanCallback * callback)
{
    // There is another ongoing scan request, reject the new one.
    VerifyOrReturnError(mpScanCallback == nullptr, CHIP_ERROR_INCORRECT_STATE);
    mpScanCallback = callback;
    CHIP_ERROR err = PlatformMgrImpl().GLibMatterContextInvokeSync(GLibMatterContextCallScan, this);
    VerifyOrReturnError(err == CHIP_NO_ERROR, err, ChipLogError(DeviceLayer, "openthread: failed to start scan"));
    return CHIP_NO_ERROR;
}

void ThreadStackManagerImpl::_OnNetworkScanFinished(GObject * source_object, GAsyncResult * res, gpointer user_data)
{
    ThreadStackManagerImpl * this_ = reinterpret_cast<ThreadStackManagerImpl *>(user_data);
    this_->_OnNetworkScanFinished(res);
}

void ThreadStackManagerImpl::_OnNetworkScanFinished(GAsyncResult * res)
{
    std::unique_ptr<GVariant, GVariantDeleter> scan_result;
    std::unique_ptr<GError, GErrorDeleter> err;
    {
        gboolean result = openthread_io_openthread_border_router_call_scan_finish(
            mProxy.get(), &MakeUniquePointerReceiver(scan_result).Get(), res, &MakeUniquePointerReceiver(err).Get());
        if (!result)
        {
            ChipLogError(DeviceLayer, "Failed to perform finish Thread network scan: %s",
                         err == nullptr ? "unknown error" : err->message);
            DeviceLayer::SystemLayer().ScheduleLambda([this]() {
                if (mpScanCallback != nullptr)
                {
                    LinuxScanResponseIterator<ThreadScanResponse> iter(nullptr);
                    mpScanCallback->OnFinished(Status::kUnknownError, CharSpan(), &iter);
                }
                mpScanCallback = nullptr;
            });
        }
    }

    std::vector<NetworkCommissioning::ThreadScanResponse> * scanResult =
        new std::vector<NetworkCommissioning::ThreadScanResponse>();

    if (g_variant_n_children(scan_result.get()) > 0)
    {
        std::unique_ptr<GVariantIter, GVariantIterDeleter> iter;
        g_variant_get(scan_result.get(), "a(tstayqqyyyybb)", &MakeUniquePointerReceiver(iter).Get());
        if (!iter)
        {
            delete scanResult;
            return;
        }

        guint64 ext_address;
        const gchar * network_name;
        guint64 ext_panid;
        const gchar * steering_data;
        guint16 panid;
        guint16 joiner_udp_port;
        guint8 channel;
        guint8 rssi;
        guint8 lqi;
        guint8 version;
        gboolean is_native;
        gboolean is_joinable;

        while (g_variant_iter_loop(iter.get(), "(tstayqqyyyybb)", &ext_address, &network_name, &ext_panid, &steering_data, &panid,
                                   &joiner_udp_port, &channel, &rssi, &lqi, &version, &is_native, &is_joinable))
        {
            ChipLogProgress(DeviceLayer,
                            "Thread Network: %s (%016" PRIx64 ") ExtPanId(%016" PRIx64 ") RSSI %u LQI %u"
                            " Version %u",
                            network_name, ext_address, ext_panid, rssi, lqi, version);
            NetworkCommissioning::ThreadScanResponse networkScanned;
            networkScanned.panId         = panid;
            networkScanned.extendedPanId = ext_panid;
            size_t networkNameLen        = strlen(network_name);
            if (networkNameLen > 16)
            {
                ChipLogProgress(DeviceLayer, "Network name is too long, ignore it.");
                continue;
            }
            networkScanned.networkNameLen = static_cast<uint8_t>(networkNameLen);
            memcpy(networkScanned.networkName, network_name, networkNameLen);
            networkScanned.channel         = channel;
            networkScanned.version         = version;
            networkScanned.extendedAddress = 0;
            networkScanned.rssi            = rssi;
            networkScanned.lqi             = lqi;

            scanResult->push_back(networkScanned);
        }
    }

    DeviceLayer::SystemLayer().ScheduleLambda([this, scanResult]() {
        // Note: We cannot post a event in ScheduleLambda since std::vector is not trivial copiable. This results in the use of
        // const_cast but should be fine for almost all cases, since we actually handled the ownership of this element to this
        // lambda.
        if (mpScanCallback != nullptr)
        {
            LinuxScanResponseIterator<NetworkCommissioning::ThreadScanResponse> iter(
                const_cast<std::vector<ThreadScanResponse> *>(scanResult));
            mpScanCallback->OnFinished(Status::kSuccess, CharSpan(), &iter);
            mpScanCallback = nullptr;
        }
        delete const_cast<std::vector<ThreadScanResponse> *>(scanResult);
    });
}

void ThreadStackManagerImpl::_ResetThreadNetworkDiagnosticsCounts() {}

CHIP_ERROR ThreadStackManagerImpl::_WriteThreadNetworkDiagnosticAttributeToTlv(AttributeId attributeId,
                                                                               app::AttributeValueEncoder & encoder)
{
    CHIP_ERROR err = CHIP_NO_ERROR;

    switch (attributeId)
    {
    case ThreadNetworkDiagnostics::Attributes::NeighborTable::Id:
    case ThreadNetworkDiagnostics::Attributes::RouteTable::Id:
    case ThreadNetworkDiagnostics::Attributes::ActiveNetworkFaultsList::Id:
        err = encoder.EncodeEmptyList();
        break;
    case ThreadNetworkDiagnostics::Attributes::Channel::Id:
    case ThreadNetworkDiagnostics::Attributes::RoutingRole::Id:
    case ThreadNetworkDiagnostics::Attributes::NetworkName::Id:
    case ThreadNetworkDiagnostics::Attributes::PanId::Id:
    case ThreadNetworkDiagnostics::Attributes::ExtendedPanId::Id:
    case ThreadNetworkDiagnostics::Attributes::MeshLocalPrefix::Id:
    case ThreadNetworkDiagnostics::Attributes::PartitionId::Id:
    case ThreadNetworkDiagnostics::Attributes::Weighting::Id:
    case ThreadNetworkDiagnostics::Attributes::DataVersion::Id:
    case ThreadNetworkDiagnostics::Attributes::StableDataVersion::Id:
    case ThreadNetworkDiagnostics::Attributes::LeaderRouterId::Id:
    case ThreadNetworkDiagnostics::Attributes::ActiveTimestamp::Id:
    case ThreadNetworkDiagnostics::Attributes::PendingTimestamp::Id:
    case ThreadNetworkDiagnostics::Attributes::Delay::Id:
    case ThreadNetworkDiagnostics::Attributes::ChannelPage0Mask::Id:
    case ThreadNetworkDiagnostics::Attributes::SecurityPolicy::Id:
    case ThreadNetworkDiagnostics::Attributes::OperationalDatasetComponents::Id:
        err = encoder.EncodeNull();
        break;
    case ThreadNetworkDiagnostics::Attributes::OverrunCount::Id:
        err = encoder.Encode(static_cast<uint64_t>(0));
        break;
    case ThreadNetworkDiagnostics::Attributes::DetachedRoleCount::Id:
        err = encoder.Encode(static_cast<uint16_t>(0));
        break;
    case ThreadNetworkDiagnostics::Attributes::ChildRoleCount::Id:
        err = encoder.Encode(static_cast<uint16_t>(0));
        break;
    case ThreadNetworkDiagnostics::Attributes::RouterRoleCount::Id:
        err = encoder.Encode(static_cast<uint16_t>(0));
        break;
    case ThreadNetworkDiagnostics::Attributes::LeaderRoleCount::Id:
        err = encoder.Encode(static_cast<uint16_t>(0));
        break;
    case ThreadNetworkDiagnostics::Attributes::AttachAttemptCount::Id:
        err = encoder.Encode(static_cast<uint16_t>(0));
        break;
    case ThreadNetworkDiagnostics::Attributes::PartitionIdChangeCount::Id:
        err = encoder.Encode(static_cast<uint16_t>(0));
        break;
    case ThreadNetworkDiagnostics::Attributes::BetterPartitionAttachAttemptCount::Id:
        err = encoder.Encode(static_cast<uint16_t>(0));
        break;
    case ThreadNetworkDiagnostics::Attributes::ParentChangeCount::Id:
        err = encoder.Encode(static_cast<uint16_t>(0));
        break;
    case ThreadNetworkDiagnostics::Attributes::TxTotalCount::Id:
        err = encoder.Encode(static_cast<uint32_t>(0));
        break;
    case ThreadNetworkDiagnostics::Attributes::TxUnicastCount::Id:
        err = encoder.Encode(static_cast<uint32_t>(0));
        break;
    case ThreadNetworkDiagnostics::Attributes::TxBroadcastCount::Id:
        err = encoder.Encode(static_cast<uint32_t>(0));
        break;
    case ThreadNetworkDiagnostics::Attributes::TxAckRequestedCount::Id:
        err = encoder.Encode(static_cast<uint32_t>(0));
        break;
    case ThreadNetworkDiagnostics::Attributes::TxAckedCount::Id:
        err = encoder.Encode(static_cast<uint32_t>(0));
        break;
    case ThreadNetworkDiagnostics::Attributes::TxNoAckRequestedCount::Id:
        err = encoder.Encode(static_cast<uint32_t>(0));
        break;
    case ThreadNetworkDiagnostics::Attributes::TxDataCount::Id:
        err = encoder.Encode(static_cast<uint32_t>(0));
        break;
    case ThreadNetworkDiagnostics::Attributes::TxDataPollCount::Id:
        err = encoder.Encode(static_cast<uint32_t>(0));
        break;
    case ThreadNetworkDiagnostics::Attributes::TxBeaconCount::Id:
        err = encoder.Encode(static_cast<uint32_t>(0));
        break;
    case ThreadNetworkDiagnostics::Attributes::TxBeaconRequestCount::Id:
        err = encoder.Encode(static_cast<uint32_t>(0));
        break;
    case ThreadNetworkDiagnostics::Attributes::TxOtherCount::Id:
        err = encoder.Encode(static_cast<uint32_t>(0));
        break;
    case ThreadNetworkDiagnostics::Attributes::TxRetryCount::Id:
        err = encoder.Encode(static_cast<uint32_t>(0));
        break;
    case ThreadNetworkDiagnostics::Attributes::TxDirectMaxRetryExpiryCount::Id:
        err = encoder.Encode(static_cast<uint32_t>(0));
        break;
    case ThreadNetworkDiagnostics::Attributes::TxIndirectMaxRetryExpiryCount::Id:
        err = encoder.Encode(static_cast<uint32_t>(0));
        break;
    case ThreadNetworkDiagnostics::Attributes::TxErrCcaCount::Id:
        err = encoder.Encode(static_cast<uint32_t>(0));
        break;
    case ThreadNetworkDiagnostics::Attributes::TxErrAbortCount::Id:
        err = encoder.Encode(static_cast<uint32_t>(0));
        break;
    case ThreadNetworkDiagnostics::Attributes::TxErrBusyChannelCount::Id:
        err = encoder.Encode(static_cast<uint32_t>(0));
        break;
    case ThreadNetworkDiagnostics::Attributes::RxTotalCount::Id:
        err = encoder.Encode(static_cast<uint32_t>(0));
        break;
    case ThreadNetworkDiagnostics::Attributes::RxUnicastCount::Id:
        err = encoder.Encode(static_cast<uint32_t>(0));
        break;
    case ThreadNetworkDiagnostics::Attributes::RxBroadcastCount::Id:
        err = encoder.Encode(static_cast<uint32_t>(0));
        break;
    case ThreadNetworkDiagnostics::Attributes::RxDataCount::Id:
        err = encoder.Encode(static_cast<uint32_t>(0));
        break;
    case ThreadNetworkDiagnostics::Attributes::RxDataPollCount::Id:
        err = encoder.Encode(static_cast<uint32_t>(0));
        break;
    case ThreadNetworkDiagnostics::Attributes::RxBeaconCount::Id:
        err = encoder.Encode(static_cast<uint32_t>(0));
        break;
    case ThreadNetworkDiagnostics::Attributes::RxBeaconRequestCount::Id:
        err = encoder.Encode(static_cast<uint32_t>(0));
        break;
    case ThreadNetworkDiagnostics::Attributes::RxOtherCount::Id:
        err = encoder.Encode(static_cast<uint32_t>(0));
        break;
    case ThreadNetworkDiagnostics::Attributes::RxAddressFilteredCount::Id:
        err = encoder.Encode(static_cast<uint32_t>(0));
        break;
    case ThreadNetworkDiagnostics::Attributes::RxDestAddrFilteredCount::Id:
        err = encoder.Encode(static_cast<uint32_t>(0));
        break;
    case ThreadNetworkDiagnostics::Attributes::RxDuplicatedCount::Id:
        err = encoder.Encode(static_cast<uint32_t>(0));
        break;
    case ThreadNetworkDiagnostics::Attributes::RxErrNoFrameCount::Id:
        err = encoder.Encode(static_cast<uint32_t>(0));
        break;
    case ThreadNetworkDiagnostics::Attributes::RxErrUnknownNeighborCount::Id:
        err = encoder.Encode(static_cast<uint32_t>(0));
        break;
    case ThreadNetworkDiagnostics::Attributes::RxErrInvalidSrcAddrCount::Id:
        err = encoder.Encode(static_cast<uint32_t>(0));
        break;
    case ThreadNetworkDiagnostics::Attributes::RxErrSecCount::Id:
        err = encoder.Encode(static_cast<uint32_t>(0));
        break;
    case ThreadNetworkDiagnostics::Attributes::RxErrFcsCount::Id:
        err = encoder.Encode(static_cast<uint32_t>(0));
        break;
    case ThreadNetworkDiagnostics::Attributes::RxErrOtherCount::Id:
        err = encoder.Encode(static_cast<uint32_t>(0));
        break;
    default:
        err = CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE;
        break;
    }

    return err;
}

CHIP_ERROR
ThreadStackManagerImpl::_AttachToThreadNetwork(const Thread::OperationalDataset & dataset,
                                               NetworkCommissioning::Internal::WirelessDriver::ConnectCallback * callback)
{
    // Reset the previously set callback since it will never be called in case incorrect dataset was supplied.
    mpConnectCallback = nullptr;
    ReturnErrorOnFailure(DeviceLayer::ThreadStackMgr().SetThreadEnabled(false));
    ReturnErrorOnFailure(DeviceLayer::ThreadStackMgr().SetThreadProvision(dataset.AsByteSpan()));

    if (dataset.IsCommissioned())
    {
        ReturnErrorOnFailure(DeviceLayer::ThreadStackMgr().SetThreadEnabled(true));
        mpConnectCallback = callback;
    }

    return CHIP_NO_ERROR;
}

void ThreadStackManagerImpl::_UpdateNetworkStatus()
{
    // Thread is not enabled, then we are not trying to connect to the network.
    VerifyOrReturn(IsThreadEnabled() && mpStatusChangeCallback != nullptr);

    Thread::OperationalDataset dataset;
    uint8_t extpanid[Thread::kSizeExtendedPanId];

    // If we have not provisioned any Thread network, return the status from last network scan,
    // If we have provisioned a network, we assume the ot-br-posix is activitely connecting to that network.
    CHIP_ERROR err = ThreadStackMgrImpl().GetThreadProvision(dataset);
    if (err != CHIP_NO_ERROR)
    {
        ChipLogError(DeviceLayer, "Failed to get configured network when updating network status: %s", err.AsString());
        return;
    }

    // The Thread network is not enabled, but has a different extended pan id.
    VerifyOrReturn(dataset.GetExtendedPanId(extpanid) == CHIP_NO_ERROR);

    // We have already connected to the network, thus return success.
    if (ThreadStackMgrImpl().IsThreadAttached())
    {
        mpStatusChangeCallback->OnNetworkingStatusChange(Status::kSuccess, MakeOptional(ByteSpan(extpanid)), NullOptional);
    }
    else
    {
        mpStatusChangeCallback->OnNetworkingStatusChange(Status::kNetworkNotFound, MakeOptional(ByteSpan(extpanid)), NullOptional);
    }
}

ThreadStackManager & ThreadStackMgr()
{
    return chip::DeviceLayer::ThreadStackManagerImpl::sInstance;
}

ThreadStackManagerImpl & ThreadStackMgrImpl()
{
    return chip::DeviceLayer::ThreadStackManagerImpl::sInstance;
}

} // namespace DeviceLayer
} // namespace chip
