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