/*
 *
 *    Copyright (c) 2019 Nest Labs, Inc.
 *    All rights reserved.
 *
 *    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.
 */

/**
 *    @file
 *          Contains non-inline method definitions for the
 *          GenericThreadStackManagerImpl_OpenThread<> template.
 */

#ifndef GENERIC_THREAD_STACK_MANAGER_IMPL_OPENTHREAD_IPP
#define GENERIC_THREAD_STACK_MANAGER_IMPL_OPENTHREAD_IPP

#include <Weave/DeviceLayer/internal/WeaveDeviceLayerInternal.h>
#include <Weave/DeviceLayer/ThreadStackManager.h>
#include <Weave/DeviceLayer/OpenThread/GenericThreadStackManagerImpl_OpenThread.h>
#include <Weave/DeviceLayer/OpenThread/OpenThreadUtils.h>
#include <Weave/Profiles/network-provisioning/NetworkProvisioning.h>
#include <Weave/DeviceLayer/internal/DeviceNetworkInfo.h>
#include <Weave/Support/crypto/WeaveRNG.h>
#include <Weave/Support/TraitEventUtils.h>
#include <nest/trait/network/TelemetryNetworkWpanTrait.h>

#include <openthread/thread.h>
#include <openthread/tasklet.h>
#include <openthread/link.h>
#include <openthread/dataset.h>
#include <openthread/dataset_ftd.h>
#include <openthread/thread_ftd.h>

using namespace ::nl::Weave::Profiles::NetworkProvisioning;
using namespace Schema::Nest::Trait::Network;

extern "C" void otSysProcessDrivers(otInstance *aInstance);

namespace nl {
namespace Weave {
namespace DeviceLayer {
namespace Internal {

// Assert some presumptions in this code
static_assert(DeviceNetworkInfo::kMaxThreadNetworkNameLength == OT_NETWORK_NAME_MAX_SIZE);
static_assert(DeviceNetworkInfo::kThreadExtendedPANIdLength == OT_EXT_PAN_ID_SIZE);
static_assert(DeviceNetworkInfo::kThreadMeshPrefixLength == OT_MESH_LOCAL_PREFIX_SIZE);
static_assert(DeviceNetworkInfo::kThreadNetworkKeyLength == OT_MASTER_KEY_SIZE);
static_assert(DeviceNetworkInfo::kThreadPSKcLength == OT_PSKC_MAX_SIZE);

// Fully instantiate the generic implementation class in whatever compilation unit includes this file.
template class GenericThreadStackManagerImpl_OpenThread<ThreadStackManagerImpl>;

/**
 * Called by OpenThread to alert the ThreadStackManager of a change in the state of the Thread stack.
 *
 * By default, applications never need to call this method directly.  However, applications that
 * wish to receive OpenThread state change call-backs directly from OpenThread (e.g. by calling
 * otSetStateChangedCallback() with their own callback function) can call this method to pass
 * state change events to the ThreadStackManager.
 */
template<class ImplClass>
void GenericThreadStackManagerImpl_OpenThread<ImplClass>::OnOpenThreadStateChange(uint32_t flags, void * context)
{
    WeaveDeviceEvent event;
    event.Type = DeviceEventType::kThreadStateChange;
    event.ThreadStateChange.RoleChanged = (flags & OT_CHANGED_THREAD_ROLE) != 0;
    event.ThreadStateChange.AddressChanged = (flags & (OT_CHANGED_IP6_ADDRESS_ADDED|OT_CHANGED_IP6_ADDRESS_REMOVED)) != 0;
    event.ThreadStateChange.NetDataChanged = (flags & OT_CHANGED_THREAD_NETDATA) != 0;
    event.ThreadStateChange.ChildNodesChanged = (flags & (OT_CHANGED_THREAD_CHILD_ADDED|OT_CHANGED_THREAD_CHILD_REMOVED)) != 0;
    event.ThreadStateChange.OpenThread.Flags = flags;
    PlatformMgr().PostEvent(&event);
}

template<class ImplClass>
void GenericThreadStackManagerImpl_OpenThread<ImplClass>::_ProcessThreadActivity(void)
{
    otTaskletsProcess(mOTInst);
    otSysProcessDrivers(mOTInst);
}

template<class ImplClass>
bool GenericThreadStackManagerImpl_OpenThread<ImplClass>::_HaveRouteToAddress(const IPAddress & destAddr)
{
    bool res = false;

    // Lock OpenThread
    Impl()->LockThreadStack();

    // No routing of IPv4 over Thread.
    VerifyOrExit(!destAddr.IsIPv4(), res = false);

    // If the device is attached to a Thread network...
    if (IsThreadAttachedNoLock())
    {
        // Link-local addresses are always presumed to be routable, provided the device is attached.
        if (destAddr.IsIPv6LinkLocal())
        {
            ExitNow(res = true);
        }

        // Iterate over the routes known to the OpenThread stack looking for a route that covers the
        // destination address.  If found, consider the address routable.
        // Ignore any routes advertised by this device.
        // If the destination address is a ULA, ignore default routes. Border routers advertising
        // default routes are not expected to be capable of routing Weave fabric ULAs unless they
        // advertise those routes specifically.
        {
            otError otErr;
            otNetworkDataIterator routeIter = OT_NETWORK_DATA_ITERATOR_INIT;
            otExternalRouteConfig routeConfig;
            const bool destIsULA = destAddr.IsIPv6ULA();

            while ((otErr = otNetDataGetNextRoute(Impl()->OTInstance(), &routeIter, &routeConfig)) == OT_ERROR_NONE)
            {
                const IPPrefix prefix = ToIPPrefix(routeConfig.mPrefix);
                char addrStr[64];
                prefix.IPAddr.ToString(addrStr, sizeof(addrStr));
                if (!routeConfig.mNextHopIsThisDevice &&
                    (!destIsULA || routeConfig.mPrefix.mLength > 0) &&
                    ToIPPrefix(routeConfig.mPrefix).MatchAddress(destAddr))
                {
                    ExitNow(res = true);
                }
            }
        }
    }

exit:

    // Unlock OpenThread
    Impl()->UnlockThreadStack();

    return res;
}

template<class ImplClass>
void GenericThreadStackManagerImpl_OpenThread<ImplClass>::_OnPlatformEvent(const WeaveDeviceEvent * event)
{
    if (event->Type == DeviceEventType::kThreadStateChange)
    {
#if WEAVE_DETAIL_LOGGING

        Impl()->LockThreadStack();

        LogOpenThreadStateChange(mOTInst, event->ThreadStateChange.OpenThread.Flags);

        Impl()->UnlockThreadStack();

#endif // WEAVE_DETAIL_LOGGING
    }
}

template<class ImplClass>
bool GenericThreadStackManagerImpl_OpenThread<ImplClass>::_IsThreadEnabled(void)
{
    otDeviceRole curRole;

    Impl()->LockThreadStack();
    curRole = otThreadGetDeviceRole(mOTInst);
    Impl()->UnlockThreadStack();

    return (curRole != OT_DEVICE_ROLE_DISABLED);
}

template<class ImplClass>
WEAVE_ERROR GenericThreadStackManagerImpl_OpenThread<ImplClass>::_SetThreadEnabled(bool val)
{
    otError otErr = OT_ERROR_NONE;

    Impl()->LockThreadStack();

    bool isEnabled = (otThreadGetDeviceRole(mOTInst) != OT_DEVICE_ROLE_DISABLED);
    if (val != isEnabled)
    {
        otErr = otThreadSetEnabled(mOTInst, val);
    }

    Impl()->UnlockThreadStack();

    return MapOpenThreadError(otErr);
}

template<class ImplClass>
bool GenericThreadStackManagerImpl_OpenThread<ImplClass>::_IsThreadProvisioned(void)
{
    bool provisioned;

    Impl()->LockThreadStack();
    provisioned = otDatasetIsCommissioned(mOTInst);
    Impl()->UnlockThreadStack();

    return provisioned;
}

template<class ImplClass>
bool GenericThreadStackManagerImpl_OpenThread<ImplClass>::_IsThreadAttached(void)
{
    otDeviceRole curRole;

    Impl()->LockThreadStack();
    curRole = otThreadGetDeviceRole(mOTInst);
    Impl()->UnlockThreadStack();

    return (curRole != OT_DEVICE_ROLE_DISABLED && curRole != OT_DEVICE_ROLE_DETACHED);
}

template<class ImplClass>
WEAVE_ERROR GenericThreadStackManagerImpl_OpenThread<ImplClass>::_GetThreadProvision(DeviceNetworkInfo & netInfo, bool includeCredentials)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;
    otOperationalDataset activeDataset;

