/*
 *
 *    Copyright (c) 2021 Project CHIP Authors
 *    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.
 */

#include <lib/dnssd/IncrementalResolve.h>

#include <string.h>

#include <lib/dnssd/minimal_mdns/core/tests/QNameStrings.h>
#include <lib/dnssd/minimal_mdns/records/IP.h>
#include <lib/dnssd/minimal_mdns/records/Ptr.h>
#include <lib/dnssd/minimal_mdns/records/ResourceRecord.h>
#include <lib/dnssd/minimal_mdns/records/Srv.h>
#include <lib/dnssd/minimal_mdns/records/Txt.h>
#include <lib/support/ScopedBuffer.h>

#include <gtest/gtest.h>

using namespace chip;
using namespace chip::Dnssd;
using namespace mdns::Minimal;

namespace {

// Operational names must be <compressed-fabric>-<node>._matter._tcp.local
const auto kTestOperationalName = testing::TestQName<4>({ "1234567898765432-ABCDEFEDCBAABCDE", "_matter", "_tcp", "local" });

// Commissionable names must be <instance>._matterc._udp.local
const auto kTestCommissionableNode = testing::TestQName<4>({ "C5038835313B8B98", "_matterc", "_udp", "local" });

// Commissioner names must be <instance>._matterd._udp.local
const auto kTestCommissionerNode = testing::TestQName<4>({ "C5038835313B8B98", "_matterd", "_udp", "local" });

// Server name that is preloaded by the `PreloadSrvRecord`
const auto kTestHostName = testing::TestQName<2>({ "abcd", "local" });

const auto kIrrelevantHostName = testing::TestQName<2>({ "different", "local" });

void PreloadSrvRecord(SrvRecord & record)
{
    uint8_t headerBuffer[HeaderRef::kSizeBytes] = {};
    HeaderRef dummyHeader(headerBuffer);

    // NOTE: record pointers persist beyond  this function, so
    // this data MUST be static
    static uint8_t dataBuffer[256];
    chip::Encoding::BigEndian::BufferWriter output(dataBuffer, sizeof(dataBuffer));
    RecordWriter writer(&output);

    EXPECT_TRUE(SrvResourceRecord(kTestOperationalName.Full(), kTestHostName.Full(), 0x1234 /* port */)
                    .Append(dummyHeader, ResourceType::kAnswer, writer));

    ResourceData resource;
    BytesRange packet(dataBuffer, dataBuffer + sizeof(dataBuffer));
    const uint8_t * _ptr = dataBuffer;

    EXPECT_TRUE(resource.Parse(packet, &_ptr));
    EXPECT_TRUE(record.Parse(resource.GetData(), packet));
}

/// Convenience method to have a  serialized QName.
/// Assumes valid QName data that is terminated by null.
template <size_t N>
static SerializedQNameIterator AsSerializedQName(const uint8_t (&v)[N])
{
    // NOTE: the -1 is because we format these items as STRINGS and that
    // appends an extra NULL terminator
    return SerializedQNameIterator(BytesRange(v, v + N - 1), v);
}

void CallOnRecord(IncrementalResolver & resolver, const ResourceRecord & record)
{
    uint8_t headerBuffer[HeaderRef::kSizeBytes] = {};
    HeaderRef dummyHeader(headerBuffer);

    uint8_t dataBuffer[256];
    chip::Encoding::BigEndian::BufferWriter output(dataBuffer, sizeof(dataBuffer));
    RecordWriter writer(&output);

    EXPECT_TRUE(record.Append(dummyHeader, ResourceType::kAnswer, writer));
    EXPECT_TRUE(writer.Fit());

    ResourceData resource;
    BytesRange packet(dataBuffer, dataBuffer + sizeof(dataBuffer));
    const uint8_t * _ptr = dataBuffer;
    EXPECT_TRUE(resource.Parse(packet, &_ptr));
    EXPECT_EQ(resolver.OnRecord(chip::Inet::InterfaceId::Null(), resource, packet), CHIP_NO_ERROR);
}

TEST(TestIncrementalResolve, TestStoredServerName)
{

    StoredServerName name;

    // name should start of as cleared
    EXPECT_FALSE(name.Get().Next());

    // Data should be storable in server name
    EXPECT_EQ(name.Set(kTestOperationalName.Serialized()), CHIP_NO_ERROR);
    EXPECT_EQ(name.Get(), kTestOperationalName.Serialized());
    EXPECT_NE(name.Get(), kTestCommissionerNode.Serialized());
    EXPECT_NE(name.Get(), kTestCommissionableNode.Serialized());

    EXPECT_EQ(name.Set(kTestCommissionerNode.Serialized()), CHIP_NO_ERROR);
    EXPECT_NE(name.Get(), kTestOperationalName.Serialized());
    EXPECT_EQ(name.Get(), kTestCommissionerNode.Serialized());
    EXPECT_NE(name.Get(), kTestCommissionableNode.Serialized());

    EXPECT_EQ(name.Set(kTestCommissionableNode.Serialized()), CHIP_NO_ERROR);
    EXPECT_NE(name.Get(), kTestOperationalName.Serialized());
    EXPECT_NE(name.Get(), kTestCommissionerNode.Serialized());
    EXPECT_EQ(name.Get(), kTestCommissionableNode.Serialized());

    {
        // setting to a too long value should reset it
        uint8_t largeBuffer[256];
        memset(largeBuffer, 0, sizeof(largeBuffer));

        Encoding::BigEndian::BufferWriter writer(largeBuffer, sizeof(largeBuffer));

        for (unsigned idx = 0; true; idx++)
        {
            writer.Put("\07abcd123"); // will not NULL-terminate, but buffer is 0-filled
            if (!writer.Fit())
            {
                break; // filled all our tests
            }

            if (writer.WritePos() < 64)
            {
                // this is how much data can be fit by the copy
                EXPECT_EQ(name.Set(AsSerializedQName(largeBuffer)), CHIP_NO_ERROR) << "idx = " << idx;
                EXPECT_EQ(name.Get(), AsSerializedQName(largeBuffer)) << "idx = " << idx;
                EXPECT_NE(name.Get(), kTestOperationalName.Serialized()) << "idx = " << idx;
            }
            else
            {
                EXPECT_EQ(name.Set(AsSerializedQName(largeBuffer)), CHIP_ERROR_NO_MEMORY) << "idx = " << idx;
                EXPECT_FALSE(name.Get().Next()) << "idx = " << idx;
            }
        }
    }
}

TEST(TestIncrementalResolve, TestCreation)
{
    IncrementalResolver resolver;

    EXPECT_FALSE(resolver.IsActive());
    EXPECT_FALSE(resolver.IsActiveBrowseParse());
    EXPECT_FALSE(resolver.IsActiveOperationalParse());
    EXPECT_TRUE(
        resolver.GetMissingRequiredInformation().HasOnly(IncrementalResolver::RequiredInformationBitFlags::kSrvInitialization));
}

TEST(TestIncrementalResolve, TestInactiveResetOnInitError)
{
    IncrementalResolver resolver;

    EXPECT_FALSE(resolver.IsActive());

    SrvRecord srvRecord;
    PreloadSrvRecord(srvRecord);

    // test host name is not a 'matter' name
    EXPECT_NE(resolver.InitializeParsing(kTestHostName.Serialized(), srvRecord), CHIP_NO_ERROR);

    EXPECT_FALSE(resolver.IsActive());
    EXPECT_FALSE(resolver.IsActiveBrowseParse());
    EXPECT_FALSE(resolver.IsActiveOperationalParse());
}

TEST(TestIncrementalResolve, TestStartOperational)
{
    IncrementalResolver resolver;

    EXPECT_FALSE(resolver.IsActive());

    SrvRecord srvRecord;
    PreloadSrvRecord(srvRecord);

    EXPECT_EQ(resolver.InitializeParsing(kTestOperationalName.Serialized(), srvRecord), CHIP_NO_ERROR);

    EXPECT_TRUE(resolver.IsActive());
    EXPECT_FALSE(resolver.IsActiveBrowseParse());
    EXPECT_TRUE(resolver.IsActiveOperationalParse());
    EXPECT_TRUE(resolver.GetMissingRequiredInformation().HasOnly(IncrementalResolver::RequiredInformationBitFlags::kIpAddress));
    EXPECT_EQ(resolver.GetTargetHostName(), kTestHostName.Serialized());
}

TEST(TestIncrementalResolve, TestStartCommissionable)
{
    IncrementalResolver resolver;

    EXPECT_FALSE(resolver.IsActive());

    SrvRecord srvRecord;
    PreloadSrvRecord(srvRecord);

    EXPECT_EQ(resolver.InitializeParsing(kTestCommissionableNode.Serialized(), srvRecord), CHIP_NO_ERROR);

    EXPECT_TRUE(resolver.IsActive());
    EXPECT_TRUE(resolver.IsActiveBrowseParse());
    EXPECT_FALSE(resolver.IsActiveOperationalParse());
    EXPECT_TRUE(resolver.GetMissingRequiredInformation().HasOnly(IncrementalResolver::RequiredInformationBitFlags::kIpAddress));
    EXPECT_EQ(resolver.GetTargetHostName(), kTestHostName.Serialized());
}

TEST(TestIncrementalResolve, TestStartCommissioner)
{
    IncrementalResolver resolver;

    EXPECT_FALSE(resolver.IsActive());

    SrvRecord srvRecord;
    PreloadSrvRecord(srvRecord);

    EXPECT_EQ(resolver.InitializeParsing(kTestCommissionerNode.Serialized(), srvRecord), CHIP_NO_ERROR);

    EXPECT_TRUE(resolver.IsActive());
    EXPECT_TRUE(resolver.IsActiveBrowseParse());
    EXPECT_FALSE(resolver.IsActiveOperationalParse());
    EXPECT_TRUE(resolver.GetMissingRequiredInformation().HasOnly(IncrementalResolver::RequiredInformationBitFlags::kIpAddress));
    EXPECT_EQ(resolver.GetTargetHostName(), kTestHostName.Serialized());
}

TEST(TestIncrementalResolve, TestParseOperational)
{
    IncrementalResolver resolver;

    EXPECT_FALSE(resolver.IsActive());

    SrvRecord srvRecord;
    PreloadSrvRecord(srvRecord);

    EXPECT_EQ(resolver.InitializeParsing(kTestOperationalName.Serialized(), srvRecord), CHIP_NO_ERROR);

    // once initialized, parsing should be ready however no IP address is available
    EXPECT_TRUE(resolver.IsActiveOperationalParse());
    EXPECT_TRUE(resolver.GetMissingRequiredInformation().HasOnly(IncrementalResolver::RequiredInformationBitFlags::kIpAddress));
    EXPECT_EQ(resolver.GetTargetHostName(), kTestHostName.Serialized());

    // Send an IP for an irrelevant host name
    {
        Inet::IPAddress addr;
        EXPECT_TRUE(Inet::IPAddress::FromString("fe80::aabb:ccdd:2233:4455", addr));

        CallOnRecord(resolver, IPResourceRecord(kIrrelevantHostName.Full(), addr));
    }

    // Send a useful IP address here
    {
        Inet::IPAddress addr;
        EXPECT_TRUE(Inet::IPAddress::FromString("fe80::abcd:ef11:2233:4455", addr));
        CallOnRecord(resolver, IPResourceRecord(kTestHostName.Full(), addr));
    }

    // Send a TXT record for an irrelevant host name
    // Note that TXT entries should be addressed to the Record address and
    // NOT to the server name for A/AAAA records
    {
        const char * entries[] = {
            "some", "foo=bar", "x=y=z", "a=", // unused data
            "T=1"                             // TCP supported
        };

        CallOnRecord(resolver, TxtResourceRecord(kTestHostName.Full(), entries));
    }

    // Adding actual text entries that are useful
    // Note that TXT entries should be addressed to the Record address and
    // NOT to the server name for A/AAAA records
    {
        const char * entries[] = {
            "foo=bar", // unused data
            "SII=23"   // session idle interval
        };

        CallOnRecord(resolver, TxtResourceRecord(kTestOperationalName.Full(), entries));
    }

    // Resolver should have all data
    EXPECT_FALSE(resolver.GetMissingRequiredInformation().HasAny());

    // At this point taking value should work. Once taken, the resolver is reset.
    ResolvedNodeData nodeData;
    EXPECT_EQ(resolver.Take(nodeData), CHIP_NO_ERROR);
    EXPECT_FALSE(resolver.IsActive());

    // validate data as it was passed in
    EXPECT_EQ(nodeData.operationalData.peerId,
              PeerId().SetCompressedFabricId(0x1234567898765432LL).SetNodeId(0xABCDEFEDCBAABCDELL));
    EXPECT_EQ(nodeData.resolutionData.numIPs, 1u);
    EXPECT_EQ(nodeData.resolutionData.port, 0x1234);
    EXPECT_FALSE(nodeData.resolutionData.supportsTcp);
    EXPECT_FALSE(nodeData.resolutionData.GetMrpRetryIntervalActive().has_value());
    EXPECT_EQ(nodeData.resolutionData.GetMrpRetryIntervalIdle(), std::make_optional(chip::System::Clock::Milliseconds32(23)));

    Inet::IPAddress addr;
    EXPECT_TRUE(Inet::IPAddress::FromString("fe80::abcd:ef11:2233:4455", addr));
    EXPECT_EQ(nodeData.resolutionData.ipAddress[0], addr);
}

TEST(TestIncrementalResolve, TestParseCommissionable)
{
    IncrementalResolver resolver;

    EXPECT_FALSE(resolver.IsActive());

    SrvRecord srvRecord;
    PreloadSrvRecord(srvRecord);

    EXPECT_EQ(resolver.InitializeParsing(kTestCommissionableNode.Serialized(), srvRecord), CHIP_NO_ERROR);

    // once initialized, parsing should be ready however no IP address is available
    EXPECT_TRUE(resolver.IsActiveBrowseParse());
    EXPECT_TRUE(resolver.GetMissingRequiredInformation().HasOnly(IncrementalResolver::RequiredInformationBitFlags::kIpAddress));
    EXPECT_EQ(resolver.GetTargetHostName(), kTestHostName.Serialized());

    // Send an IP for an irrelevant host name
    {
        Inet::IPAddress addr;

        EXPECT_TRUE(Inet::IPAddress::FromString("fe80::aabb:ccdd:2233:4455", addr));
        CallOnRecord(resolver, IPResourceRecord(kIrrelevantHostName.Full(), addr));
    }

    // Send a useful IP address here
    {
        Inet::IPAddress addr;
        EXPECT_TRUE(Inet::IPAddress::FromString("fe80::abcd:ef11:2233:4455", addr));
        CallOnRecord(resolver, IPResourceRecord(kTestHostName.Full(), addr));
    }

    // Send another IP address
    {
        Inet::IPAddress addr;
        EXPECT_TRUE(Inet::IPAddress::FromString("fe80::f0f1:f2f3:f4f5:1234", addr));
        CallOnRecord(resolver, IPResourceRecord(kTestHostName.Full(), addr));
    }

    // Send a TXT record for an irrelevant host name
    // Note that TXT entries should be addressed to the Record address and
    // NOT to the server name for A/AAAA records
    {
        const char * entries[] = {
            "some", "foo=bar", "x=y=z", "a=", // unused data
            "SII=123"                         // session idle interval
        };

        CallOnRecord(resolver, TxtResourceRecord(kTestHostName.Full(), entries));
    }

    // Adding actual text entries that are useful
    // Note that TXT entries should be addressed to the Record address and
    // NOT to the server name for A/AAAA records
    {
        const char * entries[] = {
            "foo=bar",    // unused data
            "SAI=321",    // session active interval
            "D=22345",    // Long discriminator
            "VP=321+654", // VendorProduct
            "DN=mytest"   // Device name
        };

        CallOnRecord(resolver, TxtResourceRecord(kTestCommissionableNode.Full(), entries));
    }

    // Resolver should have all data
    EXPECT_FALSE(resolver.GetMissingRequiredInformation().HasAny());

    // At this point taking value should work. Once taken, the resolver is reset.
    DiscoveredNodeData discoveredNodeData;
    EXPECT_TRUE(resolver.Take(discoveredNodeData) == CHIP_NO_ERROR);
    EXPECT_FALSE(resolver.IsActive());

    EXPECT_TRUE(discoveredNodeData.Is<CommissionNodeData>());
    CommissionNodeData nodeData = discoveredNodeData.Get<CommissionNodeData>();

    // validate data as it was passed in
    EXPECT_EQ(nodeData.numIPs, 2u);
    EXPECT_EQ(nodeData.port, 0x1234);
    EXPECT_FALSE(nodeData.supportsTcp);
    EXPECT_EQ(nodeData.GetMrpRetryIntervalActive(), std::make_optional(chip::System::Clock::Milliseconds32(321)));
    EXPECT_FALSE(nodeData.GetMrpRetryIntervalIdle().has_value());

    Inet::IPAddress addr;
    EXPECT_TRUE(Inet::IPAddress::FromString("fe80::abcd:ef11:2233:4455", addr));
    EXPECT_EQ(nodeData.ipAddress[0], addr);
    EXPECT_TRUE(Inet::IPAddress::FromString("fe80::f0f1:f2f3:f4f5:1234", addr));
    EXPECT_EQ(nodeData.ipAddress[1], addr);

    // parsed txt data for discovered nodes
    EXPECT_EQ(nodeData.longDiscriminator, 22345);
    EXPECT_EQ(nodeData.vendorId, 321);
    EXPECT_EQ(nodeData.productId, 654);
    EXPECT_STREQ(nodeData.deviceName, "mytest");
}
} // namespace
