/*
 *
 *    Copyright (c) 2013-2017 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
 *      This file implements a derived unsolicited responder
 *      (i.e., server) for the Weave Network Provisioning profile used
 *      for the Weave mock device command line functional testing
 *      tool.
 *
 */

#define __STDC_LIMIT_MACROS
#define __STDC_FORMAT_MACROS

#include <inttypes.h>
#include <limits.h>
#include <stdio.h>

#include "ToolCommon.h"
#include "MockNPServer.h"
#include <Weave/Support/CodeUtils.h>
#include <Weave/Core/WeaveTLV.h>
#include <Weave/Profiles/WeaveProfiles.h>
#include <Weave/Profiles/common/CommonProfile.h>
#include "MockOpActions.h"

extern MockOpActions OpActions;

using namespace nl::Weave::TLV;
using namespace nl::Weave::Profiles;
using namespace nl::Weave::Profiles::NetworkProvisioning;

MockNetworkProvisioningServer::MockNetworkProvisioningServer()
{
    NextNetworkId = 1;

    // NOTE: If you change this code, be sure to adjust MockNetworkProvisioningServer::Preconfig()
    // accordingly.

    ScanResults[0].NetworkType = kNetworkType_WiFi;
    ScanResults[0].WiFiSSID = strdup("Wireless-1");
    ScanResults[0].WiFiMode = kWiFiMode_Managed;
    ScanResults[0].WiFiRole = kWiFiRole_Station;
    ScanResults[0].WiFiSecurityType = kWiFiSecurityType_None;
    ScanResults[0].WirelessSignalStrength = 30;

    ScanResults[1].NetworkType = kNetworkType_WiFi;
    ScanResults[1].WiFiSSID = strdup("Wireless-2");
    ScanResults[1].WiFiMode = kWiFiMode_Managed;
    ScanResults[1].WiFiRole = kWiFiRole_Station;
    ScanResults[1].WiFiSecurityType = kWiFiSecurityType_WEP;
    ScanResults[1].WirelessSignalStrength = 10;

    ScanResults[2].NetworkType = kNetworkType_WiFi;
    ScanResults[2].WiFiSSID = strdup("Wireless-3");
    ScanResults[2].WiFiMode = kWiFiMode_Managed;
    ScanResults[2].WiFiRole = kWiFiRole_Station;
    ScanResults[2].WiFiSecurityType = kWiFiSecurityType_WPAPersonal;
    ScanResults[2].WirelessSignalStrength = -11;

    ScanResults[3].NetworkType = kNetworkType_Thread;
    ScanResults[3].ThreadNetworkName = strdup("Thread-1");
    ScanResults[3].ThreadExtendedPANId = (uint8_t *)malloc(8);
    for (int i = 0; i < 8; i++)
        ScanResults[3].ThreadExtendedPANId[i] = i + 1;
}

WEAVE_ERROR MockNetworkProvisioningServer::Init(WeaveExchangeManager *exchangeMgr)
{
    WEAVE_ERROR err;

    err = this->NetworkProvisioningServer::Init(exchangeMgr);
    SuccessOrExit(err);

    SetDelegate(this);

exit:
    return err;
}

WEAVE_ERROR MockNetworkProvisioningServer::Shutdown()
{
    return this->NetworkProvisioningServer::Shutdown();
}

void MockNetworkProvisioningServer::Reset()
{
    for (int i = 0; i < kMaxProvisionedNetworks; i++)
        ProvisionedNetworks[i].Clear();
    for (int i = 0; i < kMaxScanResults; i++)
        ScanResults[i].NetworkId = -1;
    NextNetworkId = 1;
}

void MockNetworkProvisioningServer::Preconfig()
{
    Reset();

    ProvisionedNetworks[0].NetworkId = NextNetworkId++;
    ProvisionedNetworks[0].NetworkType = kNetworkType_WiFi;
    ProvisionedNetworks[0].WiFiSSID = strdup("Wireless-3");
    ProvisionedNetworks[0].WiFiMode = kWiFiMode_Managed;
    ProvisionedNetworks[0].WiFiRole = kWiFiRole_Station;
    ProvisionedNetworks[0].WiFiSecurityType = kWiFiSecurityType_WPAPersonal;
    ProvisionedNetworks[0].WiFiKey = (uint8_t *)strdup("apassword");
    ProvisionedNetworks[0].WiFiKeyLen = strlen((const char *)ProvisionedNetworks[0].WiFiKey);

    ProvisionedNetworks[1].NetworkId = NextNetworkId++;
    ProvisionedNetworks[1].NetworkType = kNetworkType_Thread;
    ProvisionedNetworks[1].ThreadNetworkName = strdup("Thread-1");
    ProvisionedNetworks[1].ThreadExtendedPANId = (uint8_t *)malloc(8);
    for (int i = 0; i < 8; i++)
        ProvisionedNetworks[1].ThreadExtendedPANId[i] = i + 1;
    ProvisionedNetworks[1].ThreadNetworkKey = (uint8_t *)strdup("thisisathreadkey"); // must be 16 bytes
    ProvisionedNetworks[1].ThreadNetworkKeyLen = strlen((const char *)ProvisionedNetworks[1].ThreadNetworkKey);
}

