/*
 *
 *    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/InetLayer.h>

#include "TestInetCommon.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::FromIPv4(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)
    {
        struct timeval sleepTime;
        sleepTime.tv_sec  = 0;
        sleepTime.tv_usec = 10000;

        ServiceNetwork(sleepTime);
    }

    // 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::FromIPv4(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::FromIPv4(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::FromIPv4(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;
}
