/*
 *    Copyright (c) 2016-2017, The OpenThread Authors.
 *    All rights reserved.
 *
 *    Redistribution and use in source and binary forms, with or without
 *    modification, are permitted provided that the following conditions are met:
 *    1. Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *    2. Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *    3. Neither the name of the copyright holder nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 *    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 *    ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 *    WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 *    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
 *    DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 *    (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 *    LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 *    ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 *    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 *    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/**
 * @file
 *   This file implements full thread device specified Spinel interface to the OpenThread stack.
 */

#include "ncp_base.hpp"
#include <openthread/config.h>

#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
#include <openthread/backbone_router_ftd.h>
#endif
#if OPENTHREAD_CONFIG_CHANNEL_MANAGER_ENABLE
#include <openthread/channel_manager.h>
#endif
#include <openthread/child_supervision.h>
#include <openthread/dataset.h>
#include <openthread/dataset_ftd.h>
#include <openthread/diag.h>
#include <openthread/icmp6.h>
#include <openthread/ncp.h>
#include <openthread/thread_ftd.h>
#include <openthread/platform/misc.h>

#include "common/code_utils.hpp"
#include "common/debug.hpp"
#include "common/instance.hpp"
#if OPENTHREAD_CONFIG_COMMISSIONER_ENABLE
#include "meshcop/commissioner.hpp"
#endif