WEAVE_ERROR MockNetworkProvisioningServer::HandleScanNetworks(uint8_t networkType)
{
    {
        char ipAddrStr[64];
        mCurOp->PeerAddr.ToString(ipAddrStr, sizeof(ipAddrStr));
        printf("ScanNetworks request received from node %" PRIX64 " (%s)\n", mCurOp->PeerNodeId, ipAddrStr);
        printf("  Requested Network Type: %d\n", networkType);
    }

    mOpArgs.networkType = networkType;

    CompleteOrDelayCurrentOp("scan-networks");

    return WEAVE_NO_ERROR;
}

WEAVE_ERROR MockNetworkProvisioningServer::ValidateNetworkConfig(NetworkInfo& netConfig)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;

    if (netConfig.NetworkType == kNetworkType_NotSpecified)
    {
        printf("Invalid network configuration: network type not specified\n");
        err = SendStatusReport(kWeaveProfile_NetworkProvisioning, kStatusCode_InvalidNetworkConfiguration);
        SuccessOrExit(err);
        ExitNow(err = WEAVE_ERROR_INVALID_ARGUMENT);
    }

    if (netConfig.NetworkType == kNetworkType_WiFi)
    {
        if (netConfig.WiFiSSID == NULL)
        {
            printf("Invalid network configuration: Missing WiFi SSID\n");
            err = SendStatusReport(kWeaveProfile_NetworkProvisioning, kStatusCode_InvalidNetworkConfiguration);
            SuccessOrExit(err);
            ExitNow(err = WEAVE_ERROR_INVALID_ARGUMENT);
        }

        if (netConfig.WiFiMode == kWiFiMode_NotSpecified)
        {
            printf("Invalid network configuration: Missing WiFi Mode\n");
            err = SendStatusReport(kWeaveProfile_NetworkProvisioning, kStatusCode_InvalidNetworkConfiguration);
            SuccessOrExit(err);
            ExitNow(err = WEAVE_ERROR_INVALID_ARGUMENT);
        }

        if (netConfig.WiFiRole == kWiFiRole_NotSpecified)
        {
            printf("Invalid network configuration: Missing WiFi Role\n");
            err = SendStatusReport(kWeaveProfile_NetworkProvisioning, kStatusCode_InvalidNetworkConfiguration);
            SuccessOrExit(err);
            ExitNow(err = WEAVE_ERROR_INVALID_ARGUMENT);
        }

        if (netConfig.WiFiSecurityType == kWiFiSecurityType_NotSpecified)
        {
            printf("Invalid network configuration: Missing WiFi Security Type\n");
            err = SendStatusReport(kWeaveProfile_NetworkProvisioning, kStatusCode_InvalidNetworkConfiguration);
            SuccessOrExit(err);
            ExitNow(err = WEAVE_ERROR_INVALID_ARGUMENT);
        }

        if (netConfig.WiFiMode != kWiFiMode_Managed)
        {
            printf("Unsupported WiFi Mode: %d\n", netConfig.WiFiMode);
            err = SendStatusReport(kWeaveProfile_NetworkProvisioning, kStatusCode_UnsupportedWiFiMode);
            SuccessOrExit(err);
            ExitNow(err = WEAVE_ERROR_INVALID_ARGUMENT);
        }

        if (netConfig.WiFiRole != kWiFiRole_Station)
        {
            printf("Unsupported WiFi Role: %d\n", netConfig.WiFiRole);
            err = SendStatusReport(kWeaveProfile_NetworkProvisioning, kStatusCode_UnsupportedWiFiRole);
            SuccessOrExit(err);
            ExitNow(err = WEAVE_ERROR_INVALID_ARGUMENT);
        }

        if (netConfig.WiFiSecurityType != kWiFiSecurityType_None && netConfig.WiFiSecurityType != kWiFiSecurityType_WEP
                && netConfig.WiFiSecurityType != kWiFiSecurityType_WPAPersonal
                && netConfig.WiFiSecurityType != kWiFiSecurityType_WPA2Personal
                && netConfig.WiFiSecurityType != kWiFiSecurityType_WPA2MixedPersonal)
        {
            printf("Unsupported WiFi Security Type: %d\n", netConfig.WiFiSecurityType);
            err = SendStatusReport(kWeaveProfile_NetworkProvisioning, kStatusCode_UnsupportedWiFiSecurityType);
            SuccessOrExit(err);
            ExitNow(err = WEAVE_ERROR_INVALID_ARGUMENT);
        }

        if (netConfig.WiFiSecurityType != kWiFiSecurityType_None && netConfig.WiFiKey == NULL)
        {
            printf("Invalid network configuration: Missing WiFi Key\n");
            err = SendStatusReport(kWeaveProfile_NetworkProvisioning, kStatusCode_InvalidNetworkConfiguration);
            SuccessOrExit(err);
            ExitNow(err = WEAVE_ERROR_INVALID_ARGUMENT);
        }
    }

    else if (netConfig.NetworkType == kNetworkType_Thread)
    {
        // Verify that other network parameters are valid when Extended PAN Id (EPANID) present.
        // When EPANID is specified: new Thread network should be added.
        // When EPANID is not specified: new Thread network should be created.
        if (netConfig.ThreadExtendedPANId != NULL)
        {
            if (netConfig.ThreadNetworkName == NULL)
            {
                printf("Invalid network configuration: Missing Thread network name\n");
                err = SendStatusReport(kWeaveProfile_NetworkProvisioning, kStatusCode_InvalidNetworkConfiguration);
                SuccessOrExit(err);
                ExitNow(err = WEAVE_ERROR_INVALID_ARGUMENT);
            }

            if (netConfig.ThreadNetworkKey == NULL)
            {
                printf("Invalid network configuration: Missing Thread network key\n");
                err = SendStatusReport(kWeaveProfile_NetworkProvisioning, kStatusCode_InvalidNetworkConfiguration);
                SuccessOrExit(err);
                ExitNow(err = WEAVE_ERROR_INVALID_ARGUMENT);
            }

            if (netConfig.ThreadNetworkKeyLen == 0)
            {
                printf("Invalid network configuration: Zero-length Thread network key\n");
                err = SendStatusReport(kWeaveProfile_NetworkProvisioning, kStatusCode_InvalidNetworkConfiguration);
                SuccessOrExit(err);
                ExitNow(err = WEAVE_ERROR_INVALID_ARGUMENT);
            }
        }
    }

    else
    {
        printf("Unsupported network type: %d\n", netConfig.NetworkType);
        err = SendStatusReport(kWeaveProfile_NetworkProvisioning, kStatusCode_UnsupportedNetworkType);
        SuccessOrExit(err);
        ExitNow(err = WEAVE_ERROR_INVALID_ARGUMENT);
    }

    printf("Network configuration valid\n");

