/*
 *
 *    Copyright (c) 2020-2021 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 <cstdio>
#include <memory>
#include <string>
#include <vector>

#include <TracingCommandLineArgument.h>
#include <inet/InetInterface.h>
#include <inet/UDPEndPoint.h>
#include <lib/dnssd/MinimalMdnsServer.h>
#include <lib/dnssd/minimal_mdns/AddressPolicy.h>
#include <lib/dnssd/minimal_mdns/QueryBuilder.h>
#include <lib/dnssd/minimal_mdns/Server.h>
#include <lib/dnssd/minimal_mdns/core/QName.h>
#include <lib/support/CHIPArgParser.hpp>
#include <lib/support/CHIPMem.h>
#include <platform/CHIPDeviceLayer.h>
#include <system/SystemPacketBuffer.h>

#include "PacketReporter.h"

using namespace chip;

namespace {

struct Options
{
    bool unicastAnswers       = true;
    uint32_t runtimeMs        = 500;
    uint16_t querySendPort    = 5353;
    uint16_t listenPort       = 5388;
    const char * query        = "_services._dns-sd._udp.local";
    mdns::Minimal::QType type = mdns::Minimal::QType::ANY;
} gOptions;

constexpr uint32_t kTestMessageId   = 0;
constexpr size_t kMdnsMaxPacketSize = 1'024;

using namespace chip::ArgParser;

constexpr uint16_t kOptionQuery = 'q';
constexpr uint16_t kOptionType  = 't';

// non-ascii options have no short option version
constexpr uint16_t kOptionListenPort       = 0x100;
constexpr uint16_t kOptionQueryPort        = 0x101;
constexpr uint16_t kOptionRuntimeMs        = 0x102;
constexpr uint16_t kOptionMulticastReplies = 0x103;
constexpr uint16_t kOptionTraceTo          = 0x104;

// Only used for argument parsing. Tracing setup owned by the main loop.
chip::CommandLineApp::TracingSetup * tracing_setup_for_argparse = nullptr;

bool HandleOptions(const char * aProgram, OptionSet * aOptions, int aIdentifier, const char * aName, const char * aValue)
{
    switch (aIdentifier)
    {
    case kOptionListenPort:
        if (!ParseInt(aValue, gOptions.listenPort))
        {
            PrintArgError("%s: invalid value for listen port: %s\n", aProgram, aValue);
            return false;
        }
        return true;
    case kOptionQuery:
        gOptions.query = aValue;
        return true;
    case kOptionTraceTo:
        tracing_setup_for_argparse->EnableTracingFor(aValue);
        return true;
    case kOptionType:
        if (strcasecmp(aValue, "ANY") == 0)
        {
            gOptions.type = mdns::Minimal::QType::ANY;
        }
        else if (strcasecmp(aValue, "A") == 0)
        {
            gOptions.type = mdns::Minimal::QType::A;
        }
        else if (strcasecmp(aValue, "AAAA") == 0)
        {
            gOptions.type = mdns::Minimal::QType::AAAA;
        }
        else if (strcasecmp(aValue, "PTR") == 0)
        {
            gOptions.type = mdns::Minimal::QType::PTR;
        }
        else if (strcasecmp(aValue, "TXT") == 0)
        {
            gOptions.type = mdns::Minimal::QType::TXT;
        }
        else if (strcasecmp(aValue, "SRV") == 0)
        {
            gOptions.type = mdns::Minimal::QType::SRV;
        }
        else if (strcasecmp(aValue, "CNAME") == 0)
        {
            gOptions.type = mdns::Minimal::QType::CNAME;
        }
        else
        {
            PrintArgError("%s: invalid value for query type: %s\n", aProgram, aValue);
            return false;
        }
        return true;

    case kOptionQueryPort:
        if (!ParseInt(aValue, gOptions.querySendPort))
        {
            PrintArgError("%s: invalid value for query send port: %s\n", aProgram, aValue);
            return false;
        }
        return true;

    case kOptionRuntimeMs:
        if (!ParseInt(aValue, gOptions.runtimeMs))
        {
            PrintArgError("%s: invalid value for runtime ms: %s\n", aProgram, aValue);
            return false;
        }
        return true;

    case kOptionMulticastReplies:
        gOptions.unicastAnswers = false;
        return true;

    default:
        PrintArgError("%s: INTERNAL ERROR: Unhandled option: %s\n", aProgram, aName);
        return false;
    }
}

OptionDef cmdLineOptionsDef[] = {
    { "listen-port", kArgumentRequired, kOptionListenPort },
    { "query", kArgumentRequired, kOptionQuery },
    { "type", kArgumentRequired, kOptionType },
    { "query-port", kArgumentRequired, kOptionQueryPort },
    { "timeout-ms", kArgumentRequired, kOptionRuntimeMs },
    { "multicast-reply", kNoArgument, kOptionMulticastReplies },
    { "trace-to", kArgumentRequired, kOptionTraceTo },
    {},
};

OptionSet cmdLineOptions = { HandleOptions, cmdLineOptionsDef, "PROGRAM OPTIONS",
                             "  --listen-port <number>\n"
                             "        The port number to listen on\n"
                             "  -q\n"
                             "  --query\n"
                             "        The query to send\n"
                             "  -t\n"
                             "  --type\n"
                             "        The query type to ask for (ANY/PTR/A/AAAA/SRV/TXT)\n"
                             "  --query-port\n"
                             "        On what port to multicast the query\n"
                             "  --timeout-ms\n"
                             "        How long to wait for replies\n"
                             "  --multicast-reply\n"
                             "        Do not request unicast replies\n"
                             "  --trace-to <dest>\n"
                             "        trace to the given destination (supported: " SUPPORTED_COMMAND_LINE_TRACING_TARGETS ").\n"
                             "\n" };

HelpOptions helpOptions("minimal-mdns-client", "Usage: minimal-mdns-client [options]", "1.0");

OptionSet * allOptions[] = { &cmdLineOptions, &helpOptions, nullptr };

class ReportDelegate : public mdns::Minimal::ServerDelegate
{
public:
    void OnQuery(const mdns::Minimal::BytesRange & data, const chip::Inet::IPPacketInfo * info) override
    {
        char addr[32];
        info->SrcAddress.ToString(addr, sizeof(addr));

        char ifName[64];
        VerifyOrDie(info->Interface.GetInterfaceName(ifName, sizeof(ifName)) == CHIP_NO_ERROR);

        printf("QUERY from: %-15s on port %d, via interface %s\n", addr, info->SrcPort, ifName);
        Report("QUERY: ", data);
    }

    void OnResponse(const mdns::Minimal::BytesRange & data, const chip::Inet::IPPacketInfo * info) override
    {
        char addr[32];
        info->SrcAddress.ToString(addr, sizeof(addr));

        char ifName[64];
        VerifyOrDie(info->Interface.GetInterfaceName(ifName, sizeof(ifName)) == CHIP_NO_ERROR);

        printf("RESPONSE from: %-15s on port %d, via interface %s\n", addr, info->SrcPort, ifName);
        Report("RESPONSE: ", data);
    }

private:
    void Report(const char * prefix, const mdns::Minimal::BytesRange & data)
    {
        MdnsExample::PacketReporter reporter(prefix, data);
        if (!mdns::Minimal::ParsePacket(data, &reporter))
        {
            printf("INVALID PACKET!!!!!!\n");
        }
    }
};

class QuerySplitter
{
public:
    void Split(const char * query)
    {
        mStorage.clear();
        mParts.clear();

        const char * dot = nullptr;
        while (nullptr != (dot = strchr(query, '.')))
        {
            mStorage.push_back(std::string(query, dot));
            query = dot + 1;
        }

        mStorage.push_back(query);

        for (unsigned i = 0; i < mStorage.size(); i++)
        {
            mParts.push_back(mStorage[i].c_str());
        }
    }

    mdns::Minimal::Query MdnsQuery() const
    {
        mdns::Minimal::FullQName qName;

        qName.nameCount = mParts.size();
        qName.names     = mParts.data();

        return mdns::Minimal::Query(qName);
    }

private:
    std::vector<mdns::Minimal::QNamePart> mParts;
    std::vector<std::string> mStorage;
};

void BroadcastPacket(mdns::Minimal::ServerBase * server)
{
    System::PacketBufferHandle buffer = System::PacketBufferHandle::New(kMdnsMaxPacketSize);
    VerifyOrDie(!buffer.IsNull());

    QuerySplitter query;
    query.Split(gOptions.query);

    mdns::Minimal::QueryBuilder builder(std::move(buffer));

    builder.Header().SetMessageId(kTestMessageId);
    builder.AddQuery(query
                         .MdnsQuery()                                  //
                         .SetClass(mdns::Minimal::QClass::IN)          //
                         .SetType(gOptions.type)                       //
                         .SetAnswerViaUnicast(gOptions.unicastAnswers) //
    );

    if (!builder.Ok())
    {
        printf("Failed to build the question");
        return;
    }

    if (gOptions.unicastAnswers)
    {
        if (server->BroadcastUnicastQuery(builder.ReleasePacket(), gOptions.querySendPort) != CHIP_NO_ERROR)
        {
            printf("Error sending\n");
            return;
        }
    }
    else
    {
        if (server->BroadcastSend(builder.ReleasePacket(), gOptions.querySendPort) != CHIP_NO_ERROR)
        {
            printf("Error sending\n");
            return;
        }
    }
}

mdns::Minimal::Server<20> gMdnsServer;

} // namespace

int main(int argc, char ** args)
{
    if (Platform::MemoryInit() != CHIP_NO_ERROR)
    {
        printf("FAILED to initialize memory");
        return 1;
    }

    if (DeviceLayer::PlatformMgr().InitChipStack() != CHIP_NO_ERROR)
    {
        printf("FAILED to initialize chip stack");
        return 1;
    }

    chip::CommandLineApp::TracingSetup tracing_setup;

    tracing_setup_for_argparse = &tracing_setup;
    if (!chip::ArgParser::ParseArgs(args[0], argc, args, allOptions))
    {
        return 1;
    }
    tracing_setup_for_argparse = nullptr;

    printf("Running...\n");

    ReportDelegate reporter;
    CHIP_ERROR err;

    // This forces the global MDNS instance to be loaded in, effectively setting
    // built in policies for addresses.
    (void) chip::Dnssd::GlobalMinimalMdnsServer::Instance();

    gMdnsServer.SetDelegate(&reporter);

    {
        auto endpoints = mdns::Minimal::GetAddressPolicy()->GetListenEndpoints();

        err = gMdnsServer.Listen(chip::DeviceLayer::UDPEndPointManager(), endpoints.get(), gOptions.listenPort);
        if (err != CHIP_NO_ERROR)
        {
            printf("Server failed to listen on all interfaces: %s\n", chip::ErrorStr(err));
            return 1;
        }
    }

    BroadcastPacket(&gMdnsServer);

    err = DeviceLayer::SystemLayer().StartTimer(
        chip::System::Clock::Milliseconds32(gOptions.runtimeMs),
        [](System::Layer *, void *) {
            // Close all sockets BEFORE system layer is shut down, otherwise
            // attempts to free UDP sockets with system layer down will segfault
            gMdnsServer.Shutdown();

            DeviceLayer::PlatformMgr().StopEventLoopTask();
        },
        nullptr);
    if (err != CHIP_NO_ERROR)
    {
        printf("Failed to create the shutdown timer. Kill with ^C. %" CHIP_ERROR_FORMAT "\n", err.Format());
    }

    DeviceLayer::PlatformMgr().RunEventLoop();

    tracing_setup.StopTracing();
    DeviceLayer::PlatformMgr().Shutdown();
    Platform::MemoryShutdown();

    printf("Done...\n");
    return 0;
}
