/*
 *
 *    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;

static WirelessRegDomain sSupportedRegDomains[] =
{
    { 'U', 'S' },
    { 'C', 'A' },
    { 'G', 'B' },
    { 'F', 'R' },
    { 'D', 'E' },
};

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);

    RegConfig.RegDomain = sSupportedRegDomains[0];
    RegConfig.OpLocation = kWirelessOperatingLocation_Unknown;
    RegConfig.SupportedRegDomains = sSupportedRegDomains;
    RegConfig.NumSupportedRegDomains = ArraySize(sSupportedRegDomains);

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;
    RegConfig.RegDomain = sSupportedRegDomains[0];
    RegConfig.OpLocation = kWirelessOperatingLocation_Unknown;
}

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
}

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);
            }
        }
    }

    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;
}

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

    CompleteOrDelayCurrentOp("get-wireless-reg-config");

    return WEAVE_NO_ERROR;
}

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

    mOpArgs.regConfigTLV = regConfigTLV;

    CompleteOrDelayCurrentOp("set-wireless-reg-config");

    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;
    case NetworkProvisioning::kMsgType_GetWirelessRegulatoryConfig:
        err = CompleteGetWirelessRegulatoryConfig();
        break;
    case NetworkProvisioning::kMsgType_SetWirelessRegulatoryConfig:
        err = CompleteSetWirelessRegulatoryConfig(mOpArgs.regConfigTLV);
        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;

    err = SendSuccessResponse();
    SuccessOrExit(err);

exit:
    return err;
}

WEAVE_ERROR MockNetworkProvisioningServer::CompleteGetWirelessRegulatoryConfig(void)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;
    PacketBuffer *respBuf = NULL;
    TLVWriter writer;

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

    writer.Init(respBuf);

    err = RegConfig.Encode(writer);
    SuccessOrExit(err);

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

    printf("Sending GetWirelessRegulatoryConfigComplete response\n");

    err = SendGetWirelessRegulatoryConfigComplete(respBuf);
    respBuf = NULL;
    SuccessOrExit(err);

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

WEAVE_ERROR MockNetworkProvisioningServer::CompleteSetWirelessRegulatoryConfig(PacketBuffer* regConfigTLV)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;
    WirelessRegConfig newRegConfig;

    newRegConfig.Init();
    err = newRegConfig.DecodeInPlace(regConfigTLV);
    if (err != WEAVE_NO_ERROR)
    {
        SendStatusReport(kWeaveProfile_Common, Profiles::Common::kStatus_BadRequest, err);
        ExitNow(err = WEAVE_NO_ERROR);
    }

    // Ensure that the Supported Regulatory Domains field is not present.
    if (newRegConfig.NumSupportedRegDomains != 0)
    {
        SendStatusReport(kWeaveProfile_Common, Profiles::Common::kStatus_BadRequest, WEAVE_ERROR_INVALID_TLV_ELEMENT);
        ExitNow();
    }

    if (newRegConfig.IsRegDomainPresent())
    {
        // Make sure the specified regulatory domain code is supported.
        if (!newRegConfig.RegDomain.IsWorldWide())
        {
            uint16_t i;
            for (i = 0; i < RegConfig.NumSupportedRegDomains; i++)
            {
                if (RegConfig.SupportedRegDomains[i] == newRegConfig.RegDomain)
                    break;
            }
            if (i == RegConfig.NumSupportedRegDomains)
            {
                SendStatusReport(kWeaveProfile_NetworkProvisioning, Profiles::NetworkProvisioning::kStatusCode_UnsupportedRegulatoryDomain);
                ExitNow();
            }
        }
    }

    if (newRegConfig.IsOpLocationPresent())
    {
        // Make sure the operating location is supported.
        if (RegConfig.OpLocation != kWirelessOperatingLocation_Unknown &&
            RegConfig.OpLocation != kWirelessOperatingLocation_Indoors &&
            RegConfig.OpLocation != kWirelessOperatingLocation_Outdoors)
        {
            SendStatusReport(kWeaveProfile_NetworkProvisioning, Profiles::NetworkProvisioning::kStatusCode_UnsupportedOperatingLocation);
            ExitNow();
        }
    }

    if (newRegConfig.IsRegDomainPresent())
    {
        RegConfig.RegDomain = newRegConfig.RegDomain;
    }

    if (newRegConfig.IsOpLocationPresent())
    {
        RegConfig.OpLocation = newRegConfig.OpLocation;
    }

    printf("Wireless regulatory configuration set to:\n");
    PrintWirelessRegConfig(RegConfig, "  ");

    SendSuccessResponse();

exit:
    PacketBuffer::Free(regConfigTLV);
    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 < NetworkInfo::kThreadNetworkKeyLength; i++)
            printf("%02X", netInfo.ThreadNetworkKey[i]);
        printf("\n");
    }
    if (netInfo.WirelessSignalStrength != INT16_MIN)
        printf("%sWireless Signal Strength: %d\n", prefix, (int)netInfo.WirelessSignalStrength);
}

void MockNetworkProvisioningServer::PrintWirelessRegConfig(WirelessRegConfig& regConfig, const char *prefix)
{
    if (regConfig.IsRegDomainPresent())
        printf("%sRegulatory Domain: %c%c\n", prefix, regConfig.RegDomain.Code[0], regConfig.RegDomain.Code[1]);
    if (regConfig.IsOpLocationPresent())
        printf("%sOperating Location: %d\n", prefix, (int)regConfig.OpLocation);
    if (regConfig.NumSupportedRegDomains > 0)
    {
        printf("%sSupported Regulatory Domains:", prefix);
        for (uint16_t i = 0; i < regConfig.NumSupportedRegDomains; i++)
            printf("%c%c%c", (i == 0) ? ' ' : ',',
                   regConfig.SupportedRegDomains[i].Code[0],
                   regConfig.SupportedRegDomains[i].Code[1]);
        printf("\n");
    }
}

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 = %s\n", statusCode, (unsigned long)statusProfileId, nl::ErrorStr(sysError));
    return this->NetworkProvisioningServer::SendStatusReport(statusProfileId, statusCode, sysError);
}