exit:
    return err;
}

WEAVE_ERROR MockNetworkProvisioningServer::HandleAddNetwork(PacketBuffer* networkInfoTLV)
{
    {
        char ipAddrStr[64];
        mCurOp->PeerAddr.ToString(ipAddrStr, sizeof(ipAddrStr));
        printf("AddNetwork request received from node %" PRIX64 " (%s)\n", mCurOp->PeerNodeId, ipAddrStr);
    }

    mOpArgs.networkInfoTLV = networkInfoTLV;

    CompleteOrDelayCurrentOp("add-network");

    return WEAVE_NO_ERROR;
}

WEAVE_ERROR MockNetworkProvisioningServer::HandleUpdateNetwork(PacketBuffer* networkInfoTLV)
{
    {
        char ipAddrStr[64];
        mCurOp->PeerAddr.ToString(ipAddrStr, sizeof(ipAddrStr));
        printf("UpdateNetwork request received from node %" PRIX64 " (%s)\n", mCurOp->PeerNodeId, ipAddrStr);
    }

    mOpArgs.networkInfoTLV = networkInfoTLV;

    CompleteOrDelayCurrentOp("update-network");

    return WEAVE_NO_ERROR;
}

WEAVE_ERROR MockNetworkProvisioningServer::HandleRemoveNetwork(uint32_t networkId)
{
    {
        char ipAddrStr[64];
        mCurOp->PeerAddr.ToString(ipAddrStr, sizeof(ipAddrStr));
        printf("RemoveNetwork request received from node %" PRIX64 " (%s)\n", mCurOp->PeerNodeId, ipAddrStr);
        printf("  Network Id: %u\n", networkId);
    }

    mOpArgs.networkId = networkId;

    CompleteOrDelayCurrentOp("remove-network");

    return WEAVE_NO_ERROR;
}