    netInfo.Reset();

    Impl()->LockThreadStack();

    if (otDatasetIsCommissioned(mOTInst))
    {
        otError otErr = otDatasetGetActive(mOTInst, &activeDataset);
        err = MapOpenThreadError(otErr);
    }
    else
    {
        err = WEAVE_ERROR_INCORRECT_STATE;
    }

    Impl()->UnlockThreadStack();

    SuccessOrExit(err);

    netInfo.NetworkType = kNetworkType_Thread;
    netInfo.NetworkId = kThreadNetworkId;
    netInfo.FieldPresent.NetworkId = true;
    if (activeDataset.mComponents.mIsNetworkNamePresent)
    {
        strncpy(netInfo.ThreadNetworkName, (const char *)activeDataset.mNetworkName.m8, sizeof(netInfo.ThreadNetworkName));
    }
    if (activeDataset.mComponents.mIsExtendedPanIdPresent)
    {
        memcpy(netInfo.ThreadExtendedPANId, activeDataset.mExtendedPanId.m8, sizeof(netInfo.ThreadExtendedPANId));
        netInfo.FieldPresent.ThreadExtendedPANId = true;
    }
    if (activeDataset.mComponents.mIsMeshLocalPrefixPresent)
    {
        memcpy(netInfo.ThreadMeshPrefix, activeDataset.mMeshLocalPrefix.m8, sizeof(netInfo.ThreadMeshPrefix));
        netInfo.FieldPresent.ThreadMeshPrefix = true;
    }
    if (includeCredentials)
    {
        if (activeDataset.mComponents.mIsMasterKeyPresent)
        {
            memcpy(netInfo.ThreadNetworkKey, activeDataset.mMasterKey.m8, sizeof(netInfo.ThreadNetworkKey));
            netInfo.FieldPresent.ThreadNetworkKey = true;
        }
        if (activeDataset.mComponents.mIsPSKcPresent)
        {
            memcpy(netInfo.ThreadPSKc, activeDataset.mPSKc.m8, sizeof(netInfo.ThreadPSKc));
            netInfo.FieldPresent.ThreadPSKc = true;
        }
    }
    if (activeDataset.mComponents.mIsPanIdPresent)
    {
        netInfo.ThreadPANId = activeDataset.mPanId;
    }
    if (activeDataset.mComponents.mIsChannelPresent)
    {
        netInfo.ThreadChannel = activeDataset.mChannel;
    }

exit:
    return err;
}

template<class ImplClass>
WEAVE_ERROR GenericThreadStackManagerImpl_OpenThread<ImplClass>::_SetThreadProvision(const DeviceNetworkInfo & netInfo)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;
    otError otErr;
    otOperationalDataset newDataset;

