/*
 *
 *    Copyright (c) 2020-2022 Project CHIP Authors
 *
 *    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.
 */

#include "DnssdImpl.h"
#include "MdnsError.h"
#include "lib/dnssd/platform/Dnssd.h"

#include "dns_sd.h"
#include "lwip/mld6.h"
#include "mdns.h"
#include <lwip/ip4_addr.h>
#include <lwip/ip6_addr.h>

#include "FreeRTOS.h"
#include "event_groups.h"
#include "lwip/sockets.h"
#undef write
#undef read
#include <cstdio>
#include <sstream>
#include <string.h>
#include <string>

#include "mDNSDebug.h"
#include "task.h"
#include "task_def.h"
#include <errno.h>

#include "platform/CHIPDeviceLayer.h"
#include <lib/support/CHIPMem.h>
#include <lib/support/CodeUtils.h>
#include <lib/support/SafeInt.h>
#include <lib/support/logging/CHIPLogging.h>

using namespace chip::Dnssd;

extern "C" {
extern void mDNSPlatformWriteLogRedirect(void (*)(const char *, const char *));
}

namespace {
constexpr char kLocalDot[]              = "local.";
constexpr char kProtocolTcp[]           = "._tcp";
constexpr char kProtocolUdp[]           = "._udp";
static constexpr uint32_t kTimeoutMilli = 3000;
static constexpr size_t kMaxResults     = 20;

constexpr DNSServiceFlags kRegisterFlags        = kDNSServiceFlagsNoAutoRename;
constexpr DNSServiceFlags kBrowseFlags          = 0;
constexpr DNSServiceFlags kGetAddrInfoFlags     = kDNSServiceFlagsTimeout | kDNSServiceFlagsShareConnection;
constexpr DNSServiceFlags kResolveFlags         = kDNSServiceFlagsShareConnection;
constexpr DNSServiceFlags kReconfirmRecordFlags = 0;

bool IsSupportedProtocol(DnssdServiceProtocol protocol)
{
    return (protocol == DnssdServiceProtocol::kDnssdProtocolUdp) || (protocol == DnssdServiceProtocol::kDnssdProtocolTcp);
}

uint32_t GetInterfaceId(chip::Inet::InterfaceId interfaceId)
{
    return interfaceId.IsPresent() ? (uint32_t) (void *) interfaceId.GetPlatformInterface() : kDNSServiceInterfaceIndexAny;
}

std::string GetFullType(const char * type, DnssdServiceProtocol protocol)
{
    std::ostringstream typeBuilder;
    typeBuilder << type;
    typeBuilder << (protocol == DnssdServiceProtocol::kDnssdProtocolUdp ? kProtocolUdp : kProtocolTcp);
    return typeBuilder.str();
}

std::string GetFullType(const DnssdService * service)
{
    return GetFullType(service->mType, service->mProtocol);
}

std::string GetFullTypeWithSubTypes(const char * type, DnssdServiceProtocol protocol, const char * subTypes[], size_t subTypeSize)
{
    std::ostringstream typeBuilder;
    typeBuilder << type;
    typeBuilder << (protocol == DnssdServiceProtocol::kDnssdProtocolUdp ? kProtocolUdp : kProtocolTcp);
    for (int i = 0; i < (int) subTypeSize; i++)
    {
        typeBuilder << ",";
        typeBuilder << subTypes[i];
    }
    return typeBuilder.str();
}

std::string GetFullTypeWithSubTypes(const char * type, DnssdServiceProtocol protocol)
{
    auto fullType = GetFullType(type, protocol);

    std::string subtypeDelimiter = "._sub.";
    size_t position              = fullType.find(subtypeDelimiter);
    if (position != std::string::npos)
    {
        fullType = fullType.substr(position + subtypeDelimiter.size()) + "," + fullType.substr(0, position);
    }

    return fullType;
}

std::string GetFullTypeWithSubTypes(const DnssdService * service)
{
    return GetFullTypeWithSubTypes(service->mType, service->mProtocol, service->mSubTypes, service->mSubTypeSize);
}

std::string GetHostNameWithDomain(const char * hostname)
{
    return std::string(hostname) + '.' + kLocalDot;
}

void LogOnFailure(const char * name, DNSServiceErrorType err)
{
    if (kDNSServiceErr_NoError != err)
    {
        ChipLogError(Discovery, "%s (%s)", name, Error::ToString(err));
    }
}

class ScopedTXTRecord
{
public:
    ScopedTXTRecord() {}

