/*
 *
 *    Copyright (c) 2020 Project CHIP Authors
 *    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 process to effect a functional test for
 *      LwIP's Domain Name Service (DNS) interface.
 *
 */

#include <inet/InetConfig.h>

#include <stdint.h>
#include <string.h>

#include <sys/time.h>

#if INET_LWIP
#include <lwip/dns.h>
#include <lwip/ip_addr.h>
#endif // INET_LWIP

#include <CHIPVersion.h>

#include <inet/InetArgParser.h>
#include <inet/InetLayer.h>

#include "TestInetCommon.h"
#include "TestInetCommonOptions.h"
#include "TestSetupFaultInjection.h"
#include "TestSetupSignalling.h"

using namespace chip;
using namespace chip::Inet;

#define TOOL_NAME "TestLwIPDNS"

static bool HandleNonOptionArgs(const char * progName, int argc, char * argv[]);

// Globals

#if INET_LWIP
static uint8_t sNumIpAddrs = DNS_MAX_ADDRS_PER_NAME;
static ip_addr_t sIpAddrs[DNS_MAX_ADDRS_PER_NAME];
#endif // INET_LWIP

static const char * sHostname      = nullptr;
static const char * sDNSServerAddr = nullptr;

// clang-format off
static ArgParser::HelpOptions gHelpOptions(TOOL_NAME,
                                           "Usage: " TOOL_NAME " [<options...>] <hostname> <dns-server-address>\n",
                                           CHIP_VERSION_STRING "\n" CHIP_TOOL_COPYRIGHT);

static ArgParser::OptionSet * gToolOptionSets[] =
{
    &gNetworkOptions,
    &gFaultInjectionOptions,
    &gHelpOptions,
    nullptr
};
// clang-format on

#if INET_LWIP
static void found_multi(const char * aName, ip_addr_t * aIpAddrs, uint8_t aNumIpAddrs, void * callback_arg)
{
    printf("\tfound_multi response\n");
    printf("\tName: %s\n", aName);
    printf("\tnumipaddrs: %d (DNS_MAX_ADDRS_PER_NAME: %d)\n", aNumIpAddrs, DNS_MAX_ADDRS_PER_NAME);

    for (uint8_t i = 0; i < aNumIpAddrs; ++i)
    {
        char addrStr[INET6_ADDRSTRLEN];

        IPAddress(aIpAddrs[i]).ToString(addrStr, sizeof(addrStr));

        printf("\t(%d) IPv4: %s\n", i, addrStr);
    }

    Done = true;
}