WEAVE_ERROR MockNetworkProvisioningServer::HandleGetNetworks(uint8_t flags)
{
    {
        char ipAddrStr[64];
        mCurOp->PeerAddr.ToString(ipAddrStr, sizeof(ipAddrStr));
        printf("GetNetworks request received from node %" PRIX64 " (%s)\n", mCurOp->PeerNodeId, ipAddrStr);
        printf("  Flags: %d\n", flags);
    }

    mOpArgs.flags = flags;

    CompleteOrDelayCurrentOp("get-networks");

    return WEAVE_NO_ERROR;
}

WEAVE_ERROR MockNetworkProvisioningServer::HandleEnableNetwork(uint32_t networkId)
{
    {
        char ipAddrStr[64];
        mCurOp->PeerAddr.ToString(ipAddrStr, sizeof(ipAddrStr));
        printf("EnableNetwork request received from node %" PRIX64 " (%s)\n", mCurOp->PeerNodeId, ipAddrStr);
        printf("  Network Id: %u\n", networkId);
    }

    mOpArgs.networkId = networkId;

    CompleteOrDelayCurrentOp("enable-network");

    return WEAVE_NO_ERROR;
}

WEAVE_ERROR MockNetworkProvisioningServer::HandleDisableNetwork(uint32_t networkId)
{
    {
        char ipAddrStr[64];
        mCurOp->PeerAddr.ToString(ipAddrStr, sizeof(ipAddrStr));
        printf("DisableNetwork request received from node %" PRIX64 " (%s)\n", mCurOp->PeerNodeId, ipAddrStr);
        printf("  Network Id: %u\n", networkId);
    }

    mOpArgs.networkId = networkId;

    CompleteOrDelayCurrentOp("disable-network");

    return WEAVE_NO_ERROR;
}

WEAVE_ERROR MockNetworkProvisioningServer::HandleTestConnectivity(uint32_t networkId)
{
    {
        char ipAddrStr[64];
        mCurOp->PeerAddr.ToString(ipAddrStr, sizeof(ipAddrStr));
        printf("TestConnectivity request received from node %" PRIX64 " (%s)\n", mCurOp->PeerNodeId, ipAddrStr);
        printf("  Network Id: %u\n", networkId);
    }

    mOpArgs.networkId = networkId;

    CompleteOrDelayCurrentOp("test-connectivity");

    return WEAVE_NO_ERROR;
}

WEAVE_ERROR MockNetworkProvisioningServer::HandleSetRendezvousMode(uint16_t rendezvousMode)
{
    {
        char ipAddrStr[64];
        mCurOp->PeerAddr.ToString(ipAddrStr, sizeof(ipAddrStr));
        printf("SetRendezvousMode request received from node %" PRIX64 " (%s)\n", mCurOp->PeerNodeId, ipAddrStr);
        printf("  Rendezvous Mode: %u\n", rendezvousMode);
    }

    mOpArgs.rendezvousMode = rendezvousMode;

    CompleteOrDelayCurrentOp("set-rendezvous-mode");

    return WEAVE_NO_ERROR;
}

void MockNetworkProvisioningServer::EnforceAccessControl(nl::Weave::ExchangeContext *ec, uint32_t msgProfileId, uint8_t msgType,
            const nl::Weave::WeaveMessageInfo *msgInfo, AccessControlResult& result)
{
    if (sSuppressAccessControls)
    {
        result = kAccessControlResult_Accepted;
    }

    NetworkProvisioningDelegate::EnforceAccessControl(ec, msgProfileId, msgType, msgInfo, result);
}

bool MockNetworkProvisioningServer::IsPairedToAccount() const
{
    return (gCASEOptions.ServiceConfig != NULL);
}

void MockNetworkProvisioningServer::HandleOpDelayComplete(System::Layer* lSystemLayer, void* aAppState, System::Error aError)
{
    MockNetworkProvisioningServer* lServer = reinterpret_cast<MockNetworkProvisioningServer*>(aAppState);
    lServer->CompleteCurrentOp();
}

void MockNetworkProvisioningServer::CompleteOrDelayCurrentOp(const char *opName)
{
    uint32_t delay = OpActions.GetDelay(opName);
    if (delay > 0)
    {
        printf("Delaying operation by %lums\n", (unsigned long)delay);
        ::SystemLayer.StartTimer(delay, HandleOpDelayComplete, this);
    }
    else
        CompleteCurrentOp();
}