    // Form a Thread operational dataset from the given network parameters.
    memset(&newDataset, 0, sizeof(newDataset));
    newDataset.mComponents.mIsActiveTimestampPresent = true;
    newDataset.mComponents.mIsPendingTimestampPresent = true;
    if (netInfo.ThreadNetworkName[0] != 0)
    {
        strncpy((char *)newDataset.mNetworkName.m8, netInfo.ThreadNetworkName, sizeof(newDataset.mNetworkName.m8));
        newDataset.mComponents.mIsNetworkNamePresent = true;
    }
    if (netInfo.FieldPresent.ThreadExtendedPANId)
    {
        memcpy(newDataset.mExtendedPanId.m8, netInfo.ThreadExtendedPANId, sizeof(newDataset.mExtendedPanId.m8));
        newDataset.mComponents.mIsExtendedPanIdPresent = true;
    }
    if (netInfo.FieldPresent.ThreadMeshPrefix)
    {
        memcpy(newDataset.mMeshLocalPrefix.m8, netInfo.ThreadMeshPrefix, sizeof(newDataset.mMeshLocalPrefix.m8));
        newDataset.mComponents.mIsMeshLocalPrefixPresent = true;
    }
    if (netInfo.FieldPresent.ThreadNetworkKey)
    {
        memcpy(newDataset.mMasterKey.m8, netInfo.ThreadNetworkKey, sizeof(newDataset.mMasterKey.m8));
        newDataset.mComponents.mIsMasterKeyPresent = true;
    }
    if (netInfo.FieldPresent.ThreadPSKc)
    {
        memcpy(newDataset.mPSKc.m8, netInfo.ThreadPSKc, sizeof(newDataset.mPSKc.m8));
        newDataset.mComponents.mIsPSKcPresent = true;
    }
    if (netInfo.ThreadPANId != kThreadPANId_NotSpecified)
    {
        newDataset.mPanId = netInfo.ThreadPANId;
        newDataset.mComponents.mIsPanIdPresent = true;
    }
    if (netInfo.ThreadChannel != kThreadChannel_NotSpecified)
    {
        newDataset.mChannel = netInfo.ThreadChannel;
        newDataset.mComponents.mIsChannelPresent = true;
    }

    // Set the dataset as the active dataset for the node.
    Impl()->LockThreadStack();
    otErr = otDatasetSetActive(mOTInst, &newDataset);
    Impl()->UnlockThreadStack();

    VerifyOrExit(otErr == OT_ERROR_NONE, err = MapOpenThreadError(otErr));

exit:
    return err;
}

template<class ImplClass>
void GenericThreadStackManagerImpl_OpenThread<ImplClass>::_ClearThreadProvision(void)
{
    Impl()->LockThreadStack();
    otThreadSetEnabled(mOTInst, false);
    otInstanceErasePersistentInfo(mOTInst);
    Impl()->UnlockThreadStack();
}

template<class ImplClass>
bool GenericThreadStackManagerImpl_OpenThread<ImplClass>::_HaveMeshConnectivity(void)
{
    bool res;
    otDeviceRole curRole;

    Impl()->LockThreadStack();

    // Get the current Thread role.
    curRole = otThreadGetDeviceRole(mOTInst);

    // If Thread is disabled, or the node is detached, then the node has no mesh connectivity.
    if (curRole == OT_DEVICE_ROLE_DISABLED || curRole == OT_DEVICE_ROLE_DETACHED)
    {
        res = false;
    }

    // If the node is a child, that implies the existence of a parent node which provides connectivity
    // to the mesh.
    else if (curRole == OT_DEVICE_ROLE_CHILD)
    {
        res = true;
    }

    // Otherwise, if the node is acting as a router, scan the Thread neighbor table looking for at least
    // one other node that is also acting as router.
    else
    {
        otNeighborInfoIterator neighborIter = OT_NEIGHBOR_INFO_ITERATOR_INIT;
        otNeighborInfo neighborInfo;

        res = false;

        while (otThreadGetNextNeighborInfo(mOTInst, &neighborIter, &neighborInfo) == OT_ERROR_NONE)
        {
            if (!neighborInfo.mIsChild)
            {
                res = true;
                break;
            }
        }
    }

    Impl()->UnlockThreadStack();

    return res;
}

template<class ImplClass>
WEAVE_ERROR GenericThreadStackManagerImpl_OpenThread<ImplClass>::_GetAndLogThreadStatsCounters(void)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;
    otError otErr;
    nl::Weave::Profiles::DataManagement_Current::event_id_t eventId;
    Schema::Nest::Trait::Network::TelemetryNetworkWpanTrait::NetworkWpanStatsEvent counterEvent = { 0 };
    const otMacCounters *macCounters;
    const otIpCounters *ipCounters;
    otOperationalDataset activeDataset;
    otDeviceRole role;

