/*
 *
 *    Copyright (c) 2022 Project CHIP Authors
 *    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
 *      Implementation of the native methods expected by the Python
 *      version of Chip Device Manager.
 *
 */

#include <string>

#include <controller/CHIPDeviceController.h>
#include <controller/python/matter/native/PyChipError.h>
#include <json/json.h>
#include <lib/core/CHIPError.h>
#include <lib/core/TLV.h>
#include <lib/dnssd/Resolver.h>
#include <setup_payload/ManualSetupPayloadGenerator.h>
#include <setup_payload/SetupPayload.h>

using namespace chip;

typedef void (*IterateDiscoveredCommissionableNodesFunct)(const char * deviceInfoJson, size_t deviceInfoLen);

extern "C" {

bool pychip_DeviceController_HasDiscoveredCommissionableNode(Controller::DeviceCommissioner * devCtrl)
{
    for (int i = 0; i < devCtrl->GetMaxCommissionableNodesSupported(); ++i)
    {
        const Dnssd::CommissionNodeData * dnsSdInfo = devCtrl->GetDiscoveredDevice(i);
        if (dnsSdInfo == nullptr)
        {
            continue;
        }
        return true;
    }
    return false;
}

PyChipError pychip_DeviceController_DiscoverCommissionableNodes(Controller::DeviceCommissioner * devCtrl, const uint8_t filterType,
                                                                const char * filterParam)
{
    Dnssd::DiscoveryFilter filter(static_cast<Dnssd::DiscoveryFilterType>(filterType));
    switch (static_cast<Dnssd::DiscoveryFilterType>(filterType))
    {
    case Dnssd::DiscoveryFilterType::kNone:
        break;
    case Dnssd::DiscoveryFilterType::kShortDiscriminator:
    case Dnssd::DiscoveryFilterType::kLongDiscriminator:
    case Dnssd::DiscoveryFilterType::kCompressedFabricId:
    case Dnssd::DiscoveryFilterType::kVendorId:
    case Dnssd::DiscoveryFilterType::kDeviceType: {
        // For any numerical filter, convert the string to a filter value
        errno                               = 0;
        unsigned long long int numericalArg = strtoull(filterParam, nullptr, 0);
        if ((numericalArg == ULLONG_MAX) && (errno == ERANGE))
        {
            return ToPyChipError(CHIP_ERROR_INVALID_ARGUMENT);
        }
        filter.code = static_cast<uint64_t>(numericalArg);
        break;
    }
    case Dnssd::DiscoveryFilterType::kCommissioningMode:
        break;
    case Dnssd::DiscoveryFilterType::kCommissioner:
        filter.code = 1;
        break;
    case Dnssd::DiscoveryFilterType::kInstanceName:
        filter.code         = 0;
        filter.instanceName = filterParam;
        break;
    default:
        return ToPyChipError(CHIP_ERROR_INVALID_ARGUMENT);
    }

    return ToPyChipError(devCtrl->DiscoverCommissionableNodes(filter));
}

PyChipError pychip_DeviceController_StopCommissionableDiscovery(Controller::DeviceCommissioner * devCtrl)
{
    return ToPyChipError(devCtrl->StopCommissionableDiscovery());
}

void pychip_DeviceController_IterateDiscoveredCommissionableNodes(Controller::DeviceCommissioner * devCtrl,
                                                                  IterateDiscoveredCommissionableNodesFunct cb)
{
    VerifyOrReturn(cb != nullptr);

    for (int i = 0; i < devCtrl->GetMaxCommissionableNodesSupported(); ++i)
    {
        const Dnssd::CommissionNodeData * dnsSdInfo = devCtrl->GetDiscoveredDevice(i);
        if (dnsSdInfo == nullptr)
        {
            continue;
        }

        Json::Value jsonVal;

        char rotatingId[Dnssd::kMaxRotatingIdLen * 2 + 1] = "";
        TEMPORARY_RETURN_IGNORED Encoding::BytesToUppercaseHexString(dnsSdInfo->rotatingId, dnsSdInfo->rotatingIdLen, rotatingId,
                                                                     sizeof(rotatingId));

        ChipLogProgress(Discovery, "Commissionable Node %d", i);
        jsonVal["instanceName"]       = dnsSdInfo->instanceName;
        jsonVal["hostName"]           = dnsSdInfo->hostName;
        jsonVal["port"]               = dnsSdInfo->port;
        jsonVal["longDiscriminator"]  = dnsSdInfo->longDiscriminator;
        jsonVal["vendorId"]           = dnsSdInfo->vendorId;
        jsonVal["productId"]          = dnsSdInfo->productId;
        jsonVal["commissioningMode"]  = dnsSdInfo->commissioningMode;
        jsonVal["deviceType"]         = dnsSdInfo->deviceType;
        jsonVal["deviceName"]         = dnsSdInfo->deviceName;
        jsonVal["pairingInstruction"] = dnsSdInfo->pairingInstruction;
        jsonVal["pairingHint"]        = dnsSdInfo->pairingHint;

        auto idleInterval = dnsSdInfo->GetMrpRetryIntervalIdle();
        if (idleInterval.has_value())
        {
            jsonVal["mrpRetryIntervalIdle"] = idleInterval->count();
        }

        auto activeInterval = dnsSdInfo->GetMrpRetryIntervalActive();
        if (activeInterval.has_value())
        {
            jsonVal["mrpRetryIntervalActive"] = activeInterval->count();
        }

        auto activeThreshold = dnsSdInfo->GetMrpRetryActiveThreshold();
        if (activeThreshold.has_value())
        {
            jsonVal["mrpRetryActiveThreshold"] = activeThreshold->count();
        }

        jsonVal["supportsTcpClient"] = dnsSdInfo->supportsTcpClient;
        jsonVal["supportsTcpServer"] = dnsSdInfo->supportsTcpServer;
        {
            Json::Value addresses;
            for (unsigned j = 0; j < dnsSdInfo->numIPs; ++j)
            {
                char buf[Inet::IPAddress::kMaxStringLength];
                dnsSdInfo->ipAddress[j].ToString(buf);
                addresses[j] = buf;
            }
            jsonVal["addresses"] = addresses;
        }
        if (dnsSdInfo->isICDOperatingAsLIT.has_value())
        {
            jsonVal["isICDOperatingAsLIT"] = *(dnsSdInfo->isICDOperatingAsLIT);
        }
        if (dnsSdInfo->rotatingIdLen > 0)
        {
            jsonVal["rotatingId"] = rotatingId;
        }

        {
            auto str = jsonVal.toStyledString();
            cb(str.c_str(), str.size());
        }
    }
}

bool pychip_DeviceController_GetIPForDiscoveredDevice(Controller::DeviceCommissioner * devCtrl, int idx, char * addrStr,
                                                      uint32_t len)
{
    const Dnssd::CommissionNodeData * dnsSdInfo = devCtrl->GetDiscoveredDevice(idx);
    if (dnsSdInfo == nullptr)
    {
        return false;
    }
    // TODO(cecille): Select which one we actually want.
    if (dnsSdInfo->ipAddress[0].ToString(addrStr, len) == addrStr)
    {
        return true;
    }
    return false;
}

PyChipError pychip_CreateManualCode(uint16_t longDiscriminator, uint32_t passcode, char * manualCodeBuffer, size_t inBufSize,
                                    size_t * outBufSize)
{
    SetupPayload payload;
    SetupDiscriminator discriminator;
    discriminator.SetLongValue(longDiscriminator);
    payload.discriminator = discriminator;
    payload.setUpPINCode  = passcode;
    std::string setupManualCode;

    *outBufSize    = 0;
    CHIP_ERROR err = ManualSetupPayloadGenerator(payload).payloadDecimalStringRepresentation(setupManualCode);
    if (err == CHIP_NO_ERROR)
    {
        MutableCharSpan span(manualCodeBuffer, inBufSize);
        // Plus 1 so we copy the null terminator
        TEMPORARY_RETURN_IGNORED CopyCharSpanToMutableCharSpan(CharSpan(setupManualCode.c_str(), setupManualCode.length() + 1),
                                                               span);
        *outBufSize = span.size();
        if (*outBufSize == 0)
        {
            err = CHIP_ERROR_NO_MEMORY;
        }
    }

    return ToPyChipError(err);
}
}