void MockNetworkProvisioningServer::CompleteCurrentOp()
{
    WEAVE_ERROR err;

    switch (mCurOpType)
    {
#if WEAVE_CONFIG_SUPPORT_LEGACY_ADD_NETWORK_MESSAGE
    case NetworkProvisioning::kMsgType_AddNetwork:
#endif
    case NetworkProvisioning::kMsgType_AddNetworkV2:
        err = CompleteAddNetwork(mOpArgs.networkInfoTLV);
        break;
    case NetworkProvisioning::kMsgType_DisableNetwork:
        err = CompleteDisableNetwork(mOpArgs.networkId);
        break;
    case NetworkProvisioning::kMsgType_EnableNetwork:
        err = CompleteEnableNetwork(mOpArgs.networkId);
        break;
    case NetworkProvisioning::kMsgType_GetNetworks:
        err = CompleteGetNetworks(mOpArgs.flags);
        break;
    case NetworkProvisioning::kMsgType_RemoveNetwork:
        err = CompleteRemoveNetwork(mOpArgs.networkId);
        break;
    case NetworkProvisioning::kMsgType_ScanNetworks:
        err = CompleteScanNetworks(mOpArgs.networkType);
        break;
    case NetworkProvisioning::kMsgType_SetRendezvousMode:
        err = CompleteSetRendezvousMode(mOpArgs.rendezvousMode);
        break;
    case NetworkProvisioning::kMsgType_TestConnectivity:
        err = CompleteTestConnectivity(mOpArgs.networkId);
        break;
    case NetworkProvisioning::kMsgType_UpdateNetwork:
        err = CompleteUpdateNetwork(mOpArgs.networkInfoTLV);
        break;
    default:
        err = WEAVE_ERROR_INVALID_MESSAGE_TYPE;
        break;
    }

    if (err != WEAVE_NO_ERROR)
        SendStatusReport(kWeaveProfile_Common, Common::kStatus_InternalError, err);
}

WEAVE_ERROR MockNetworkProvisioningServer::CompleteScanNetworks(uint8_t networkType)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;
    PacketBuffer *respBuf = NULL;
    TLVWriter writer;
    uint16_t resultCount = 0;
    char ipAddrStr[64];
    mCurOp->PeerAddr.ToString(ipAddrStr, sizeof(ipAddrStr));

    if (networkType != kNetworkType_WiFi && networkType != kNetworkType_Thread)
    {
        SendStatusReport(kWeaveProfile_NetworkProvisioning, kStatusCode_UnsupportedNetworkType);
        ExitNow();
    }

    // Make the network ids in the scan results match the ids assigned in the provisioned networks list.
    for (int i = 0; i < kMaxScanResults; i++)
        if (ScanResults[i].NetworkType != kNetworkType_NotSpecified)
        {
            ScanResults[i].NetworkId = -1;
            for (int j = 0; j < kMaxProvisionedNetworks; j++)
                if (ScanResults[i].NetworkType == kNetworkType_WiFi
                        && ProvisionedNetworks[j].NetworkType == kNetworkType_WiFi
                        && strcmp(ScanResults[i].WiFiSSID, ProvisionedNetworks[j].WiFiSSID) == 0
                        && ScanResults[i].WiFiMode == ProvisionedNetworks[j].WiFiMode
                        && ScanResults[i].WiFiRole == ProvisionedNetworks[j].WiFiRole
                        && ScanResults[i].WiFiSecurityType == ProvisionedNetworks[j].WiFiSecurityType)
                {
                    ScanResults[i].NetworkId = ProvisionedNetworks[j].NetworkId;
                    break;
                }
                else if (ScanResults[i].NetworkType == kNetworkType_Thread
                            && ProvisionedNetworks[j].NetworkType == kNetworkType_Thread
                            && strcmp(ScanResults[i].ThreadNetworkName, ProvisionedNetworks[j].ThreadNetworkName) == 0
                            && ScanResults[i].ThreadExtendedPANId == ProvisionedNetworks[j].ThreadExtendedPANId)
                {
                    ScanResults[i].NetworkId = ProvisionedNetworks[j].NetworkId;
                    break;
                }
        }

    respBuf = PacketBuffer::New();
    VerifyOrExit(respBuf != NULL, err = WEAVE_ERROR_NO_MEMORY);

    writer.Init(respBuf);

    err = NetworkInfo::EncodeList(writer, kMaxScanResults, ScanResults, (NetworkType)networkType, NetworkInfo::kEncodeFlag_All, resultCount);
    SuccessOrExit(err);

    err = writer.Finalize();
    SuccessOrExit(err);

    printf("Sending NetworkScanComplete response\n");
    printf("  Network Count: %d\n", resultCount);

    err = SendNetworkScanComplete(resultCount, respBuf);
    respBuf = NULL;
    SuccessOrExit(err);

    return WEAVE_NO_ERROR;