    Impl()->LockThreadStack();

    // Get Mac Counters
    macCounters = otLinkGetCounters(mOTInst);

    // Rx Counters
    counterEvent.phyRx                = macCounters->mRxTotal;
    counterEvent.macUnicastRx         = macCounters->mRxUnicast;
    counterEvent.macBroadcastRx       = macCounters->mRxBroadcast;
    counterEvent.macRxData            = macCounters->mRxData;
    counterEvent.macRxDataPoll        = macCounters->mRxDataPoll;
    counterEvent.macRxBeacon          = macCounters->mRxBeacon;
    counterEvent.macRxBeaconReq       = macCounters->mRxBeaconRequest;
    counterEvent.macRxOtherPkt        = macCounters->mRxOther;
    counterEvent.macRxFilterWhitelist = macCounters->mRxAddressFiltered;
    counterEvent.macRxFilterDestAddr  = macCounters->mRxDestAddrFiltered;

    // Tx Counters
    counterEvent.phyTx          = macCounters->mTxTotal;
    counterEvent.macUnicastTx   = macCounters->mTxUnicast;
    counterEvent.macBroadcastTx = macCounters->mTxBroadcast;
    counterEvent.macTxAckReq    = macCounters->mTxAckRequested;
    counterEvent.macTxNoAckReq  = macCounters->mTxNoAckRequested;
    counterEvent.macTxAcked     = macCounters->mTxAcked;
    counterEvent.macTxData      = macCounters->mTxData;
    counterEvent.macTxDataPoll  = macCounters->mTxDataPoll;
    counterEvent.macTxBeacon    = macCounters->mTxBeacon;
    counterEvent.macTxBeaconReq = macCounters->mTxBeaconRequest;
    counterEvent.macTxOtherPkt  = macCounters->mTxOther;
    counterEvent.macTxRetry     = macCounters->mTxRetry;

    // Tx Error Counters
    counterEvent.macTxFailCca = macCounters->mTxErrCca;

    // Rx Error Counters
    counterEvent.macRxFailDecrypt         = macCounters->mRxErrSec;
    counterEvent.macRxFailNoFrame         = macCounters->mRxErrNoFrame;
    counterEvent.macRxFailUnknownNeighbor = macCounters->mRxErrUnknownNeighbor;
    counterEvent.macRxFailInvalidSrcAddr  = macCounters->mRxErrInvalidSrcAddr;
    counterEvent.macRxFailFcs             = macCounters->mRxErrFcs;
    counterEvent.macRxFailOther           = macCounters->mRxErrOther;

    // Get Ip Counters
    ipCounters = otThreadGetIp6Counters(mOTInst);

    // Ip Counters
    counterEvent.ipTxSuccess = ipCounters->mTxSuccess;
    counterEvent.ipRxSuccess = ipCounters->mRxSuccess;
    counterEvent.ipTxFailure = ipCounters->mTxFailure;
    counterEvent.ipRxFailure = ipCounters->mRxFailure;

    if (otDatasetIsCommissioned(mOTInst))
    {
        otErr = otDatasetGetActive(mOTInst, &activeDataset);
        VerifyOrExit(otErr == OT_ERROR_NONE, err = MapOpenThreadError(otErr));

        if (activeDataset.mComponents.mIsChannelPresent)
        {
            counterEvent.channel = activeDataset.mChannel;
        }
    }

    role = otThreadGetDeviceRole(mOTInst);

    switch (role)
    {
    case OT_DEVICE_ROLE_LEADER:
        counterEvent.nodeType |= TelemetryNetworkWpanTrait::NODE_TYPE_LEADER;
        // Intentional fall-through: if it's a leader, then it's also a router
    case OT_DEVICE_ROLE_ROUTER:
        counterEvent.nodeType |= TelemetryNetworkWpanTrait::NODE_TYPE_ROUTER;
        break;
    case OT_DEVICE_ROLE_CHILD:
    case OT_DEVICE_ROLE_DISABLED:
    case OT_DEVICE_ROLE_DETACHED:
    default:
        counterEvent.nodeType = 0;
        break;
    }

    counterEvent.threadType = TelemetryNetworkWpanTrait::THREAD_TYPE_OPENTHREAD;