    ~ScopedTXTRecord()
    {
        if (mDataSize != 0)
        {
            TXTRecordDeallocate(&mRecordRef);
        }
    }

    CHIP_ERROR Init(TextEntry * textEntries, size_t textEntrySize)
    {
        VerifyOrReturnError(textEntrySize <= kDnssdTextMaxSize, CHIP_ERROR_INVALID_ARGUMENT);

        TXTRecordCreate(&mRecordRef, sizeof(mRecordBuffer), mRecordBuffer);

        for (size_t i = 0; i < textEntrySize; i++)
        {
            TextEntry entry = textEntries[i];
            VerifyOrReturnError(chip::CanCastTo<uint8_t>(entry.mDataSize), CHIP_ERROR_INVALID_ARGUMENT);

            auto err = TXTRecordSetValue(&mRecordRef, entry.mKey, static_cast<uint8_t>(entry.mDataSize), entry.mData);
            VerifyOrReturnError(err == kDNSServiceErr_NoError, CHIP_ERROR_INVALID_ARGUMENT);
        }

        mDataSize = TXTRecordGetLength(&mRecordRef);
        if (mDataSize == 0)
        {
            TXTRecordDeallocate(&mRecordRef);
        }

        mData = TXTRecordGetBytesPtr(&mRecordRef);
        return CHIP_NO_ERROR;
    }

    uint16_t size() { return mDataSize; }
    const void * data() { return mData; }

private:
    uint16_t mDataSize = 0;
    const void * mData = nullptr;

    TXTRecordRef mRecordRef;
    char mRecordBuffer[kDnssdTextMaxSize];
};
} // namespace