exit:
    if (respBuf != NULL)
        PacketBuffer::Free(respBuf);
    return err;
}

WEAVE_ERROR MockNetworkProvisioningServer::CompleteAddNetwork(PacketBuffer* networkInfoTLV)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;
    NetworkInfo newNetworkConfig;
    NetworkInfo *targetNetworkConfig = NULL;
    TLVReader reader;

    reader.Init(networkInfoTLV);

    err = reader.Next();
    SuccessOrExit(err);

    err = newNetworkConfig.Decode(reader);
    SuccessOrExit(err);

    printf("  Network Config:\n");
    PrintNetworkInfo(newNetworkConfig, "    ");

    newNetworkConfig.WirelessSignalStrength = INT16_MIN;

    err = ValidateNetworkConfig(newNetworkConfig);
    if (err == WEAVE_ERROR_INVALID_ARGUMENT)
        ExitNow(err = WEAVE_NO_ERROR);
    SuccessOrExit(err);

    for (int i = 0; i < kMaxProvisionedNetworks; i++)
    {
        NetworkInfo& curElem = ProvisionedNetworks[i];
        if (curElem.NetworkType == kNetworkType_NotSpecified)
        {
            if (targetNetworkConfig == NULL)
                targetNetworkConfig = &curElem;
            continue;
        }

        if (newNetworkConfig.NetworkType == kNetworkType_WiFi && curElem.NetworkType == kNetworkType_WiFi
                && strcmp(curElem.WiFiSSID, newNetworkConfig.WiFiSSID) == 0
                && curElem.WiFiMode == newNetworkConfig.WiFiMode && curElem.WiFiRole == newNetworkConfig.WiFiRole
                && curElem.WiFiSecurityType == newNetworkConfig.WiFiSecurityType)
        {
            targetNetworkConfig = &curElem;
            break;
        }

        if (newNetworkConfig.NetworkType == kNetworkType_Thread && curElem.NetworkType == kNetworkType_Thread
                && strcmp(curElem.ThreadNetworkName, newNetworkConfig.ThreadNetworkName) == 0
                && memcmp(curElem.ThreadExtendedPANId, newNetworkConfig.ThreadExtendedPANId, 8) == 0)
        {
            targetNetworkConfig = &curElem;
            break;
        }
    }

    if (targetNetworkConfig == NULL)
    {
        err = SendStatusReport(kWeaveProfile_NetworkProvisioning, kStatusCode_TooManyNetworks);
        ExitNow();
    }

    if (targetNetworkConfig->NetworkType != kNetworkType_NotSpecified)
        newNetworkConfig.NetworkId = targetNetworkConfig->NetworkId;
    else
        newNetworkConfig.NetworkId = NextNetworkId++;

    newNetworkConfig.CopyTo(*targetNetworkConfig);

    printf("Sending AddNetworkComplete response\n");
    printf("  Network Id: %lu\n", (unsigned long)targetNetworkConfig->NetworkId);

    err = SendAddNetworkComplete(targetNetworkConfig->NetworkId);
    SuccessOrExit(err);

exit:
    PacketBuffer::Free(networkInfoTLV);
    return err;
}

WEAVE_ERROR MockNetworkProvisioningServer::CompleteUpdateNetwork(PacketBuffer* networkInfoTLV)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;
    NetworkInfo networkConfigUpdate, updatedNetworkConfig;
    NetworkInfo *existingNetworkConfig = NULL;
    TLVReader reader;

    reader.Init(networkInfoTLV);

    err = reader.Next();
    SuccessOrExit(err);

    err = networkConfigUpdate.Decode(reader);
    SuccessOrExit(err);

    printf("  Updated Network Config:\n");
    PrintNetworkInfo(networkConfigUpdate, "    ");

    if (networkConfigUpdate.NetworkId == -1)
    {
        err = SendStatusReport(kWeaveProfile_NetworkProvisioning, kStatusCode_InvalidNetworkConfiguration);
        ExitNow();
    }

    for (int i = 0; i < kMaxProvisionedNetworks; i++)
        if (ProvisionedNetworks[i].NetworkType != kNetworkType_NotSpecified
                && ProvisionedNetworks[i].NetworkId == networkConfigUpdate.NetworkId)
        {
            existingNetworkConfig = &ProvisionedNetworks[i];
            break;
        }

    if (existingNetworkConfig == NULL)
    {
        printf("Specified network id not found\n");
        err = SendStatusReport(kWeaveProfile_NetworkProvisioning, kStatusCode_UnknownNetwork);
        ExitNow();
    }

    err = existingNetworkConfig->CopyTo(updatedNetworkConfig);
    SuccessOrExit(err);

    err = networkConfigUpdate.MergeTo(updatedNetworkConfig);
    SuccessOrExit(err);

    err = ValidateNetworkConfig(updatedNetworkConfig);
    if (err == WEAVE_ERROR_INVALID_ARGUMENT)
        ExitNow(err = WEAVE_NO_ERROR);
    SuccessOrExit(err);

    err = updatedNetworkConfig.CopyTo(*existingNetworkConfig);
    SuccessOrExit(err);

    err = SendSuccessResponse();
    SuccessOrExit(err);