    WeaveLogProgress(DeviceLayer,
                     "Rx Counters:\n"
                     "PHY Rx Total:                 %d\n"
                     "MAC Rx Unicast:               %d\n"
                     "MAC Rx Broadcast:             %d\n"
                     "MAC Rx Data:                  %d\n"
                     "MAC Rx Data Polls:            %d\n"
                     "MAC Rx Beacons:               %d\n"
                     "MAC Rx Beacon Reqs:           %d\n"
                     "MAC Rx Other:                 %d\n"
                     "MAC Rx Filtered Whitelist:    %d\n"
                     "MAC Rx Filtered DestAddr:     %d\n",
                     counterEvent.phyRx, counterEvent.macUnicastRx, counterEvent.macBroadcastRx, counterEvent.macRxData,
                     counterEvent.macRxDataPoll, counterEvent.macRxBeacon, counterEvent.macRxBeaconReq, counterEvent.macRxOtherPkt,
                     counterEvent.macRxFilterWhitelist, counterEvent.macRxFilterDestAddr);

    WeaveLogProgress(DeviceLayer,
                     "Tx Counters:\n"
                     "PHY Tx Total:                 %d\n"
                     "MAC Tx Unicast:               %d\n"
                     "MAC Tx Broadcast:             %d\n"
                     "MAC Tx Data:                  %d\n"
                     "MAC Tx Data Polls:            %d\n"
                     "MAC Tx Beacons:               %d\n"
                     "MAC Tx Beacon Reqs:           %d\n"
                     "MAC Tx Other:                 %d\n"
                     "MAC Tx Retry:                 %d\n"
                     "MAC Tx CCA Fail:              %d\n",
                     counterEvent.phyTx, counterEvent.macUnicastTx, counterEvent.macBroadcastTx, counterEvent.macTxData,
                     counterEvent.macTxDataPoll, counterEvent.macTxBeacon, counterEvent.macTxBeaconReq, counterEvent.macTxOtherPkt,
                     counterEvent.macTxRetry, counterEvent.macTxFailCca);

    WeaveLogProgress(DeviceLayer,
                     "Failure Counters:\n"
                     "MAC Rx Decrypt Fail:          %d\n"
                     "MAC Rx No Frame Fail:         %d\n"
                     "MAC Rx Unknown Neighbor Fail: %d\n"
                     "MAC Rx Invalid Src Addr Fail: %d\n"
                     "MAC Rx FCS Fail:              %d\n"
                     "MAC Rx Other Fail:            %d\n",
                     counterEvent.macRxFailDecrypt, counterEvent.macRxFailNoFrame, counterEvent.macRxFailUnknownNeighbor,
                     counterEvent.macRxFailInvalidSrcAddr, counterEvent.macRxFailFcs, counterEvent.macRxFailOther);

    eventId = nl::LogEvent(&counterEvent);
    WeaveLogProgress(DeviceLayer, "OpenThread Telemetry Stats Event Id: %u\n", eventId);

    Impl()->UnlockThreadStack();

exit:
    return err;
}

template<class ImplClass>
WEAVE_ERROR GenericThreadStackManagerImpl_OpenThread<ImplClass>::_GetAndLogThreadTopologyMinimal(void)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;
    otError otErr;
    nl::Weave::Profiles::DataManagement_Current::event_id_t eventId;
    Schema::Nest::Trait::Network::TelemetryNetworkWpanTrait::NetworkWpanTopoMinimalEvent topologyEvent = { 0 };
    const otExtAddress *extAddress;

    Impl()->LockThreadStack();

    topologyEvent.rloc16 = otThreadGetRloc16(mOTInst);

    // Router ID is the top 6 bits of the RLOC
    topologyEvent.routerId = (topologyEvent.rloc16 >> 10) & 0x3f;

    topologyEvent.leaderRouterId = otThreadGetLeaderRouterId(mOTInst);

    otErr = otThreadGetParentAverageRssi(mOTInst, &topologyEvent.parentAverageRssi);
    VerifyOrExit(otErr == OT_ERROR_NONE, err = MapOpenThreadError(otErr));

    otErr = otThreadGetParentLastRssi(mOTInst, &topologyEvent.parentLastRssi);
    VerifyOrExit(otErr == OT_ERROR_NONE, err = MapOpenThreadError(otErr));

    topologyEvent.partitionId = otThreadGetPartitionId(mOTInst);

    extAddress = otLinkGetExtendedAddress(mOTInst);

    topologyEvent.extAddress.mBuf = (uint8_t *)extAddress;
    topologyEvent.extAddress.mLen = sizeof(otExtAddress);

    topologyEvent.instantRssi = otPlatRadioGetRssi(mOTInst);

    WeaveLogProgress(DeviceLayer,
                     "Thread Topology:\n"
                     "RLOC16:           %04X\n"
                     "Router ID:        %u\n"
                     "Leader Router ID: %u\n"
                     "Parent Avg RSSI:  %d\n"
                     "Parent Last RSSI: %d\n"
                     "Partition ID:     %d\n"
                     "Extended Address: %02X%02X:%02X%02X:%02X%02X:%02X%02X\n"
                     "Instant RSSI:     %d\n",
                     topologyEvent.rloc16, topologyEvent.routerId, topologyEvent.leaderRouterId, topologyEvent.parentAverageRssi,
                     topologyEvent.parentLastRssi, topologyEvent.partitionId, topologyEvent.extAddress.mBuf[0], topologyEvent.extAddress.mBuf[1],
                     topologyEvent.extAddress.mBuf[2], topologyEvent.extAddress.mBuf[3], topologyEvent.extAddress.mBuf[4],
                     topologyEvent.extAddress.mBuf[5], topologyEvent.extAddress.mBuf[6], topologyEvent.extAddress.mBuf[7], topologyEvent.instantRssi);

