/*
 *
 *    Copyright (c) 2022 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 <lib/dnssd/IncrementalResolve.h>

#include <lib/dnssd/IPAddressSorter.h>
#include <lib/dnssd/ServiceNaming.h>
#include <lib/dnssd/TxtFields.h>
#include <lib/dnssd/minimal_mdns/Logging.h>
#include <lib/dnssd/minimal_mdns/core/RecordWriter.h>
#include <lib/support/CHIPMemString.h>
#include <trace/trace.h>

namespace chip {
namespace Dnssd {

using namespace mdns::Minimal;
using namespace mdns::Minimal::Logging;

namespace {

ByteSpan GetSpan(const mdns::Minimal::BytesRange & range)
{
    return ByteSpan(range.Start(), range.Size());
}

/// Handles filling record data from TXT records.
///
/// Supported records are whatever `FillNodeDataFromTxt` supports.
template <class DataType>
class TxtParser : public mdns::Minimal::TxtRecordDelegate
{
public:
    explicit TxtParser(DataType & data) : mData(data) {}
    void OnRecord(const mdns::Minimal::BytesRange & name, const mdns::Minimal::BytesRange & value) override
    {
        FillNodeDataFromTxt(GetSpan(name), GetSpan(value), mData);
    }

private:
    DataType & mData;
};

enum class ServiceNameType
{
    kInvalid, // not a matter service name
    kOperational,
    kCommissioner,
    kCommissionable,
};

// Common prefix to check for all operational/commissioner/commissionable name parts
constexpr QNamePart kOperationalSuffix[]    = { kOperationalServiceName, kOperationalProtocol, kLocalDomain };
constexpr QNamePart kCommissionableSuffix[] = { kCommissionableServiceName, kCommissionProtocol, kLocalDomain };
constexpr QNamePart kCommissionerSuffix[]   = { kCommissionerServiceName, kCommissionProtocol, kLocalDomain };

ServiceNameType ComputeServiceNameType(SerializedQNameIterator name)
{
    // SRV record names look like:
    //   <compressed-fabric-id>-<node-id>._matter._tcp.local  (operational)
    //   <instance>._matterc._udp.local  (commissionable)
    //   <instance>._matterd._udp.local  (commissioner)

    // Starts with compressed-fabric-node or instance, skip over it.
    if (!name.Next() || !name.IsValid())
    {
        // missing required components - empty service name
        return ServiceNameType::kInvalid;
    }

    if (name == kOperationalSuffix)
    {
        return ServiceNameType::kOperational;
    }

    if (name == kCommissionableSuffix)
    {
        return ServiceNameType::kCommissionable;
    }

    if (name == kCommissionerSuffix)
    {
        return ServiceNameType::kCommissioner;
    }

    return ServiceNameType::kInvalid;
}

/// Automatically resets a IncrementalResolver to inactive in its destructor
/// unless disarmed.
///
/// Used for RAII for inactive reset
class AutoInactiveResetter
{
public:
    explicit AutoInactiveResetter(IncrementalResolver & resolver) : mResolver(resolver) {}
    ~AutoInactiveResetter()
    {
        if (mArmed)
        {
            mResolver.ResetToInactive();
        }
    }

    void Disarm() { mArmed = false; }

private:
    bool mArmed = true;
    IncrementalResolver & mResolver;
};

} // namespace

CHIP_ERROR StoredServerName::Set(SerializedQNameIterator value)
{
    chip::Encoding::BigEndian::BufferWriter output(mNameBuffer, sizeof(mNameBuffer));
    RecordWriter writer(&output);

    writer.WriteQName(value);

    if (!writer.Fit())
    {
        Clear();
        return CHIP_ERROR_NO_MEMORY;
    }

    return CHIP_NO_ERROR;
}

SerializedQNameIterator StoredServerName::Get() const
{
    return SerializedQNameIterator(BytesRange(mNameBuffer, mNameBuffer + sizeof(mNameBuffer)), mNameBuffer);
}

CHIP_ERROR IncrementalResolver::InitializeParsing(mdns::Minimal::SerializedQNameIterator name, const mdns::Minimal::SrvRecord & srv)
{
    AutoInactiveResetter inactiveReset(*this);

    ReturnErrorOnFailure(mRecordName.Set(name));
    ReturnErrorOnFailure(mTargetHostName.Set(srv.GetName()));
    mCommonResolutionData.port = srv.GetPort();

    {
        // TODO: Chip code historically seems to assume that the host name is of the
        // form "<MAC or 802.15.4 Extended Address in hex>.local" and only saves the first part.
        //
        // This should not be needed as server name should not be relevant once parsed.
        // The Resolver keeps track of this name for the purpose of address resolution
        // in mTargetHostName.
        //
        // Keeping track of this in resolution data does not seem useful and should be
        // removed.
        SerializedQNameIterator serverName = srv.GetName();

        VerifyOrReturnError(serverName.Next() && serverName.IsValid(), CHIP_ERROR_INVALID_ARGUMENT);

        // only save the first part: the MAC or 802.15.4 Extended Address in hex
        Platform::CopyString(mCommonResolutionData.hostName, serverName.Value());
    }

    switch (ComputeServiceNameType(name))
    {
    case ServiceNameType::kOperational:
        mSpecificResolutionData.Set<OperationalNodeData>();
        {
            // Operational addresses start with peer node information
            SerializedQNameIterator nameCopy = name;
            if (!nameCopy.Next() || !nameCopy.IsValid())
            {
                return CHIP_ERROR_INVALID_ARGUMENT;
            }

            CHIP_ERROR err =
                ExtractIdFromInstanceName(nameCopy.Value(), &mSpecificResolutionData.Get<OperationalNodeData>().peerId);
            if (err != CHIP_NO_ERROR)
            {
                return err;
            }
        }

        LogFoundOperationalSrvRecord(mSpecificResolutionData.Get<OperationalNodeData>().peerId, mTargetHostName.Get());
        break;
    case ServiceNameType::kCommissioner:
    case ServiceNameType::kCommissionable:
        mSpecificResolutionData.Set<CommissionNodeData>();

        {
            // Commission addresses start with instance name
            SerializedQNameIterator nameCopy = name;
            if (!nameCopy.Next() || !nameCopy.IsValid())
            {
                return CHIP_ERROR_INVALID_ARGUMENT;
            }

            Platform::CopyString(mSpecificResolutionData.Get<CommissionNodeData>().instanceName, nameCopy.Value());
        }

        LogFoundCommissionSrvRecord(mSpecificResolutionData.Get<CommissionNodeData>().instanceName, mTargetHostName.Get());
        break;
    default:
        return CHIP_ERROR_INVALID_ARGUMENT;
    }

    inactiveReset.Disarm();
    return CHIP_NO_ERROR;
}

IncrementalResolver::RequiredInformationFlags IncrementalResolver::GetMissingRequiredInformation() const
{
    RequiredInformationFlags flags;

    if (!mSpecificResolutionData.Valid())
    {
        flags.Set(RequiredInformationBitFlags::kSrvInitialization);
    }
    else
    {
        if (mCommonResolutionData.numIPs == 0)
        {
            flags.Set(RequiredInformationBitFlags::kIpAddress);
        }
    }

    return flags;
}

CHIP_ERROR IncrementalResolver::OnRecord(Inet::InterfaceId interface, const ResourceData & data, BytesRange packetRange)
{
    MATTER_TRACE_EVENT_SCOPE("Incremental resolver record parsing"); // measure until loop finished

    if (!IsActive())
    {
        return CHIP_NO_ERROR; // nothing to parse
    }

    switch (data.GetType())
    {
    case QType::TXT:
        if (data.GetName() != mRecordName.Get())
        {
            MATTER_TRACE_EVENT_INSTANT("TXT not applicable");
            return CHIP_NO_ERROR;
        }
        return OnTxtRecord(data, packetRange);
    case QType::A: {
        if (data.GetName() != mTargetHostName.Get())
        {
            MATTER_TRACE_EVENT_INSTANT("A (IPv4) not applicable");
            return CHIP_NO_ERROR;
        }

#if INET_CONFIG_ENABLE_IPV4
        Inet::IPAddress addr;
        if (!ParseARecord(data.GetData(), &addr))
        {
            return CHIP_ERROR_INVALID_ARGUMENT;
        }

        return OnIpAddress(interface, addr);
#else
#if CHIP_MINMDNS_HIGH_VERBOSITY
        ChipLogProgress(Discovery, "Ignoring A record: IPv4 not supported");
#endif
        // skipping IPv4 addresses
        return CHIP_NO_ERROR;
#endif
    }
    case QType::AAAA: {
        if (data.GetName() != mTargetHostName.Get())
        {
            MATTER_TRACE_EVENT_INSTANT("AAAA (IPv6) not applicable");
            return CHIP_NO_ERROR;
        }

        Inet::IPAddress addr;
        if (!ParseAAAARecord(data.GetData(), &addr))
        {
            return CHIP_ERROR_INVALID_ARGUMENT;
        }

        return OnIpAddress(interface, addr);
    }
    case QType::SRV: // SRV handled on creation, ignored for 'additional data'
    default:
        // Other types not interesting during parsing
        return CHIP_NO_ERROR;
    }

    return CHIP_NO_ERROR;
}

CHIP_ERROR IncrementalResolver::OnTxtRecord(const ResourceData & data, BytesRange packetRange)
{
    {
        TxtParser<CommonResolutionData> delegate(mCommonResolutionData);
        if (!ParseTxtRecord(data.GetData(), &delegate))
        {
            return CHIP_ERROR_INVALID_ARGUMENT;
        }
    }

    if (IsActiveCommissionParse())
    {
        TxtParser<CommissionNodeData> delegate(mSpecificResolutionData.Get<CommissionNodeData>());
        if (!ParseTxtRecord(data.GetData(), &delegate))
        {
            return CHIP_ERROR_INVALID_ARGUMENT;
        }
    }

    return CHIP_NO_ERROR;
}

CHIP_ERROR IncrementalResolver::OnIpAddress(Inet::InterfaceId interface, const Inet::IPAddress & addr)
{
    if (mCommonResolutionData.numIPs >= ArraySize(mCommonResolutionData.ipAddress))
    {
        return CHIP_ERROR_NO_MEMORY;
    }

    if (!mCommonResolutionData.interfaceId.IsPresent())
    {
        mCommonResolutionData.interfaceId = interface;
    }
    else if (mCommonResolutionData.interfaceId != interface)
    {
        // IP addresses received from multiple packets over different interfaces.
        // Processing is assumed per single interface.
        return CHIP_ERROR_INVALID_ARGUMENT;
    }

    mCommonResolutionData.ipAddress[mCommonResolutionData.numIPs++] = addr;

    LogFoundIPAddress(mTargetHostName.Get(), addr);

    return CHIP_NO_ERROR;
}

CHIP_ERROR IncrementalResolver::Take(DiscoveredNodeData & outputData)
{
    VerifyOrReturnError(IsActiveCommissionParse(), CHIP_ERROR_INCORRECT_STATE);

    IPAddressSorter::Sort(mCommonResolutionData.ipAddress, mCommonResolutionData.numIPs, mCommonResolutionData.interfaceId);

    outputData.resolutionData = mCommonResolutionData;
    outputData.commissionData = mSpecificResolutionData.Get<CommissionNodeData>();

    ResetToInactive();

    return CHIP_NO_ERROR;
}

CHIP_ERROR IncrementalResolver::Take(ResolvedNodeData & outputData)
{
    VerifyOrReturnError(IsActiveOperationalParse(), CHIP_ERROR_INCORRECT_STATE);

    outputData.resolutionData  = mCommonResolutionData;
    outputData.operationalData = mSpecificResolutionData.Get<OperationalNodeData>();

    ResetToInactive();

    return CHIP_NO_ERROR;
}

} // namespace Dnssd
} // namespace chip