exit:
    PacketBuffer::Free(networkInfoTLV);
    return err;
}

WEAVE_ERROR MockNetworkProvisioningServer::CompleteRemoveNetwork(uint32_t networkId)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;
    NetworkInfo *existingNetworkConfig = NULL;

    for (int i = 0; i < kMaxProvisionedNetworks; i++)
        if (ProvisionedNetworks[i].NetworkType != kNetworkType_NotSpecified
                && ProvisionedNetworks[i].NetworkId == networkId)
        {
            existingNetworkConfig = &ProvisionedNetworks[i];
            break;
        }

    if (existingNetworkConfig == NULL)
    {
        printf("Specified network id not found\n");
        err = SendStatusReport(kWeaveProfile_NetworkProvisioning, kStatusCode_UnknownNetwork);
        ExitNow();
    }

    existingNetworkConfig->Clear();

    err = SendSuccessResponse();
    SuccessOrExit(err);

exit:
    return err;
}

WEAVE_ERROR MockNetworkProvisioningServer::CompleteGetNetworks(uint8_t flags)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;
    PacketBuffer *respBuf = NULL;
    TLVWriter writer;
    uint16_t resultCount = 0;
    char ipAddrStr[64];
    mCurOp->PeerAddr.ToString(ipAddrStr, sizeof(ipAddrStr));

    respBuf = PacketBuffer::New();
    VerifyOrExit(respBuf != NULL, err = WEAVE_ERROR_NO_MEMORY);

    writer.Init(respBuf);

    err = NetworkInfo::EncodeList(writer, kMaxProvisionedNetworks, ProvisionedNetworks, kNetworkType_NotSpecified, flags, resultCount);
    SuccessOrExit(err);

    err = writer.Finalize();
    SuccessOrExit(err);

    printf("Sending GetNetworksComplete response\n");
    printf("  Network Count: %d\n", resultCount);

    err = SendGetNetworksComplete(resultCount, respBuf);
    respBuf = NULL;
    SuccessOrExit(err);

    return WEAVE_NO_ERROR;

exit:
    if (respBuf != NULL)
        PacketBuffer::Free(respBuf);
    return err;
}

WEAVE_ERROR MockNetworkProvisioningServer::CompleteEnableNetwork(uint32_t networkId)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;
    NetworkInfo *existingNetworkConfig = NULL;

    for (int i = 0; i < kMaxProvisionedNetworks; i++)
        if (ProvisionedNetworks[i].NetworkType != kNetworkType_NotSpecified
                && ProvisionedNetworks[i].NetworkId == networkId)
        {
            existingNetworkConfig = &ProvisionedNetworks[i];
            break;
        }

    if (existingNetworkConfig == NULL)
    {
        printf("Specified network id not found\n");
        err = SendStatusReport(kWeaveProfile_NetworkProvisioning, kStatusCode_UnknownNetwork);
        ExitNow();
    }

    err = SendSuccessResponse();
    SuccessOrExit(err);

exit:
    return err;
}

WEAVE_ERROR MockNetworkProvisioningServer::CompleteDisableNetwork(uint32_t networkId)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;
    NetworkInfo *existingNetworkConfig = NULL;

    for (int i = 0; i < kMaxProvisionedNetworks; i++)
        if (ProvisionedNetworks[i].NetworkType != kNetworkType_NotSpecified
                && ProvisionedNetworks[i].NetworkId == networkId)
        {
            printf("Specified network id not found\n");
            existingNetworkConfig = &ProvisionedNetworks[i];
            break;
        }

    if (existingNetworkConfig == NULL)
    {
        err = SendStatusReport(kWeaveProfile_NetworkProvisioning, kStatusCode_UnknownNetwork);
        ExitNow();
    }

    err = SendSuccessResponse();
    SuccessOrExit(err);