    eventId = nl::LogEvent(&topologyEvent);
    WeaveLogProgress(DeviceLayer, "OpenThread Telemetry Stats Event Id: %u\n", eventId);

    Impl()->UnlockThreadStack();

exit:
    if (err != WEAVE_NO_ERROR)
    {
        WeaveLogError(DeviceLayer, "GetAndLogThreadTopologyMinimul failed: %s", nl::ErrorStr(err));
    }

    return err;
}

#define TELEM_NEIGHBOR_TABLE_SIZE (64)
#define TELEM_PRINT_BUFFER_SIZE (64)

template<class ImplClass>
WEAVE_ERROR GenericThreadStackManagerImpl_OpenThread<ImplClass>::_GetAndLogThreadTopologyFull(void)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;
    otError otErr;
    nl::Weave::Profiles::DataManagement_Current::EventOptions neighborTopoOpts(true);
    nl::Weave::Profiles::DataManagement_Current::event_id_t eventId;
    Schema::Nest::Trait::Network::TelemetryNetworkWpanTrait::NetworkWpanTopoFullEvent fullTopoEvent = { 0 };
    Schema::Nest::Trait::Network::TelemetryNetworkWpanTrait::TopoEntryEvent neighborTopoEvent = { 0 };
    otIp6Address * leaderAddr = NULL;
    uint8_t * networkData = NULL;
    uint8_t * stableNetworkData = NULL;
    uint8_t networkDataLen = 0;
    uint8_t stableNetworkDataLen = 0;
    const otExtAddress * extAddress;
    otNeighborInfo neighborInfo[TELEM_NEIGHBOR_TABLE_SIZE];
    otNeighborInfoIterator iter;
    otNeighborInfoIterator iterCopy;
    char printBuf[TELEM_PRINT_BUFFER_SIZE];

    Impl()->LockThreadStack();

    fullTopoEvent.rloc16 = otThreadGetRloc16(mOTInst);

    // Router ID is the top 6 bits of the RLOC
    fullTopoEvent.routerId = (fullTopoEvent.rloc16 >> 10) & 0x3f;

    fullTopoEvent.leaderRouterId = otThreadGetLeaderRouterId(mOTInst);

    otErr = otThreadGetLeaderRloc(mOTInst, leaderAddr);
    VerifyOrExit(otErr == OT_ERROR_NONE, err = MapOpenThreadError(otErr));

    fullTopoEvent.leaderAddress.mBuf = leaderAddr->mFields.m8;
    fullTopoEvent.leaderAddress.mLen = OT_IP6_ADDRESS_SIZE;

    fullTopoEvent.leaderWeight = otThreadGetLeaderWeight(mOTInst);

    fullTopoEvent.leaderLocalWeight = otThreadGetLocalLeaderWeight(mOTInst);

    otErr = otNetDataGet(mOTInst, false, networkData, &networkDataLen);
    VerifyOrExit(otErr == OT_ERROR_NONE, err = MapOpenThreadError(otErr));

    fullTopoEvent.networkData.mBuf = networkData;
    fullTopoEvent.networkData.mLen = networkDataLen;

    fullTopoEvent.networkDataVersion = otNetDataGetVersion(mOTInst);

    otErr = otNetDataGet(mOTInst, true, stableNetworkData, &stableNetworkDataLen);
    VerifyOrExit(otErr == OT_ERROR_NONE, err = MapOpenThreadError(otErr));

    fullTopoEvent.stableNetworkData.mBuf = stableNetworkData;
    fullTopoEvent.stableNetworkData.mLen = stableNetworkDataLen;

    fullTopoEvent.stableNetworkDataVersion = otNetDataGetStableVersion(mOTInst);

    // Deprecated property
    fullTopoEvent.preferredRouterId = -1;

    extAddress = otLinkGetExtendedAddress(mOTInst);

    fullTopoEvent.extAddress.mBuf = (uint8_t *)extAddress;
    fullTopoEvent.extAddress.mLen = sizeof(otExtAddress);

    fullTopoEvent.partitionId = otThreadGetPartitionId(mOTInst);

    fullTopoEvent.instantRssi = otPlatRadioGetRssi(mOTInst);

    iter = OT_NEIGHBOR_INFO_ITERATOR_INIT;
    iterCopy = OT_NEIGHBOR_INFO_ITERATOR_INIT;
    fullTopoEvent.neighborTableSize = 0;
    fullTopoEvent.childTableSize = 0;

    while (otThreadGetNextNeighborInfo(mOTInst, &iter, &neighborInfo[iter]) == OT_ERROR_NONE)
    {
        fullTopoEvent.neighborTableSize++;
        if (neighborInfo[iterCopy].mIsChild)
        {
            fullTopoEvent.childTableSize++;
        }
        iterCopy = iter;
    }

    WeaveLogProgress(DeviceLayer,
                     "Thread Topology:\n"
                     "RLOC16:                %04X\n"
                     "Router ID:             %u\n"
                     "Leader Router ID:      %u\n"
                     "Leader Address:        %02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X:%02X%02X\n"
                     "Leader Weight:         %d\n"
                     "Local Leader Weight:   %d\n"
                     "Network Data Len:      %d\n"
                     "Network Data Version:  %d\n"
                     "Extended Address:      %02X%02X:%02X%02X:%02X%02X:%02X%02X\n"
                     "Partition ID:          %X\n"
                     "Instant RSSI:          %d\n"
                     "Neighbor Table Length: %d\n"
                     "Child Table Length:    %d\n",
                     fullTopoEvent.rloc16, fullTopoEvent.routerId, fullTopoEvent.leaderRouterId,
                     fullTopoEvent.leaderAddress.mBuf[0], fullTopoEvent.leaderAddress.mBuf[1], fullTopoEvent.leaderAddress.mBuf[2], fullTopoEvent.leaderAddress.mBuf[3],
                     fullTopoEvent.leaderAddress.mBuf[4], fullTopoEvent.leaderAddress.mBuf[5], fullTopoEvent.leaderAddress.mBuf[6], fullTopoEvent.leaderAddress.mBuf[7],
                     fullTopoEvent.leaderAddress.mBuf[8], fullTopoEvent.leaderAddress.mBuf[9], fullTopoEvent.leaderAddress.mBuf[10], fullTopoEvent.leaderAddress.mBuf[11],
                     fullTopoEvent.leaderAddress.mBuf[12], fullTopoEvent.leaderAddress.mBuf[13], fullTopoEvent.leaderAddress.mBuf[14], fullTopoEvent.leaderAddress.mBuf[15],
                     fullTopoEvent.leaderWeight, fullTopoEvent.leaderLocalWeight, fullTopoEvent.networkData.mLen, fullTopoEvent.networkDataVersion,
                     fullTopoEvent.extAddress.mBuf[0], fullTopoEvent.extAddress.mBuf[1], fullTopoEvent.extAddress.mBuf[2], fullTopoEvent.extAddress.mBuf[3],
                     fullTopoEvent.extAddress.mBuf[4], fullTopoEvent.extAddress.mBuf[5], fullTopoEvent.extAddress.mBuf[6], fullTopoEvent.extAddress.mBuf[7],
                     fullTopoEvent.partitionId, fullTopoEvent.instantRssi, fullTopoEvent.neighborTableSize, fullTopoEvent.childTableSize);

    eventId = nl::LogEvent(&fullTopoEvent);
    WeaveLogProgress(DeviceLayer, "OpenThread Full Topology Event Id: %u\n", eventId);

    // Populate the neighbor event options.
    // This way the neighbor topology entries are linked to the actual topology full event.
    neighborTopoOpts.relatedEventID = eventId;
    neighborTopoOpts.relatedImportance = TelemetryNetworkWpanTrait::NetworkWpanTopoFullEvent::Schema.mImportance;

    // Handle each neighbor event seperatly.
    for (uint32_t i = 0; i < fullTopoEvent.neighborTableSize; i++)
    {
        otNeighborInfo * neighbor           = &neighborInfo[i];

        neighborTopoEvent.extAddress.mBuf   = neighbor->mExtAddress.m8;
        neighborTopoEvent.extAddress.mLen   = sizeof(uint64_t);

        neighborTopoEvent.rloc16            = neighbor->mRloc16;
        neighborTopoEvent.linkQualityIn     = neighbor->mLinkQualityIn;
        neighborTopoEvent.averageRssi       = neighbor->mAverageRssi;
        neighborTopoEvent.age               = neighbor->mAge;
        neighborTopoEvent.rxOnWhenIdle      = neighbor->mRxOnWhenIdle;
        // TODO: not supported in old version of OpenThread used by Nordic SDK.
        // neighborTopoEvent.fullFunction      = neighbor->mFullThreadDevice;
        neighborTopoEvent.fullFunction      = false;
        neighborTopoEvent.secureDataRequest = neighbor->mSecureDataRequest;
        neighborTopoEvent.fullNetworkData   = neighbor->mFullNetworkData;
        neighborTopoEvent.lastRssi          = neighbor->mLastRssi;
        neighborTopoEvent.linkFrameCounter  = neighbor->mLinkFrameCounter;
        neighborTopoEvent.mleFrameCounter   = neighbor->mMleFrameCounter;
        neighborTopoEvent.isChild           = neighbor->mIsChild;

        if (neighborTopoEvent.isChild)
        {
            otChildInfo * child =  NULL;
            otErr = otThreadGetChildInfoById(mOTInst, neighborTopoEvent.rloc16, child);
            VerifyOrExit(otErr == OT_ERROR_NONE, err = MapOpenThreadError(otErr));

            neighborTopoEvent.timeout            = child->mTimeout;
            neighborTopoEvent.networkDataVersion = child->mNetworkDataVersion;

            neighborTopoEvent.SetTimeoutPresent();
            neighborTopoEvent.SetNetworkDataVersionPresent();

            snprintf(printBuf, TELEM_PRINT_BUFFER_SIZE, ", Timeout: %10lu NetworkDataVersion: %3d",
                               neighborTopoEvent.timeout, neighborTopoEvent.networkDataVersion);
        }
        else
        {
            neighborTopoEvent.SetTimeoutNull();
            neighborTopoEvent.SetNetworkDataVersionNull();

            printBuf[0] = 0;
        }

        WeaveLogProgress(DeviceLayer,
                         "TopoEntry[%u]:     %02X%02X:%02X%02X:%02X%02X:%02X%02X\n"
                         "RLOC:              %04X\n"
                         "Age:               %3d\n"
                         "LQI:               %1d\n"
                         "AvgRSSI:           %3d\n"
                         "LastRSSI:          %3d\n"
                         "LinkFrameCounter:  %10d\n"
                         "MleFrameCounter:   %10d\n"
                         "RxOnWhenIdle:      %c\n"
                         "SecureDataRequest: %c\n"
                         "FullFunction:      %c\n"
                         "FullNetworkData:   %c\n"
                         "IsChild:           %c%s\n",
                         i, neighborTopoEvent.extAddress.mBuf[0], neighborTopoEvent.extAddress.mBuf[1], neighborTopoEvent.extAddress.mBuf[2],
                         neighborTopoEvent.extAddress.mBuf[3], neighborTopoEvent.extAddress.mBuf[4], neighborTopoEvent.extAddress.mBuf[5],
                         neighborTopoEvent.extAddress.mBuf[6], neighborTopoEvent.extAddress.mBuf[7], neighborTopoEvent.rloc16, neighborTopoEvent.age,
                         neighborTopoEvent.linkQualityIn, neighborTopoEvent.averageRssi, neighborTopoEvent.lastRssi, neighborTopoEvent.linkFrameCounter,
                         neighborTopoEvent.mleFrameCounter, neighborTopoEvent.rxOnWhenIdle ? 'Y' : 'n', neighborTopoEvent.secureDataRequest ? 'Y' : 'n',
                         neighborTopoEvent.fullFunction ? 'Y' : 'n', neighborTopoEvent.fullNetworkData ? 'Y' : 'n',
                         neighborTopoEvent.isChild ? 'Y' : 'n', printBuf);

        eventId = nl::LogEvent(&neighborTopoEvent, neighborTopoOpts);
        WeaveLogProgress(DeviceLayer, "OpenThread Neighbor TopoEntry[%u] Event Id: %ld\n", i, eventId);
    }

    Impl()->UnlockThreadStack();