static void TestLwIPDNS(void)
{
    uint8_t numdns = 1;
    ip_addr_t dnsserver[1];
    IPAddress DNSServerIPv4Addr;

    IPAddress::FromString(sDNSServerAddr, DNSServerIPv4Addr);

    dnsserver[0] = DNSServerIPv4Addr.ToIPv4();

    dns_setserver(numdns, dnsserver);

    printf("\nStarted dns_gethostbyname_multi test...\n\n");

    // Expected request / response
    printf("Expected request / response #1\n");
    printf("hn: %s, ips: %p, nips: %d, fm: %p, arg: %p\n", hostname, sIpAddrs, sNumIpAddrs, found_multi, NULL);
    printf("ip[0]: %d, ip[1]: %d\n", sIpAddrs[0], sIpAddrs[1]);
    err_t res = dns_gethostbyname_multi(hostname, sIpAddrs, &sNumIpAddrs, found_multi, NULL);
    if (res == ERR_INPROGRESS)
    {
        printf("\tdns_gethostbyname_multi: %d (ERR_INPROGRESS)\n", res);
    }
    else
    {
        printf("\tdns_gethostbyname_multi: %d (expected -5: ERR_INPROGRESS)\n", res);
    }

    while (!Done)
    {
        constexpr uint32_t kSleepTimeMilliseconds = 10;
        ServiceNetwork(kSleepTimeMilliseconds);
    }

    // Expected cached response
    printf("Expected cached response #1\n");
    sNumIpAddrs = DNS_MAX_ADDRS_PER_NAME;
    printf("hn: %s, ips: %p, nips: %d, fm: %p, arg: %p\n", hostname, ipaddrs, sNumIpAddrs, found_multi, NULL);
    printf("ip[0]: %d, ip[1]: %d\n", sIpAddrs[0], sIpAddrs[1]);
    res = dns_gethostbyname_multi(hostname, ipaddrs, &sNumIpAddrs, found_multi, NULL);
    if (res == ERR_OK)
    {
        printf("\tdns_gethostbyname_multi: %d (ERR_OK)\n", res);
        printf("\tlocal DNS cache response\n");
        printf("\tName: %s\n", hostname);
        printf("\tnumipaddrs: %d\n", sNumIpAddrs);
        for (uint8_t i = 0; i < sNumIpAddrs; ++i)
        {
            char addrStr[64];
            IPAddress(sIpAddrs[i]).ToString(addrStr, sizeof(addrStr));
            printf("\t(%d) IPv4: %s\n", i, addrStr);
        }
    }
    else
    {
        printf("\tdns_gethostbyname_multi: %d (expected : ERR_OK)\n", res);
    }

    // Expected cached response
    printf("Expected cached response #2\n");
    sNumIpAddrs = DNS_MAX_ADDRS_PER_NAME - 1;
    printf("hn: %s, ips: %p, nips: %d, fm: %p, arg: %p\n", hostname, ipaddrs, sNumIpAddrs, found_multi, NULL);
    printf("ip[0]: %d, ip[1]: %d\n", sIpAddrs[0], sIpAddrs[1]);

    res = dns_gethostbyname_multi(hostname, sIpAddrs, &sNumIpAddrs, found_multi, NULL);

    if (res == ERR_OK)
    {
        printf("\tdns_gethostbyname_multi: %d (ERR_OK)\n", res);
        printf("\tlocal DNS cache response\n");
        printf("\tName: %s\n", hostname);
        printf("\tnumipaddrs: %d\n", sNumIpAddrs);
        for (i = 0; i < sNumIpAddrs; ++i)
        {
            char addrStr[64];
            IPAddress(sIpAddrs[i]).ToString(addrStr, sizeof(addrStr));
            printf("\t(%d) IPv4: %s\n", i, addrStr);
        }
    }
    else
    {
        printf("\tdns_gethostbyname_multi: %d (expected : ERR_OK)\n", res);
    }

    // Expected cached response
    printf("Expected cached response #3\n");
    sNumIpAddrs = 0;
    printf("hn: %s, ips: %p, nips: %d, fm: %p, arg: %p\n", hostname, ipaddrs, sNumIpAddrs, found_multi, NULL);
    printf("ip[0]: %d, ip[1]: %d\n", sIpAddrs[0], sIpAddrs[1]);

    res = dns_gethostbyname_multi(hostname, ipaddrs, &sNumIpAddrs, found_multi, NULL);

    if (res == ERR_OK)
    {
        printf("\tdns_gethostbyname_multi: %d (ERR_OK)\n", res);
        printf("\tlocal DNS cache response\n");
        printf("\tName: %s\n", hostname);
        printf("\tnumipaddrs: %d\n", sNumIpAddrs);
        for (i = 0; i < sNumIpAddrs; ++i)
        {
            char addrStr[64];
            IPAddress(sIpAddrs[i]).ToString(addrStr, sizeof(addrStr));
            printf("\t(%d) IPv4: %s\n", i, addrStr);
        }
    }
    else
    {
        printf("\tdns_gethostbyname_multi: %d (expected : ERR_OK)\n", res);
    }
}
#endif // INET_LWIP

int main(int argc, char * argv[])
{
    SetSIGUSR1Handler();

    if (argc == 1)
    {
        gHelpOptions.PrintBriefUsage(stderr);
        exit(EXIT_FAILURE);
    }

    if (!ParseArgs(TOOL_NAME, argc, argv, gToolOptionSets, HandleNonOptionArgs))
    {
        exit(EXIT_FAILURE);
    }

    InitSystemLayer();

    InitNetwork();

#if INET_LWIP
    TestLwIPDNS();
#else
    fprintf(stderr, "Please assert INET_LWIP to use this test.\n");
#endif // INET_LWIP

    ShutdownNetwork();

    ShutdownSystemLayer();

    return (EXIT_SUCCESS);
}

static bool HandleNonOptionArgs(const char * progName, int argc, char * argv[])
{
    if (argc < 2)
    {
        printf("TestDNS: Missing %s argument\n", argc == 0 ? "<hostname>" : "<dns-server-address>");
        return false;
    }

    if (argc > 2)
    {
        printf("Unexpected argument: %s\n", argv[1]);
    }

    sHostname      = argv[0];
    sDNSServerAddr = argv[1];

    return true;
}