#if OPENTHREAD_FTD
namespace ot {
namespace Ncp {

otError NcpBase::EncodeChildInfo(const otChildInfo &aChildInfo)
{
    otError error = OT_ERROR_NONE;
    uint8_t modeFlags;

    modeFlags =
        LinkFlagsToFlagByte(aChildInfo.mRxOnWhenIdle, aChildInfo.mFullThreadDevice, aChildInfo.mFullNetworkData);

    SuccessOrExit(error = mEncoder.WriteEui64(aChildInfo.mExtAddress));
    SuccessOrExit(error = mEncoder.WriteUint16(aChildInfo.mRloc16));
    SuccessOrExit(error = mEncoder.WriteUint32(aChildInfo.mTimeout));
    SuccessOrExit(error = mEncoder.WriteUint32(aChildInfo.mAge));
    SuccessOrExit(error = mEncoder.WriteUint8(aChildInfo.mNetworkDataVersion));
    SuccessOrExit(error = mEncoder.WriteUint8(aChildInfo.mLinkQualityIn));
    SuccessOrExit(error = mEncoder.WriteInt8(aChildInfo.mAverageRssi));
    SuccessOrExit(error = mEncoder.WriteUint8(modeFlags));
    SuccessOrExit(error = mEncoder.WriteInt8(aChildInfo.mLastRssi));

exit:
    return error;
}

// ----------------------------------------------------------------------------
// MARK: Property/Status Changed
// ----------------------------------------------------------------------------

#if OPENTHREAD_CONFIG_MLE_PARENT_RESPONSE_CALLBACK_API_ENABLE
void NcpBase::HandleParentResponseInfo(otThreadParentResponseInfo *aInfo, void *aContext)
{
    VerifyOrExit(aInfo && aContext);

    static_cast<NcpBase *>(aContext)->HandleParentResponseInfo(*aInfo);

exit:
    return;
}

void NcpBase::HandleParentResponseInfo(const otThreadParentResponseInfo &aInfo)
{
    VerifyOrExit(!mChangedPropsSet.IsPropertyFiltered(SPINEL_PROP_PARENT_RESPONSE_INFO));

    SuccessOrExit(mEncoder.BeginFrame(SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0, SPINEL_CMD_PROP_VALUE_IS,
                                      SPINEL_PROP_PARENT_RESPONSE_INFO));

    SuccessOrExit(mEncoder.WriteEui64(aInfo.mExtAddr));
    SuccessOrExit(mEncoder.WriteUint16(aInfo.mRloc16));
    SuccessOrExit(mEncoder.WriteInt8(aInfo.mRssi));
    SuccessOrExit(mEncoder.WriteInt8(aInfo.mPriority));
    SuccessOrExit(mEncoder.WriteUint8(aInfo.mLinkQuality3));
    SuccessOrExit(mEncoder.WriteUint8(aInfo.mLinkQuality2));
    SuccessOrExit(mEncoder.WriteUint8(aInfo.mLinkQuality1));
    SuccessOrExit(mEncoder.WriteBool(aInfo.mIsAttached));

    SuccessOrExit(mEncoder.EndFrame());

exit:
    return;
}
#endif

void NcpBase::HandleNeighborTableChanged(otNeighborTableEvent aEvent, const otNeighborTableEntryInfo *aEntry)
{
    GetNcpInstance()->HandleNeighborTableChanged(aEvent, *aEntry);
}

void NcpBase::HandleNeighborTableChanged(otNeighborTableEvent aEvent, const otNeighborTableEntryInfo &aEntry)
{
    otError           error   = OT_ERROR_NONE;
    unsigned int      command = SPINEL_CMD_PROP_VALUE_REMOVED;
    spinel_prop_key_t property;

    switch (aEvent)
    {
    case OT_NEIGHBOR_TABLE_EVENT_CHILD_ADDED:
        command = SPINEL_CMD_PROP_VALUE_INSERTED;

        OT_FALL_THROUGH;

    case OT_NEIGHBOR_TABLE_EVENT_CHILD_REMOVED:
        property = SPINEL_PROP_THREAD_CHILD_TABLE;
        VerifyOrExit(!aEntry.mInfo.mChild.mIsStateRestoring);
        break;

    case OT_NEIGHBOR_TABLE_EVENT_ROUTER_ADDED:
        command = SPINEL_CMD_PROP_VALUE_INSERTED;

        OT_FALL_THROUGH;

    case OT_NEIGHBOR_TABLE_EVENT_ROUTER_REMOVED:
        property = SPINEL_PROP_THREAD_NEIGHBOR_TABLE;
        break;

    default:
        ExitNow();
    }

    VerifyOrExit(!mChangedPropsSet.IsPropertyFiltered(property));

    SuccessOrExit(error = mEncoder.BeginFrame(SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0, command, property));

    if (property == SPINEL_PROP_THREAD_CHILD_TABLE)
    {
        SuccessOrExit(error = EncodeChildInfo(aEntry.mInfo.mChild));
    }
    else
    {
        SuccessOrExit(error = EncodeNeighborInfo(aEntry.mInfo.mRouter));
    }

    SuccessOrExit(error = mEncoder.EndFrame());

exit:

    // If the frame can not be added (out of NCP buffer space), we remember
    // to send an async `LAST_STATUS(NOMEM)` when buffer space becomes
    // available. Also `mShouldEmitChildTableUpdate` flag is set to `true` so
    // that the entire child table is later emitted as `VALUE_IS` spinel frame
    // update from `ProcessThreadChangedFlags()`.

    if (error != OT_ERROR_NONE)
    {
        if (property == SPINEL_PROP_THREAD_CHILD_TABLE)
        {
            mShouldEmitChildTableUpdate = true;
        }

        mChangedPropsSet.AddLastStatus(SPINEL_STATUS_NOMEM);
        mUpdateChangedPropsTask.Post();
    }
}

// ----------------------------------------------------------------------------
// MARK: Individual Property Handlers
// ----------------------------------------------------------------------------

template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_LOCAL_LEADER_WEIGHT>(void)
{
    return mEncoder.WriteUint8(otThreadGetLocalLeaderWeight(mInstance));
}

template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_LEADER_WEIGHT>(void)
{
    return mEncoder.WriteUint8(otThreadGetLeaderWeight(mInstance));
}

template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_CHILD_TABLE>(void)
{
    otError     error = OT_ERROR_NONE;
    otChildInfo childInfo;
    uint16_t    maxChildren;

    maxChildren = otThreadGetMaxAllowedChildren(mInstance);

    for (uint16_t index = 0; index < maxChildren; index++)
    {
        if ((otThreadGetChildInfoByIndex(mInstance, index, &childInfo) != OT_ERROR_NONE) || childInfo.mIsStateRestoring)
        {
            continue;
        }

        SuccessOrExit(error = mEncoder.OpenStruct());
        SuccessOrExit(error = EncodeChildInfo(childInfo));
        SuccessOrExit(error = mEncoder.CloseStruct());
    }

exit:
    return error;
}

template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_ROUTER_TABLE>(void)
{
    otError      error = OT_ERROR_NONE;
    otRouterInfo routerInfo;
    uint8_t      maxRouterId;

    maxRouterId = otThreadGetMaxRouterId(mInstance);

    for (uint8_t routerId = 0; routerId <= maxRouterId; routerId++)
    {
        if ((otThreadGetRouterInfo(mInstance, routerId, &routerInfo) != OT_ERROR_NONE) || !routerInfo.mAllocated)
        {
            continue;
        }

        SuccessOrExit(error = mEncoder.OpenStruct());

        SuccessOrExit(error = mEncoder.WriteEui64(routerInfo.mExtAddress));
        SuccessOrExit(error = mEncoder.WriteUint16(routerInfo.mRloc16));
        SuccessOrExit(error = mEncoder.WriteUint8(routerInfo.mRouterId));
        SuccessOrExit(error = mEncoder.WriteUint8(routerInfo.mNextHop));
        SuccessOrExit(error = mEncoder.WriteUint8(routerInfo.mPathCost));
        SuccessOrExit(error = mEncoder.WriteUint8(routerInfo.mLinkQualityIn));
        SuccessOrExit(error = mEncoder.WriteUint8(routerInfo.mLinkQualityOut));
        SuccessOrExit(error = mEncoder.WriteUint8(routerInfo.mAge));
        SuccessOrExit(error = mEncoder.WriteBool(routerInfo.mLinkEstablished));

        SuccessOrExit(error = mEncoder.CloseStruct());
    }

exit:
    return error;
}

template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_CHILD_TABLE_ADDRESSES>(void)
{
    otError                   error = OT_ERROR_NONE;
    otChildInfo               childInfo;
    uint16_t                  maxChildren;
    otIp6Address              ip6Address;
    otChildIp6AddressIterator iterator = OT_CHILD_IP6_ADDRESS_ITERATOR_INIT;

    maxChildren = otThreadGetMaxAllowedChildren(mInstance);

    for (uint16_t childIndex = 0; childIndex < maxChildren; childIndex++)
    {
        if ((otThreadGetChildInfoByIndex(mInstance, childIndex, &childInfo) != OT_ERROR_NONE) ||
            childInfo.mIsStateRestoring)
        {
            continue;
        }

        SuccessOrExit(error = mEncoder.OpenStruct());

        SuccessOrExit(error = mEncoder.WriteEui64(childInfo.mExtAddress));
        SuccessOrExit(error = mEncoder.WriteUint16(childInfo.mRloc16));

        iterator = OT_CHILD_IP6_ADDRESS_ITERATOR_INIT;

        while (otThreadGetChildNextIp6Address(mInstance, childIndex, &iterator, &ip6Address) == OT_ERROR_NONE)
        {
            SuccessOrExit(error = mEncoder.WriteIp6Address(ip6Address));
        }

        SuccessOrExit(error = mEncoder.CloseStruct());
    }

exit:
    return error;
}

template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_ROUTER_ROLE_ENABLED>(void)
{
    return mEncoder.WriteBool(otThreadIsRouterEligible(mInstance));
}

template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_THREAD_ROUTER_ROLE_ENABLED>(void)
{
    bool    eligible;
    otError error = OT_ERROR_NONE;

    SuccessOrExit(error = mDecoder.ReadBool(eligible));

    error = otThreadSetRouterEligible(mInstance, eligible);

exit:
    return error;
}

template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_MAC_MAX_RETRY_NUMBER_INDIRECT>(void)
{
    return mEncoder.WriteUint8(otLinkGetMaxFrameRetriesIndirect(mInstance));
}

template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_MAC_MAX_RETRY_NUMBER_INDIRECT>(void)
{
    uint8_t maxFrameRetriesIndirect;
    otError error = OT_ERROR_NONE;

    SuccessOrExit(error = mDecoder.ReadUint8(maxFrameRetriesIndirect));
    otLinkSetMaxFrameRetriesIndirect(mInstance, maxFrameRetriesIndirect);

exit:
    return error;
}

#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_DOMAIN_NAME>(void)
{
    return mEncoder.WriteUtf8(otThreadGetDomainName(mInstance));
}

template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_THREAD_DOMAIN_NAME>(void)
{
    otError     error = OT_ERROR_NONE;
    const char *domainName;

    SuccessOrExit(error = mDecoder.ReadUtf8(domainName));

    error = otThreadSetDomainName(mInstance, domainName);

exit:
    return error;
}
#endif

#if OPENTHREAD_CONFIG_DUA_ENABLE
template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_DUA_ID>(void)
{
    const otIp6InterfaceIdentifier *iid   = otThreadGetFixedDuaInterfaceIdentifier(mInstance);
    otError                         error = OT_ERROR_NONE;

    if (iid == nullptr)
    {
        // send empty response
    }
    else
    {
        for (uint8_t i : iid->mFields.m8)
        {
            SuccessOrExit(error = mEncoder.WriteUint8(i));
        }
    }

exit:
    return error;
}

template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_THREAD_DUA_ID>(void)
{
    otError error = OT_ERROR_NONE;

    if (mDecoder.GetRemainingLength() == 0)
    {
        SuccessOrExit(error = otThreadSetFixedDuaInterfaceIdentifier(mInstance, nullptr));
    }
    else
    {
        otIp6InterfaceIdentifier iid;

        for (uint8_t &i : iid.mFields.m8)
        {
            SuccessOrExit(error = mDecoder.ReadUint8(i));
        }

        SuccessOrExit(error = otThreadSetFixedDuaInterfaceIdentifier(mInstance, &iid));
    }

exit:
    return error;
}
#endif // OPENTHREAD_CONFIG_DUA_ENABLE

#if OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE
template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_BACKBONE_ROUTER_LOCAL_STATE>(void)
{
    uint8_t state = SPINEL_THREAD_BACKBONE_ROUTER_STATE_DISABLED;

    switch (otBackboneRouterGetState(mInstance))
    {
    case OT_BACKBONE_ROUTER_STATE_DISABLED:
        state = SPINEL_THREAD_BACKBONE_ROUTER_STATE_DISABLED;
        break;

    case OT_BACKBONE_ROUTER_STATE_SECONDARY:
        state = SPINEL_THREAD_BACKBONE_ROUTER_STATE_SECONDARY;
        break;

    case OT_BACKBONE_ROUTER_STATE_PRIMARY:
        state = SPINEL_THREAD_BACKBONE_ROUTER_STATE_PRIMARY;
        break;
    }

    return mEncoder.WriteUint8(state);
}

template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_THREAD_BACKBONE_ROUTER_LOCAL_STATE>(void)
{
    uint8_t state;
    otError error = OT_ERROR_NONE;

    SuccessOrExit(error = mDecoder.ReadUint8(state));

    if (state)
    {
        otBackboneRouterSetEnabled(mInstance, true);
    }
    else
    {
        otBackboneRouterSetEnabled(mInstance, false);
    }

exit:
    return error;
}

template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_BACKBONE_ROUTER_LOCAL_CONFIG>(void)
{
    otError                error = OT_ERROR_NONE;
    otBackboneRouterConfig bbrConfig;

    otBackboneRouterGetConfig(mInstance, &bbrConfig);

    SuccessOrExit(error = mEncoder.WriteUint16(bbrConfig.mReregistrationDelay));
    SuccessOrExit(error = mEncoder.WriteUint32(bbrConfig.mMlrTimeout));
    SuccessOrExit(error = mEncoder.WriteUint8(bbrConfig.mSequenceNumber));

exit:
    return error;
}

template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_THREAD_BACKBONE_ROUTER_LOCAL_CONFIG>(void)
{
    otError                error = OT_ERROR_NONE;
    otBackboneRouterConfig bbrConfig;

    SuccessOrExit(error = mDecoder.ReadUint16(bbrConfig.mReregistrationDelay));
    SuccessOrExit(error = mDecoder.ReadUint32(bbrConfig.mMlrTimeout));
    SuccessOrExit(error = mDecoder.ReadUint8(bbrConfig.mSequenceNumber));

    SuccessOrExit(error = otBackboneRouterSetConfig(mInstance, &bbrConfig));

exit:
    return error;
}

template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_THREAD_BACKBONE_ROUTER_LOCAL_REGISTER>(void)
{
    return otBackboneRouterRegister(mInstance);
}

template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_BACKBONE_ROUTER_LOCAL_REGISTRATION_JITTER>(void)
{
    uint8_t jitter = otBackboneRouterGetRegistrationJitter(mInstance);

    return mEncoder.WriteUint8(jitter);
}

template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_THREAD_BACKBONE_ROUTER_LOCAL_REGISTRATION_JITTER>(void)
{
    otError error = OT_ERROR_NONE;
    uint8_t jitter;

    SuccessOrExit(error = mDecoder.ReadUint8(jitter));

    otBackboneRouterSetRegistrationJitter(mInstance, jitter);

exit:
    return error;
}
#endif // OPENTHREAD_FTD && OPENTHREAD_CONFIG_BACKBONE_ROUTER_ENABLE

template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_NET_PSKC>(void)
{
    Pskc pskc;

    otThreadGetPskc(mInstance, &pskc);

    return mEncoder.WriteData(pskc.m8, sizeof(spinel_net_pskc_t));
}

template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_NET_PSKC>(void)
{
    const uint8_t *ptr = nullptr;
    uint16_t       len;
    otError        error = OT_ERROR_NONE;

    SuccessOrExit(error = mDecoder.ReadData(ptr, len));

    VerifyOrExit(len == sizeof(spinel_net_pskc_t), error = OT_ERROR_PARSE);

    error = otThreadSetPskc(mInstance, reinterpret_cast<const otPskc *>(ptr));

exit:
    return error;
}

#if OPENTHREAD_CONFIG_REFERENCE_DEVICE_ENABLE
template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_NET_PARTITION_ID>(void)
{
    uint32_t partitionId = 0;
    otError  error       = OT_ERROR_NONE;

    SuccessOrExit(error = mDecoder.ReadUint32(partitionId));

    otThreadSetPreferredLeaderPartitionId(mInstance, partitionId);

exit:
    return error;
}
#endif

template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_CHILD_COUNT_MAX>(void)
{
    return mEncoder.WriteUint8(static_cast<uint8_t>(otThreadGetMaxAllowedChildren(mInstance)));
}

template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_THREAD_CHILD_COUNT_MAX>(void)
{
    uint8_t maxChildren = 0;
    otError error       = OT_ERROR_NONE;

    SuccessOrExit(error = mDecoder.ReadUint8(maxChildren));

    error = otThreadSetMaxAllowedChildren(mInstance, maxChildren);

exit:
    return error;
}

template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_ROUTER_UPGRADE_THRESHOLD>(void)
{
    return mEncoder.WriteUint8(otThreadGetRouterUpgradeThreshold(mInstance));
}

template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_THREAD_ROUTER_UPGRADE_THRESHOLD>(void)
{
    uint8_t threshold = 0;
    otError error     = OT_ERROR_NONE;

    SuccessOrExit(error = mDecoder.ReadUint8(threshold));

    otThreadSetRouterUpgradeThreshold(mInstance, threshold);

exit:
    return error;
}

template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_ROUTER_DOWNGRADE_THRESHOLD>(void)
{
    return mEncoder.WriteUint8(otThreadGetRouterDowngradeThreshold(mInstance));
}

template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_THREAD_ROUTER_DOWNGRADE_THRESHOLD>(void)
{
    uint8_t threshold = 0;
    otError error     = OT_ERROR_NONE;

    SuccessOrExit(error = mDecoder.ReadUint8(threshold));

    otThreadSetRouterDowngradeThreshold(mInstance, threshold);

exit:
    return error;
}

template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_ROUTER_SELECTION_JITTER>(void)
{
    return mEncoder.WriteUint8(otThreadGetRouterSelectionJitter(mInstance));
}

template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_THREAD_ROUTER_SELECTION_JITTER>(void)
{
    uint8_t jitter = 0;
    otError error  = OT_ERROR_NONE;

    SuccessOrExit(error = mDecoder.ReadUint8(jitter));

    otThreadSetRouterSelectionJitter(mInstance, jitter);

exit:
    return error;
}

template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_CONTEXT_REUSE_DELAY>(void)
{
    return mEncoder.WriteUint32(otThreadGetContextIdReuseDelay(mInstance));
}

template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_THREAD_CONTEXT_REUSE_DELAY>(void)
{
    uint32_t delay = 0;
    otError  error = OT_ERROR_NONE;

    SuccessOrExit(error = mDecoder.ReadUint32(delay));

    otThreadSetContextIdReuseDelay(mInstance, delay);

exit:
    return error;
}

template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_NETWORK_ID_TIMEOUT>(void)
{
    return mEncoder.WriteUint8(otThreadGetNetworkIdTimeout(mInstance));
}

template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_THREAD_NETWORK_ID_TIMEOUT>(void)
{
    uint8_t timeout = 0;
    otError error   = OT_ERROR_NONE;

    SuccessOrExit(error = mDecoder.ReadUint8(timeout));

    otThreadSetNetworkIdTimeout(mInstance, timeout);

exit:
    return error;
}

template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_NEW_DATASET>(void)
{
    otError              error;
    otOperationalDataset dataset;

    error = otDatasetCreateNewNetwork(mInstance, &dataset);

    if (error == OT_ERROR_NONE)
    {
        error = EncodeOperationalDataset(dataset);
    }
    else
    {
        error = mEncoder.OverwriteWithLastStatusError(ThreadErrorToSpinelStatus(error));
    }

    return error;
}

#if OPENTHREAD_CONFIG_COMMISSIONER_ENABLE

template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_MESHCOP_COMMISSIONER_STATE>(void)
{
    uint8_t state = SPINEL_MESHCOP_COMMISSIONER_STATE_DISABLED;

    switch (otCommissionerGetState(mInstance))
    {
    case OT_COMMISSIONER_STATE_DISABLED:
        state = SPINEL_MESHCOP_COMMISSIONER_STATE_DISABLED;
        break;

    case OT_COMMISSIONER_STATE_PETITION:
        state = SPINEL_MESHCOP_COMMISSIONER_STATE_PETITION;
        break;

    case OT_COMMISSIONER_STATE_ACTIVE:
        state = SPINEL_MESHCOP_COMMISSIONER_STATE_ACTIVE;
        break;
    }

    return mEncoder.WriteUint8(state);
}

template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_MESHCOP_COMMISSIONER_STATE>(void)
{
    uint8_t state;
    otError error = OT_ERROR_NONE;

    SuccessOrExit(error = mDecoder.ReadUint8(state));

    switch (state)
    {
    case SPINEL_MESHCOP_COMMISSIONER_STATE_DISABLED:
        error = otCommissionerStop(mInstance);
        break;

    case SPINEL_MESHCOP_COMMISSIONER_STATE_ACTIVE:
        error = otCommissionerStart(mInstance, nullptr, nullptr, nullptr);
        break;

    default:
        error = OT_ERROR_INVALID_ARGS;
        break;
    }

exit:
    return error;
}

template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_MESHCOP_COMMISSIONER_JOINERS>(void)
{
    otError      error = OT_ERROR_NONE;
    uint16_t     iter  = 0;
    otJoinerInfo joinerInfo;

    while (otCommissionerGetNextJoinerInfo(mInstance, &iter, &joinerInfo) == OT_ERROR_NONE)
    {
        SuccessOrExit(error = mEncoder.OpenStruct());

        SuccessOrExit(error = mEncoder.OpenStruct()); // Joiner Id (any, EUI64 or a Joiner Discerner) struct

        switch (joinerInfo.mType)
        {
        case OT_JOINER_INFO_TYPE_ANY:
            break;

        case OT_JOINER_INFO_TYPE_EUI64:
            SuccessOrExit(error = mEncoder.WriteEui64(joinerInfo.mSharedId.mEui64));
            break;

        case OT_JOINER_INFO_TYPE_DISCERNER:
            SuccessOrExit(error = mEncoder.WriteUint8(joinerInfo.mSharedId.mDiscerner.mLength));
            SuccessOrExit(error = mEncoder.WriteUint64(joinerInfo.mSharedId.mDiscerner.mValue));
            break;
        }

        SuccessOrExit(error = mEncoder.CloseStruct());

        SuccessOrExit(error = mEncoder.WriteUint32(joinerInfo.mExpirationTime));
        SuccessOrExit(error = mEncoder.WriteUtf8(joinerInfo.mPskd.m8));

        SuccessOrExit(error = mEncoder.CloseStruct());
    }

exit:
    return error;
}

template <> otError NcpBase::HandlePropertyInsert<SPINEL_PROP_MESHCOP_COMMISSIONER_JOINERS>(void)
{
    otError             error = OT_ERROR_NONE;
    otJoinerDiscerner   discerner;
    bool                withDiscerner = false;
    const otExtAddress *eui64;
    uint32_t            timeout;
    const char         *psk;

    SuccessOrExit(error = mDecoder.OpenStruct());

    switch (mDecoder.GetRemainingLengthInStruct())
    {
    case 0:
        // Empty struct indicates any joiner
        eui64 = nullptr;
        break;

    case sizeof(spinel_eui64_t):
        SuccessOrExit(error = mDecoder.ReadEui64(eui64));
        break;

    default:
        SuccessOrExit(error = mDecoder.ReadUint8(discerner.mLength));
        SuccessOrExit(error = mDecoder.ReadUint64(discerner.mValue));
        withDiscerner = true;
        break;
    }

    SuccessOrExit(error = mDecoder.CloseStruct());

    SuccessOrExit(error = mDecoder.ReadUint32(timeout));
    SuccessOrExit(error = mDecoder.ReadUtf8(psk));

    if (withDiscerner)
    {
        error = otCommissionerAddJoinerWithDiscerner(mInstance, &discerner, psk, timeout);
    }
    else
    {
        error = otCommissionerAddJoiner(mInstance, eui64, psk, timeout);
    }

exit:
    return error;
}

template <> otError NcpBase::HandlePropertyRemove<SPINEL_PROP_MESHCOP_COMMISSIONER_JOINERS>(void)
{
    otError             error = OT_ERROR_NONE;
    otJoinerDiscerner   discerner;
    bool                withDiscerner = false;
    const otExtAddress *eui64;

    SuccessOrExit(error = mDecoder.OpenStruct());

    switch (mDecoder.GetRemainingLengthInStruct())
    {
    case 0:
        // Empty struct indicates any joiner
        eui64 = nullptr;
        break;

    case sizeof(spinel_eui64_t):
        SuccessOrExit(error = mDecoder.ReadEui64(eui64));
        break;

    default:
        SuccessOrExit(error = mDecoder.ReadUint8(discerner.mLength));
        SuccessOrExit(error = mDecoder.ReadUint64(discerner.mValue));
        withDiscerner = true;
        break;
    }

    SuccessOrExit(error = mDecoder.CloseStruct());

    if (withDiscerner)
    {
        error = otCommissionerRemoveJoinerWithDiscerner(mInstance, &discerner);
    }
    else
    {
        error = otCommissionerRemoveJoiner(mInstance, eui64);
    }

exit:
    return error;
}

template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_MESHCOP_COMMISSIONER_PROVISIONING_URL>(void)
{
    return mEncoder.WriteUtf8(otCommissionerGetProvisioningUrl(mInstance));
}

template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_MESHCOP_COMMISSIONER_PROVISIONING_URL>(void)
{
    otError     error = OT_ERROR_NONE;
    const char *url;

    SuccessOrExit(error = mDecoder.ReadUtf8(url));

    error = otCommissionerSetProvisioningUrl(mInstance, url);

exit:
    return error;
}

template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_MESHCOP_COMMISSIONER_SESSION_ID>(void)
{
    return mEncoder.WriteUint16(otCommissionerGetSessionId(mInstance));
}

template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_MESHCOP_COMMISSIONER_ANNOUNCE_BEGIN>(void)
{
    otError             error = OT_ERROR_NONE;
    uint32_t            channelMask;
    uint8_t             count;
    uint16_t            period;
    const otIp6Address *address;

    SuccessOrExit(error = mDecoder.ReadUint32(channelMask));
    SuccessOrExit(error = mDecoder.ReadUint8(count));
    SuccessOrExit(error = mDecoder.ReadUint16(period));
    SuccessOrExit(error = mDecoder.ReadIp6Address(address));

    error = otCommissionerAnnounceBegin(mInstance, channelMask, count, period, address);

exit:
    return error;
}

template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_MESHCOP_COMMISSIONER_ENERGY_SCAN>(void)
{
    otError             error = OT_ERROR_NONE;
    uint32_t            channelMask;
    uint8_t             count;
    uint16_t            period;
    uint16_t            scanDuration;
    const otIp6Address *address;

    SuccessOrExit(error = mDecoder.ReadUint32(channelMask));
    SuccessOrExit(error = mDecoder.ReadUint8(count));
    SuccessOrExit(error = mDecoder.ReadUint16(period));
    SuccessOrExit(error = mDecoder.ReadUint16(scanDuration));
    SuccessOrExit(error = mDecoder.ReadIp6Address(address));

    error = otCommissionerEnergyScan(mInstance, channelMask, count, period, scanDuration, address,
                                     &NcpBase::HandleCommissionerEnergyReport_Jump, this);

exit:
    return error;
}

void NcpBase::HandleCommissionerEnergyReport_Jump(uint32_t       aChannelMask,
                                                  const uint8_t *aEnergyData,
                                                  uint8_t        aLength,
                                                  void          *aContext)
{
    static_cast<NcpBase *>(aContext)->HandleCommissionerEnergyReport(aChannelMask, aEnergyData, aLength);
}

void NcpBase::HandleCommissionerEnergyReport(uint32_t aChannelMask, const uint8_t *aEnergyData, uint8_t aLength)
{
    otError error = OT_ERROR_NONE;

    SuccessOrExit(error = mEncoder.BeginFrame(SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0, SPINEL_CMD_PROP_VALUE_INSERTED,
                                              SPINEL_PROP_MESHCOP_COMMISSIONER_ENERGY_SCAN_RESULT));
    SuccessOrExit(error = mEncoder.WriteUint32(aChannelMask));
    SuccessOrExit(error = mEncoder.WriteDataWithLen(aEnergyData, aLength));
    SuccessOrExit(error = mEncoder.EndFrame());

exit:

    if (error != OT_ERROR_NONE)
    {
        mChangedPropsSet.AddLastStatus(SPINEL_STATUS_NOMEM);
        mUpdateChangedPropsTask.Post();
    }
}

template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_MESHCOP_COMMISSIONER_PAN_ID_QUERY>(void)
{
    otError             error = OT_ERROR_NONE;
    uint16_t            panId;
    uint32_t            channelMask;
    const otIp6Address *address;

    SuccessOrExit(error = mDecoder.ReadUint16(panId));
    SuccessOrExit(error = mDecoder.ReadUint32(channelMask));
    SuccessOrExit(error = mDecoder.ReadIp6Address(address));

    error = otCommissionerPanIdQuery(mInstance, panId, channelMask, address,
                                     &NcpBase::HandleCommissionerPanIdConflict_Jump, this);

exit:
    return error;
}

void NcpBase::HandleCommissionerPanIdConflict_Jump(uint16_t aPanId, uint32_t aChannelMask, void *aContext)
{
    static_cast<NcpBase *>(aContext)->HandleCommissionerPanIdConflict(aPanId, aChannelMask);
}

void NcpBase::HandleCommissionerPanIdConflict(uint16_t aPanId, uint32_t aChannelMask)
{
    otError error = OT_ERROR_NONE;

    SuccessOrExit(error = mEncoder.BeginFrame(SPINEL_HEADER_FLAG | SPINEL_HEADER_IID_0, SPINEL_CMD_PROP_VALUE_INSERTED,
                                              SPINEL_PROP_MESHCOP_COMMISSIONER_PAN_ID_CONFLICT_RESULT));

    SuccessOrExit(error = mEncoder.WriteUint16(aPanId));
    SuccessOrExit(error = mEncoder.WriteUint32(aChannelMask));
    SuccessOrExit(error = mEncoder.EndFrame());

exit:

    if (error != OT_ERROR_NONE)
    {
        mChangedPropsSet.AddLastStatus(SPINEL_STATUS_NOMEM);
        mUpdateChangedPropsTask.Post();
    }
}

template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_MESHCOP_COMMISSIONER_MGMT_GET>(void)
{
    otError        error = OT_ERROR_NONE;
    const uint8_t *tlvs;
    uint16_t       length;

    SuccessOrExit(error = mDecoder.ReadDataWithLen(tlvs, length));
    VerifyOrExit(length <= 255, error = OT_ERROR_INVALID_ARGS);

    error = otCommissionerSendMgmtGet(mInstance, tlvs, static_cast<uint8_t>(length));

exit:
    return error;
}

template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_MESHCOP_COMMISSIONER_MGMT_SET>(void)
{
    otError                error = OT_ERROR_NONE;
    const uint8_t         *tlvs;
    uint16_t               length;
    otCommissioningDataset dataset;

    SuccessOrExit(error = mDecoder.ReadDataWithLen(tlvs, length));
    VerifyOrExit(length <= 255, error = OT_ERROR_INVALID_ARGS);

    memset(&dataset, 0, sizeof(otCommissioningDataset));
    error = otCommissionerSendMgmtSet(mInstance, &dataset, tlvs, static_cast<uint8_t>(length));

exit:
    return error;
}

otError NcpBase::HandlePropertySet_SPINEL_PROP_MESHCOP_COMMISSIONER_GENERATE_PSKC(uint8_t aHeader)
{
    otError        error = OT_ERROR_NONE;
    const char    *passPhrase;
    const char    *networkName;
    const uint8_t *extPanIdData;
    uint16_t       length;
    otPskc         pskc;

    SuccessOrExit(error = mDecoder.ReadUtf8(passPhrase));
    SuccessOrExit(error = mDecoder.ReadUtf8(networkName));
    SuccessOrExit(error = mDecoder.ReadDataWithLen(extPanIdData, length));
    VerifyOrExit(length == sizeof(spinel_net_xpanid_t), error = OT_ERROR_PARSE);

    SuccessOrExit(error = otDatasetGeneratePskc(passPhrase, reinterpret_cast<const otNetworkName *>(networkName),
                                                reinterpret_cast<const otExtendedPanId *>(extPanIdData), &pskc));

    SuccessOrExit(
        error = mEncoder.BeginFrame(aHeader, SPINEL_CMD_PROP_VALUE_IS, SPINEL_PROP_MESHCOP_COMMISSIONER_GENERATE_PSKC));
    SuccessOrExit(error = mEncoder.WriteData(pskc.m8, sizeof(pskc)));
    SuccessOrExit(error = mEncoder.EndFrame());

exit:
    return error;
}

// SPINEL_PROP_THREAD_COMMISSIONER_ENABLED is replaced by SPINEL_PROP_MESHCOP_COMMISSIONER_STATE. Please use the new
// property. The old property/implementation remains for backward compatibility.

template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_COMMISSIONER_ENABLED>(void)
{
    return mEncoder.WriteBool(otCommissionerGetState(mInstance) == OT_COMMISSIONER_STATE_ACTIVE);
}

otError NcpBase::HandlePropertySet_SPINEL_PROP_THREAD_COMMISSIONER_ENABLED(uint8_t aHeader)
{
    bool    enabled = false;
    otError error   = OT_ERROR_NONE;

    SuccessOrExit(error = mDecoder.ReadBool(enabled));

    if (!enabled)
    {
        error = otCommissionerStop(mInstance);
    }
    else
    {
        error = otCommissionerStart(mInstance, nullptr, nullptr, nullptr);
    }

exit:
    return PrepareLastStatusResponse(aHeader, ThreadErrorToSpinelStatus(error));
}

// SPINEL_PROP_THREAD_JOINERS is replaced by SPINEL_PROP_MESHCOP_COMMISSIONER_JOINERS. Please us the new property.
// The old property/implementation remains for backward compatibility.

template <> otError NcpBase::HandlePropertyInsert<SPINEL_PROP_THREAD_JOINERS>(void)
{
    otError             error         = OT_ERROR_NONE;
    const otExtAddress *eui64         = nullptr;
    const char         *pskd          = nullptr;
    uint32_t            joinerTimeout = 0;

    SuccessOrExit(error = mDecoder.ReadUtf8(pskd));
    SuccessOrExit(error = mDecoder.ReadUint32(joinerTimeout));

    if (mDecoder.ReadEui64(eui64) != OT_ERROR_NONE)
    {
        eui64 = nullptr;
    }

    error = otCommissionerAddJoiner(mInstance, eui64, pskd, joinerTimeout);

exit:
    return error;
}
#endif // OPENTHREAD_CONFIG_COMMISSIONER_ENABLE

template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_THREAD_LOCAL_LEADER_WEIGHT>(void)
{
    uint8_t weight;
    otError error = OT_ERROR_NONE;

    SuccessOrExit(error = mDecoder.ReadUint8(weight));

    otThreadSetLocalLeaderWeight(mInstance, weight);

exit:
    return error;
}

#if OPENTHREAD_CONFIG_MLE_STEERING_DATA_SET_OOB_ENABLE

template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_STEERING_DATA>(void)
{
    return mEncoder.WriteEui64(mSteeringDataAddress);
}

template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_THREAD_STEERING_DATA>(void)
{
    otError error = OT_ERROR_NONE;

    SuccessOrExit(error = mDecoder.ReadEui64(mSteeringDataAddress));

    otThreadSetSteeringData(mInstance, &mSteeringDataAddress);

exit:
    return error;
}
#endif // #if OPENTHREAD_CONFIG_MLE_STEERING_DATA_SET_OOB_ENABLE

template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_PREFERRED_ROUTER_ID>(void)
{
    return mEncoder.WriteUint8(mPreferredRouteId);
}

template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_THREAD_PREFERRED_ROUTER_ID>(void)
{
    otError error = OT_ERROR_NONE;

    SuccessOrExit(error = mDecoder.ReadUint8(mPreferredRouteId));

    SuccessOrExit(error = otThreadSetPreferredRouterId(mInstance, mPreferredRouteId));

exit:
    return error;
}

template <> otError NcpBase::HandlePropertyRemove<SPINEL_PROP_THREAD_ACTIVE_ROUTER_IDS>(void)
{
    otError error = OT_ERROR_NONE;
    uint8_t routerId;

    SuccessOrExit(error = mDecoder.ReadUint8(routerId));

    error = otThreadReleaseRouterId(mInstance, routerId);

    // `INVALID_STATE` is returned when router ID was not allocated (i.e. not in the list)
    // in such a case, the "remove" operation can be considered successful.

    if (error == OT_ERROR_INVALID_STATE)
    {
        error = OT_ERROR_NONE;
    }

exit:
    return error;
}

template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_THREAD_ADDRESS_CACHE_TABLE>(void)
{
    otError              error = OT_ERROR_NONE;
    otCacheEntryIterator iterator;
    otCacheEntryInfo     entry;

    memset(&iterator, 0, sizeof(iterator));

    for (uint8_t index = 0;; index++)
    {
        SuccessOrExit(otThreadGetNextCacheEntry(mInstance, &entry, &iterator));

        SuccessOrExit(error = mEncoder.OpenStruct());
        SuccessOrExit(error = mEncoder.WriteIp6Address(entry.mTarget));
        SuccessOrExit(error = mEncoder.WriteUint16(entry.mRloc16));
        SuccessOrExit(error = mEncoder.WriteUint8(index));

        switch (entry.mState)
        {
        case OT_CACHE_ENTRY_STATE_CACHED:
            SuccessOrExit(error = mEncoder.WriteUint8(SPINEL_ADDRESS_CACHE_ENTRY_STATE_CACHED));
            break;
        case OT_CACHE_ENTRY_STATE_SNOOPED:
            SuccessOrExit(error = mEncoder.WriteUint8(SPINEL_ADDRESS_CACHE_ENTRY_STATE_SNOOPED));
            break;
        case OT_CACHE_ENTRY_STATE_QUERY:
            SuccessOrExit(error = mEncoder.WriteUint8(SPINEL_ADDRESS_CACHE_ENTRY_STATE_QUERY));
            break;
        case OT_CACHE_ENTRY_STATE_RETRY_QUERY:
            SuccessOrExit(error = mEncoder.WriteUint8(SPINEL_ADDRESS_CACHE_ENTRY_STATE_RETRY_QUERY));
            break;
        }

        SuccessOrExit(error = mEncoder.OpenStruct());

        if (entry.mState == OT_CACHE_ENTRY_STATE_CACHED)
        {
            SuccessOrExit(error = mEncoder.WriteBool(entry.mValidLastTrans));
            SuccessOrExit(error = mEncoder.WriteUint32(entry.mLastTransTime));
            SuccessOrExit(error = mEncoder.WriteIp6Address(entry.mMeshLocalEid));
        }

        SuccessOrExit(error = mEncoder.CloseStruct());

        SuccessOrExit(error = mEncoder.OpenStruct());

        if (entry.mState != OT_CACHE_ENTRY_STATE_CACHED)
        {
            SuccessOrExit(error = mEncoder.WriteBool(entry.mCanEvict));
            SuccessOrExit(error = mEncoder.WriteUint16(entry.mTimeout));
            SuccessOrExit(error = mEncoder.WriteUint16(entry.mRetryDelay));
        }

        SuccessOrExit(error = mEncoder.CloseStruct());

        SuccessOrExit(error = mEncoder.CloseStruct());
    }

exit:
    return error;
}

template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CHILD_SUPERVISION_INTERVAL>(void)
{
    return mEncoder.WriteUint16(otChildSupervisionGetInterval(mInstance));
}

template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_CHILD_SUPERVISION_INTERVAL>(void)
{
    otError  error = OT_ERROR_NONE;
    uint16_t interval;

    SuccessOrExit(error = mDecoder.ReadUint16(interval));
    otChildSupervisionSetInterval(mInstance, interval);

exit:
    return error;
}

#if OPENTHREAD_CONFIG_CHANNEL_MANAGER_ENABLE

template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CHANNEL_MANAGER_NEW_CHANNEL>(void)
{
    return mEncoder.WriteUint8(otChannelManagerGetRequestedChannel(mInstance));
}

template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_CHANNEL_MANAGER_NEW_CHANNEL>(void)
{
    uint8_t channel;
    otError error = OT_ERROR_NONE;

    SuccessOrExit(error = mDecoder.ReadUint8(channel));

    otChannelManagerRequestChannelChange(mInstance, channel);

exit:
    return error;
}

template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CHANNEL_MANAGER_DELAY>(void)
{
    return mEncoder.WriteUint16(otChannelManagerGetDelay(mInstance));
}

template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_CHANNEL_MANAGER_DELAY>(void)
{
    uint16_t delay;
    otError  error = OT_ERROR_NONE;

    SuccessOrExit(error = mDecoder.ReadUint16(delay));

    error = otChannelManagerSetDelay(mInstance, delay);

exit:
    return error;
}

template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CHANNEL_MANAGER_SUPPORTED_CHANNELS>(void)
{
    return EncodeChannelMask(otChannelManagerGetSupportedChannels(mInstance));
}

template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_CHANNEL_MANAGER_SUPPORTED_CHANNELS>(void)
{
    uint32_t channelMask = 0;
    otError  error       = OT_ERROR_NONE;

    SuccessOrExit(error = DecodeChannelMask(channelMask));
    otChannelManagerSetSupportedChannels(mInstance, channelMask);

exit:
    return error;
}

template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CHANNEL_MANAGER_FAVORED_CHANNELS>(void)
{
    return EncodeChannelMask(otChannelManagerGetFavoredChannels(mInstance));
}

template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_CHANNEL_MANAGER_FAVORED_CHANNELS>(void)
{
    uint32_t channelMask = 0;
    otError  error       = OT_ERROR_NONE;

    SuccessOrExit(error = DecodeChannelMask(channelMask));
    otChannelManagerSetFavoredChannels(mInstance, channelMask);

exit:
    return error;
}

template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CHANNEL_MANAGER_CHANNEL_SELECT>(void)
{
    return mEncoder.WriteBool(false);
}

template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_CHANNEL_MANAGER_CHANNEL_SELECT>(void)
{
    bool    skipQualityCheck = false;
    otError error            = OT_ERROR_NONE;

    SuccessOrExit(error = mDecoder.ReadBool(skipQualityCheck));
    error = otChannelManagerRequestChannelSelect(mInstance, skipQualityCheck);

exit:
    return error;
}

template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CHANNEL_MANAGER_AUTO_SELECT_ENABLED>(void)
{
    return mEncoder.WriteBool(otChannelManagerGetAutoChannelSelectionEnabled(mInstance));
}

template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_CHANNEL_MANAGER_AUTO_SELECT_ENABLED>(void)
{
    bool    enabled = false;
    otError error   = OT_ERROR_NONE;

    SuccessOrExit(error = mDecoder.ReadBool(enabled));
    otChannelManagerSetAutoChannelSelectionEnabled(mInstance, enabled);

exit:
    return error;
}

template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_CHANNEL_MANAGER_AUTO_SELECT_INTERVAL>(void)
{
    return mEncoder.WriteUint32(otChannelManagerGetAutoChannelSelectionInterval(mInstance));
}

template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_CHANNEL_MANAGER_AUTO_SELECT_INTERVAL>(void)
{
    uint32_t interval;
    otError  error = OT_ERROR_NONE;

    SuccessOrExit(error = mDecoder.ReadUint32(interval));
    error = otChannelManagerSetAutoChannelSelectionInterval(mInstance, interval);

exit:
    return error;
}

#endif // OPENTHREAD_CONFIG_CHANNEL_MANAGER_ENABLE

#if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE
template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_TIME_SYNC_PERIOD>(void)
{
    return mEncoder.WriteUint16(otNetworkTimeGetSyncPeriod(mInstance));
}

template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_TIME_SYNC_PERIOD>(void)
{
    otError  error = OT_ERROR_NONE;
    uint16_t timeSyncPeriod;

    SuccessOrExit(error = mDecoder.ReadUint16(timeSyncPeriod));

    SuccessOrExit(error = otNetworkTimeSetSyncPeriod(mInstance, timeSyncPeriod));

exit:
    return error;
}

template <> otError NcpBase::HandlePropertyGet<SPINEL_PROP_TIME_SYNC_XTAL_THRESHOLD>(void)
{
    return mEncoder.WriteUint16(otNetworkTimeGetXtalThreshold(mInstance));
}

template <> otError NcpBase::HandlePropertySet<SPINEL_PROP_TIME_SYNC_XTAL_THRESHOLD>(void)
{
    otError  error = OT_ERROR_NONE;
    uint16_t xtalThreshold;

    SuccessOrExit(error = mDecoder.ReadUint16(xtalThreshold));

    SuccessOrExit(error = otNetworkTimeSetXtalThreshold(mInstance, xtalThreshold));

exit:
    return error;
}
#endif // OPENTHREAD_CONFIG_TIME_SYNC_ENABLE

} // namespace Ncp
} // namespace ot

#endif // OPENTHREAD_FTD