exit:
    if (err != WEAVE_NO_ERROR)
    {
        WeaveLogError(DeviceLayer, "GetAndLogThreadTopologyFull failed: %s", nl::ErrorStr(err));
    }
    return err;
}

template<class ImplClass>
WEAVE_ERROR GenericThreadStackManagerImpl_OpenThread<ImplClass>::DoInit(otInstance * otInst)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;
    otError otErr;

    // Arrange for OpenThread errors to be translated to text.
    RegisterOpenThreadErrorFormatter();

    mOTInst = NULL;

    // If an OpenThread instance hasn't been supplied, call otInstanceInitSingle() to
    // create or acquire a singleton instance of OpenThread.
    if (otInst == NULL)
    {
        otInst = otInstanceInitSingle();
        VerifyOrExit(otInst != NULL, err = MapOpenThreadError(OT_ERROR_FAILED));
    }

    mOTInst = otInst;

    // Arrange for OpenThread to call the OnOpenThreadStateChange method whenever a
    // state change occurs.  Note that we reference the OnOpenThreadStateChange method
    // on the concrete implementation class so that that class can override the default
    // method implementation if it chooses to.
    otErr = otSetStateChangedCallback(otInst, ImplClass::OnOpenThreadStateChange, NULL);
    VerifyOrExit(otErr == OT_ERROR_NONE, err = MapOpenThreadError(otErr));

    // TODO: generalize this
    {
        otLinkModeConfig linkMode;

        memset(&linkMode, 0, sizeof(linkMode));
        linkMode.mRxOnWhenIdle       = true;
        linkMode.mSecureDataRequests = true;
        linkMode.mDeviceType         = true;
        linkMode.mNetworkData        = true;

        otErr = otThreadSetLinkMode(otInst, linkMode);
        VerifyOrExit(otErr == OT_ERROR_NONE, err = MapOpenThreadError(otErr));
    }

    // TODO: not supported in old version of OpenThread used by Nordic SDK.
    // otIp6SetSlaacEnabled(otInst, false);

    otErr = otIp6SetEnabled(otInst, true);
    VerifyOrExit(otErr == OT_ERROR_NONE, err = MapOpenThreadError(otErr));

    if (otThreadGetDeviceRole(mOTInst) == OT_DEVICE_ROLE_DISABLED && otDatasetIsCommissioned(otInst))
    {
        otErr = otThreadSetEnabled(otInst, true);
        VerifyOrExit(otErr == OT_ERROR_NONE, err = MapOpenThreadError(otErr));
    }

exit:
    return err;
}

template<class ImplClass>
bool GenericThreadStackManagerImpl_OpenThread<ImplClass>::IsThreadAttachedNoLock(void)
{
    otDeviceRole curRole = otThreadGetDeviceRole(mOTInst);
    return (curRole != OT_DEVICE_ROLE_DISABLED && curRole != OT_DEVICE_ROLE_DETACHED);
}


} // namespace Internal
} // namespace DeviceLayer
} // namespace Weave
} // namespace nl


#endif // GENERIC_THREAD_STACK_MANAGER_IMPL_OPENTHREAD_IPP