exit:
    return err;
}

WEAVE_ERROR MockNetworkProvisioningServer::CompleteTestConnectivity(uint32_t networkId)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;
    NetworkInfo *existingNetworkConfig = NULL;

    for (int i = 0; i < kMaxProvisionedNetworks; i++)
        if (ProvisionedNetworks[i].NetworkType != kNetworkType_NotSpecified
                && ProvisionedNetworks[i].NetworkId == networkId)
        {
            existingNetworkConfig = &ProvisionedNetworks[i];
            break;
        }

    if (existingNetworkConfig == NULL)
    {
        printf("Specified network id not found\n");
        err = SendStatusReport(kWeaveProfile_NetworkProvisioning, kStatusCode_UnknownNetwork);
        ExitNow();
    }

    err = SendSuccessResponse();
    SuccessOrExit(err);

exit:
    return err;
}

WEAVE_ERROR MockNetworkProvisioningServer::CompleteSetRendezvousMode(uint16_t rendezvousMode)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;

    {
        char ipAddrStr[64];
        mCurOp->PeerAddr.ToString(ipAddrStr, sizeof(ipAddrStr));
        printf("SetRendezvousMode request received from node %" PRIX64 " (%s)\n", mCurOp->PeerNodeId, ipAddrStr);
        printf("  Rendezvous Mode: %u\n", rendezvousMode);
    }

    err = SendSuccessResponse();
    SuccessOrExit(err);

exit:
    return err;
}

void MockNetworkProvisioningServer::PrintNetworkInfo(NetworkInfo& netInfo, const char *prefix)
{
    printf("%sNetwork Type: %d\n", prefix, (int)netInfo.NetworkType);
    if (netInfo.NetworkId != -1)
        printf("%sNetwork Id: %ld\n", prefix, (long)netInfo.NetworkId);
    if (netInfo.WiFiSSID != NULL)
        printf("%sWiFi SSID: %s\n", prefix, netInfo.WiFiSSID);
    if (netInfo.WiFiMode != -1)
        printf("%sWiFi Mode: %d\n", prefix, (int)netInfo.WiFiMode);
    if (netInfo.WiFiRole != -1)
        printf("%sWiFi Role: %d\n", prefix, (int)netInfo.WiFiRole);
    if (netInfo.WiFiSecurityType != -1)
        printf("%sWiFi Security Type: %d\n", prefix, (int)netInfo.WiFiSecurityType);
    if (netInfo.WiFiKey != NULL)
    {
        char keyBuf[256];
        uint32_t i = (netInfo.WiFiKeyLen < sizeof(keyBuf)) ? netInfo.WiFiKeyLen : sizeof(keyBuf) - 1;
        memcpy(keyBuf, netInfo.WiFiKey, i);
        keyBuf[i] = 0;
        printf("%sWiFi Key: %s\n", prefix, keyBuf);
    }

    if (netInfo.ThreadNetworkName != NULL)
        printf("%sThread Network Name: %s\n", prefix, netInfo.ThreadNetworkName);
    if (netInfo.ThreadExtendedPANId != NULL)
    {
        printf("%sThread Extended PAN Id: ", prefix);
        for (int i = 0; i < 8; i++)
            printf("%02X", netInfo.ThreadExtendedPANId[i]);
        printf("\n");
    }
    if (netInfo.ThreadNetworkKey != NULL)
    {
        printf("%sThread Network Key: ", prefix);
        for (uint32_t i = 0; i < netInfo.ThreadNetworkKeyLen; i++)
            printf("%02X", netInfo.ThreadNetworkKey[i]);
        printf("\n");
    }
    if (netInfo.WirelessSignalStrength != INT16_MIN)
        printf("%sWireless Signal Strength: %d\n", prefix, (int)netInfo.WirelessSignalStrength);
}

WEAVE_ERROR MockNetworkProvisioningServer::SendStatusReport(uint32_t statusProfileId, uint16_t statusCode, WEAVE_ERROR sysError)
{
    if (statusProfileId == kWeaveProfile_Common && statusCode == Common::kStatus_Success)
        printf("Sending StatusReport: Success\n");
    else if (sysError == WEAVE_NO_ERROR)
        printf("Sending StatusReport: Status code = %u, Status profile = %lu\n", statusCode, (unsigned long)statusProfileId);
    else
        printf("Sending StatusReport: Status code = %u, Status profile = %lu, System error = %d\n", statusCode, (unsigned long)statusProfileId, sysError);
    return this->NetworkProvisioningServer::SendStatusReport(statusProfileId, statusCode, sysError);
}
