#include <condition_variable>
#include <mutex>
#include <thread>

#include <nlunit-test.h>

#include "lib/dnssd/platform/Dnssd.h"
#include "platform/CHIPDeviceLayer.h"
#include "platform/PlatformManager.h"
#include <lib/support/CHIPMem.h>
#include <lib/support/UnitTestRegistration.h>

using chip::Dnssd::DnssdService;
using chip::Dnssd::DnssdServiceProtocol;
using chip::Dnssd::TextEntry;

static unsigned int gBrowsedServicesCount  = 0;
static unsigned int gResolvedServicesCount = 0;
static bool gEndOfInput                    = false;

static void HandleResolve(void * context, DnssdService * result, const chip::Span<chip::Inet::IPAddress> & addresses,
                          CHIP_ERROR error)
{
    char addrBuf[100];
    nlTestSuite * suite = static_cast<nlTestSuite *>(context);

    NL_TEST_ASSERT(suite, result != nullptr);
    NL_TEST_ASSERT(suite, error == CHIP_NO_ERROR);

    if (!addresses.empty())
    {
        addresses.data()[0].ToString(addrBuf, sizeof(addrBuf));
        printf("Service[%u] at [%s]:%u\n", gResolvedServicesCount, addrBuf, result->mPort);
    }

    NL_TEST_ASSERT(suite, result->mTextEntrySize == 1);
    NL_TEST_ASSERT(suite, strcmp(result->mTextEntries[0].mKey, "key") == 0);
    NL_TEST_ASSERT(suite, strcmp(reinterpret_cast<const char *>(result->mTextEntries[0].mData), "val") == 0);

    if (gBrowsedServicesCount == ++gResolvedServicesCount)
    {
        chip::DeviceLayer::PlatformMgr().StopEventLoopTask();
        chip::DeviceLayer::PlatformMgr().Shutdown();
        exit(0);
    }
}

static void HandleBrowse(void * context, DnssdService * services, size_t servicesSize, bool finalBrowse, CHIP_ERROR error)
{
    nlTestSuite * suite = static_cast<nlTestSuite *>(context);

    // Make sure that we will not be called again after end-of-input is set
    NL_TEST_ASSERT(suite, gEndOfInput == false);
    NL_TEST_ASSERT(suite, error == CHIP_NO_ERROR);

    gBrowsedServicesCount += servicesSize;
    gEndOfInput = finalBrowse;

    if (servicesSize > 0)
    {
        printf("Browse mDNS service size %u\n", static_cast<unsigned int>(servicesSize));
        for (unsigned int i = 0; i < servicesSize; i++)
        {
            printf("Service[%u] name %s\n", i, services[i].mName);
            printf("Service[%u] type %s\n", i, services[i].mType);
            NL_TEST_ASSERT(suite, ChipDnssdResolve(&services[i], services[i].mInterface, HandleResolve, suite) == CHIP_NO_ERROR);
        }
    }
}

static void HandlePublish(void * context, const char * type, const char * instanceName, CHIP_ERROR error) {}

static void InitCallback(void * context, CHIP_ERROR error)
{
    DnssdService service;
    TextEntry entry;
    char key[]          = "key";
    char val[]          = "val";
    nlTestSuite * suite = static_cast<nlTestSuite *>(context);

    NL_TEST_ASSERT(suite, error == CHIP_NO_ERROR);

    service.mInterface = chip::Inet::InterfaceId::Null();
    service.mPort      = 80;
    strcpy(service.mHostName, "MatterTest");
    strcpy(service.mName, "test");
    strcpy(service.mType, "_mock");
    service.mAddressType   = chip::Inet::IPAddressType::kAny;
    service.mProtocol      = DnssdServiceProtocol::kDnssdProtocolTcp;
    entry.mKey             = key;
    entry.mData            = reinterpret_cast<const uint8_t *>(val);
    entry.mDataSize        = strlen(reinterpret_cast<const char *>(entry.mData));
    service.mTextEntries   = &entry;
    service.mTextEntrySize = 1;
    service.mSubTypes      = nullptr;
    service.mSubTypeSize   = 0;

    NL_TEST_ASSERT(suite, ChipDnssdPublishService(&service, HandlePublish) == CHIP_NO_ERROR);
    intptr_t browseIdentifier;
    ChipDnssdBrowse("_mock", DnssdServiceProtocol::kDnssdProtocolTcp, chip::Inet::IPAddressType::kAny,
                    chip::Inet::InterfaceId::Null(), HandleBrowse, suite, &browseIdentifier);
}

static void ErrorCallback(void * context, CHIP_ERROR error)
{
    VerifyOrDieWithMsg(error == CHIP_NO_ERROR, DeviceLayer, "Mdns error: %" CHIP_ERROR_FORMAT "\n", error.Format());
}

void TestDnssdPubSub(nlTestSuite * inSuite, void * inContext)
{
    chip::Platform::MemoryInit();
    chip::DeviceLayer::PlatformMgr().InitChipStack();
    NL_TEST_ASSERT(inSuite, chip::Dnssd::ChipDnssdInit(InitCallback, ErrorCallback, inSuite) == CHIP_NO_ERROR);

    ChipLogProgress(DeviceLayer, "Start EventLoop");
    chip::DeviceLayer::PlatformMgr().RunEventLoop();
    ChipLogProgress(DeviceLayer, "End EventLoop");
}

static const nlTest sTests[] = { NL_TEST_DEF("Test Dnssd::PubSub", TestDnssdPubSub), NL_TEST_SENTINEL() };

int TestDnssd()
{
    std::mutex mtx;

    std::condition_variable readyCondition;
    bool ready = false;

    std::condition_variable doneCondition;
    bool done     = false;
    bool shutdown = false;

    int retVal = EXIT_FAILURE;

    std::thread t([&]() {
        {
            std::lock_guard<std::mutex> lock(mtx);
            ready = true;
            readyCondition.notify_one();
        }

        nlTestSuite theSuite = { "CHIP DeviceLayer mdns tests", &sTests[0], nullptr, nullptr };

        nlTestRunner(&theSuite, nullptr);
        retVal = nlTestRunnerStats(&theSuite);

        {
            std::lock_guard<std::mutex> lock(mtx);
            done = true;
            doneCondition.notify_all();
        }
    });

    {
        std::unique_lock<std::mutex> lock(mtx);
        readyCondition.wait(lock, [&] { return ready; });

        doneCondition.wait_for(lock, std::chrono::seconds(5));
        if (!done)
        {
            fprintf(stderr, "mDNS test timeout, is avahi daemon running?\n");

            //
            // This will stop the event loop above, and wait till it has actually stopped
            // (i.e exited RunEventLoop()).
            //
            chip::Dnssd::ChipDnssdShutdown();
            chip::DeviceLayer::PlatformMgr().StopEventLoopTask();
            chip::DeviceLayer::PlatformMgr().Shutdown();
            shutdown = true;

            doneCondition.wait_for(lock, std::chrono::seconds(1));
            if (!done)
            {
                fprintf(stderr, "Orderly shutdown of the platform main loop failed as well.\n");
            }
            retVal = EXIT_FAILURE;
        }
    }
    t.join();

    if (!shutdown)
    {
        chip::Dnssd::ChipDnssdShutdown();
        chip::DeviceLayer::PlatformMgr().StopEventLoopTask();
        chip::DeviceLayer::PlatformMgr().Shutdown();
    }
    chip::Platform::MemoryShutdown();

    return retVal;
}

CHIP_REGISTER_TEST_SUITE(TestDnssd);