namespace chip {
namespace Dnssd {

#define SERVICE_DOMAIN ("local")

MdnsContexts MdnsContexts::sInstance;
static DNSServiceRef BrowseClient = NULL;
static TaskHandle_t gResolveTask  = NULL;
static EventGroupHandle_t gResolveTaskWakeEvent;

void ChipDnssdMdnsLog(const char * level, const char * msg)
{
    ChipLogProgress(ServiceProvisioning, "%s %s", StringOrNullMarker(level), StringOrNullMarker(msg));
}

static void OnRegister(DNSServiceRef sdRef, DNSServiceFlags flags, DNSServiceErrorType err, const char * name, const char * type,
                       const char * domain, void * context)
{
    ChipLogDetail(Discovery, "Mdns: %s name: %s, type: %s, domain: %s, flags: %ld", __func__, name, type, domain, flags);

    auto sdCtx = reinterpret_cast<RegisterContext *>(context);
    sdCtx->Finalize(err);
};

CHIP_ERROR Register(void * context, DnssdPublishCallback callback, uint32_t interfaceId, const char * type, const char * name,
                    uint16_t port, ScopedTXTRecord & record, Inet::IPAddressType addressType, const char * hostname)
{
    ChipLogDetail(Discovery, "Registering service %s on host %s with port %u and type: %s on interface id: %" PRIu32, name,
                  hostname, port, type, interfaceId);

    RegisterContext * sdCtx = nullptr;
    if (CHIP_NO_ERROR == MdnsContexts::GetInstance().GetRegisterContextOfType(type, &sdCtx))
    {
        auto err = DNSServiceUpdateRecord(sdCtx->serviceRef, nullptr, kRegisterFlags, record.size(), record.data(), 0 /* ttl */);
        VerifyOrReturnError(kDNSServiceErr_NoError == err, sdCtx->Finalize(err));
        return CHIP_NO_ERROR;
    }

    sdCtx = chip::Platform::New<RegisterContext>(type, name, callback, context);
    VerifyOrReturnError(nullptr != sdCtx, CHIP_ERROR_NO_MEMORY);

    DNSServiceRef sdRef;
    auto err = DNSServiceRegister(&sdRef, kRegisterFlags, interfaceId, name, type, kLocalDot, hostname, htons(port), record.size(),
                                  record.data(), OnRegister, sdCtx);
    VerifyOrReturnError(kDNSServiceErr_NoError == err, sdCtx->Finalize(err));

    return MdnsContexts::GetInstance().Add(sdCtx, sdRef);
}

static void mdnsd_entry(void * not_used)
{
    ChipLogProgress(ServiceProvisioning, "mdnsd_entry start");
    mdnsd_start();
    ChipLogProgress(ServiceProvisioning, "mdnsd_entry return");
    vTaskDelete(NULL);
}

CHIP_ERROR ChipDnssdInit(DnssdAsyncReturnCallback initCallback, DnssdAsyncReturnCallback errorCallback, void * context)
{
    CHIP_ERROR error = CHIP_NO_ERROR;
#if LWIP_IPV6
    struct netif * sta_if = netif_default;
    ip6_addr_t mld_address;
#endif

#if LWIP_IPV6
    sta_if->ip6_autoconfig_enabled = 1;
    ip6_addr_set_solicitednode(&mld_address, netif_ip6_addr(sta_if, 0)->addr[3]);
    mld6_joingroup(netif_ip6_addr(sta_if, 0), &mld_address);
#endif

    ChipLogProgress(ServiceProvisioning, "create mdnsd_task");

    mDNSPlatformWriteLogRedirect(ChipDnssdMdnsLog);

    // xTaskHandle create mDNS daemon task
    if (pdPASS != xTaskCreate(mdnsd_entry, "mdnsd", (15 * 1024) / sizeof(portSTACK_TYPE), NULL, TASK_PRIORITY_NORMAL, NULL))
    {
        ChipLogProgress(ServiceProvisioning, "Cannot create mdnsd_task");
        error = CHIP_ERROR_INTERNAL;
    }

    initCallback(context, error);

    return error;
}

void ChipDnssdShutdown(void)
{
    ChipLogProgress(ServiceProvisioning, "shutdown mdnsd_task not implemented");
}

static const char * GetProtocolString(DnssdServiceProtocol protocol)
{
    return protocol == DnssdServiceProtocol::kDnssdProtocolTcp ? "_tcp" : "_udp";
}

CHIP_ERROR ChipDnssdPublishService(const DnssdService * service, DnssdPublishCallback callback, void * context)
{
    VerifyOrReturnError(service != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
    VerifyOrReturnError(IsSupportedProtocol(service->mProtocol), CHIP_ERROR_INVALID_ARGUMENT);
    VerifyOrReturnError(callback != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
    VerifyOrReturnError(strcmp(service->mHostName, "") != 0, CHIP_ERROR_INVALID_ARGUMENT);

    ScopedTXTRecord record;
    ReturnErrorOnFailure(record.Init(service->mTextEntries, service->mTextEntrySize));

    auto regtype     = GetFullTypeWithSubTypes(service);
    auto interfaceId = GetInterfaceId(service->mInterface);
    auto hostname    = GetHostNameWithDomain(service->mHostName);

    return Register(context, callback, interfaceId, regtype.c_str(), service->mName, service->mPort, record, service->mAddressType,
                    hostname.c_str());
}

CHIP_ERROR ChipDnssdRemoveServices()
{
    auto err = MdnsContexts::GetInstance().RemoveAllOfType(ContextType::Register);
    if (CHIP_ERROR_KEY_NOT_FOUND == err)
    {
        err = CHIP_NO_ERROR;
    }
    return err;
}

CHIP_ERROR ChipDnssdFinalizeServiceUpdate()
{
    return CHIP_NO_ERROR;
}

void ChipDNSServiceBrowseReply(DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interfaceIndex, DNSServiceErrorType errorCode,
                               const char * serviceName, const char * regtype, const char * replyDomain, void * context)
{
    DnssdBrowseCallback ChipBrowseHandler = (DnssdBrowseCallback) context;
    DnssdService service;

    ChipLogProgress(ServiceProvisioning, "ChipDNSServiceBrowseReply %s", StringOrNullMarker(serviceName));
    strcpy(service.mName, serviceName);

    ChipBrowseHandler(NULL, &service, 1, true, CHIP_NO_ERROR);
}

CHIP_ERROR ChipDnssdBrowse(const char * type, DnssdServiceProtocol protocol, chip::Inet::IPAddressType addressType,
                           chip::Inet::InterfaceId interface, DnssdBrowseCallback callback, void * context,
                           intptr_t * browseIdentifier)
{
    CHIP_ERROR error = CHIP_NO_ERROR;
    DNSServiceErrorType err;
    char ServiceType[kDnssdTypeMaxSize + 10] = { 0 };

    (void) addressType;
    ChipLogProgress(ServiceProvisioning, "ChipDnssdBrowse %s", StringOrNullMarker(type));
    strcpy(ServiceType, type);
    strcat(ServiceType, ".");
    strcat(ServiceType, GetProtocolString(protocol));
    err = DNSServiceBrowse(&BrowseClient, 0, 0, ServiceType, SERVICE_DOMAIN, ChipDNSServiceBrowseReply, (void *) callback);
    ChipLogProgress(ServiceProvisioning, "DNSServiceBrowse %d", (int) err);
    if (err)
    {
        error = CHIP_ERROR_INTERNAL;
    }
    else
    {
        *browseIdentifier = reinterpret_cast<intptr_t>(nullptr);
    }
    return error;
}

CHIP_ERROR ChipDnssdStopBrowse(intptr_t browseIdentifier)
{
    return CHIP_ERROR_NOT_IMPLEMENTED;
}

static void resolve_client_task(void * parameter)
{
    EventBits_t uxBits;
    struct timeval tv;
    int result;
    int fd;
    fd_set readfds;

    while (1)
    {
        int nfds = 0;
        FD_ZERO(&readfds);
        nfds = MdnsContexts::GetInstance().GetSelectFd(&readfds);

        if (nfds == 0)
        {
            uxBits = xEventGroupWaitBits(gResolveTaskWakeEvent, 1, pdTRUE, pdFALSE, portMAX_DELAY);
            continue;
        }

        tv.tv_sec  = 0;
        tv.tv_usec = 100000; // 100ms

        result = select(nfds + 1, &readfds, (fd_set *) NULL, (fd_set *) NULL, &tv);
        if (result > 0)
        {
            DNSServiceErrorType error = kDNSServiceErr_NoError;

            for (fd = 0; fd <= nfds; ++fd)
            {
                if (FD_ISSET(fd, &readfds))
                {
                    DNSServiceRef resolveClient = NULL;
                    void * context              = MdnsContexts::GetInstance().GetBySockFd(fd);
                    if (context)
                    {
                        auto sdCtx = reinterpret_cast<ResolveContext *>(context);
                        error      = DNSServiceProcessResult(sdCtx->serviceRef);
                        {
                            mdnslogInfo("DNSServiceProcessResult(%d) returned %d\n", fd, error);
                        }
                    } // if context
                }
            } // for
        }
        else
        {
            // remove timeout contexts
            for (fd = 0; fd <= nfds; ++fd)
            {
                GenericContext * context = MdnsContexts::GetInstance().GetBySockFd(fd);
                if (context && context->mSelectCount > 10)
                {
                    context->Finalize(kDNSServiceErr_Timeout);
                }
            }
        }
    } // while

    gResolveTask = NULL;
    vTaskDelete(NULL);
}

static void OnGetAddrInfo(DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interfaceId, DNSServiceErrorType err,
                          const char * hostname, const struct sockaddr * address, uint32_t ttl, void * context)
{
    ChipLogProgress(ServiceProvisioning, "DNSServiceGetAddrInfo: OnGetAddrInfo");

    auto sdCtx = reinterpret_cast<ResolveContext *>(context);
    ReturnOnFailure(MdnsContexts::GetInstance().Has(sdCtx));

    if (kDNSServiceErr_NoError == err)
    {
        sdCtx->OnNewAddress(interfaceId, address);
    }

    if (!(flags & kDNSServiceFlagsMoreComing))
    {
        VerifyOrReturn(sdCtx->HasAddress(), sdCtx->Finalize(kDNSServiceErr_BadState));
        sdCtx->Finalize();
    }
}

static void GetAddrInfo(ResolveContext * sdCtx)
{
    ChipLogProgress(ServiceProvisioning, "ChipDNSServiceResolveReply: GetAddrInfo");

    int dns_fd;
    auto protocol = sdCtx->protocol;

    for (auto & interface : sdCtx->interfaces)
    {
        DNSServiceRef resolveClient = NULL;
        auto interfaceId            = interface.first;
        auto hostname               = interface.second.fullyQualifiedDomainName.c_str();

        DNSServiceRefDeallocate(sdCtx->serviceRef);

        auto err          = DNSServiceGetAddrInfo(&resolveClient, 0, interfaceId, protocol, hostname, OnGetAddrInfo, sdCtx);
        sdCtx->serviceRef = resolveClient;
        VerifyOrReturn(kDNSServiceErr_NoError == err, sdCtx->Finalize(err));
    }
}

void ChipDNSServiceResolveReply(DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interfaceIndex, DNSServiceErrorType errorCode,
                                const char * fullname, const char * hosttarget, uint16_t port,
                                /* In network byte order */ uint16_t txtLen, const unsigned char * txtRecord, void * context)
{
    ChipLogProgress(ServiceProvisioning, "ChipDNSServiceResolveReply");
    if (context)
    {
        auto sdCtx = reinterpret_cast<ResolveContext *>(context);

        sdCtx->OnNewInterface(interfaceIndex, fullname, hosttarget, port, txtLen, txtRecord);
        if (kDNSServiceInterfaceIndexLocalOnly == interfaceIndex)
        {
            sdCtx->OnNewLocalOnlyAddress();
            sdCtx->Finalize();
            return;
        }
        if (!(flags & kDNSServiceFlagsMoreComing))
        {
            VerifyOrReturn(sdCtx->HasInterface(), sdCtx->Finalize(kDNSServiceErr_BadState));
            GetAddrInfo(sdCtx);
        }
    }
}

CHIP_ERROR ChipDnssdResolve(DnssdService * service, chip::Inet::InterfaceId interface, DnssdResolveCallback callback,
                            void * context)
{
    DNSServiceRef resolveClient = NULL;
    CHIP_ERROR error            = CHIP_NO_ERROR;
    DNSServiceErrorType err;
    char ServiceType[kDnssdTypeMaxSize + 10] = { 0 };
    int dns_fd;
    uint32_t interfaceIndex = GetInterfaceId(interface);

    ChipLogProgress(ServiceProvisioning, "ChipDnssdResolve %s", service->mName);
    strcpy(ServiceType, service->mType);
    strcat(ServiceType, ".");
    strcat(ServiceType, GetProtocolString(service->mProtocol));

    auto sdCtx = chip::Platform::New<ResolveContext>(context, callback, service->mAddressType);
    VerifyOrReturnError(nullptr != sdCtx, CHIP_ERROR_NO_MEMORY);

    err = DNSServiceResolve(&resolveClient, 0, interfaceIndex, service->mName, ServiceType, SERVICE_DOMAIN,
                            ChipDNSServiceResolveReply, sdCtx);
    ChipLogProgress(ServiceProvisioning, "DNSServiceResolve %d", (int) err);
    if (err)
    {
        return CHIP_ERROR_INTERNAL;
    }

    sdCtx->serviceRef = resolveClient;
    error             = MdnsContexts::GetInstance().Add(sdCtx, sdCtx->serviceRef);
    if (error == CHIP_NO_ERROR)
    {
        if (gResolveTask == NULL)
        {
            gResolveTaskWakeEvent = xEventGroupCreate();
            if (gResolveTaskWakeEvent == NULL)
            {
                ChipLogProgress(ServiceProvisioning, "Cannot create resolve_task event group");
                return CHIP_ERROR_INTERNAL;
            }

            if (pdPASS !=
                xTaskCreate(resolve_client_task, "mdnsr", (15 * 1024) / sizeof(portSTACK_TYPE), (void *) service,
                            TASK_PRIORITY_NORMAL, &gResolveTask))
            {
                ChipLogProgress(ServiceProvisioning, "Cannot create resolve_task");
                return CHIP_ERROR_INTERNAL;
            }
        }
        else
        {
            // wake up task
            xEventGroupSetBits(gResolveTaskWakeEvent, 1);
        }
    }

    return error;
}

void ChipDnssdResolveNoLongerNeeded(const char * instanceName) {}

CHIP_ERROR ChipDnssdReconfirmRecord(const char * hostname, chip::Inet::IPAddress address, chip::Inet::InterfaceId interface)
{
    return CHIP_ERROR_NOT_IMPLEMENTED;
}

} // namespace Dnssd
} // namespace chip
