/*
 *
 *    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 <tracing/macros.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)
{
    if (!IsActive())
    {
        return CHIP_NO_ERROR; // nothing to parse
    }

    switch (data.GetType())
    {
    case QType::TXT:
        if (data.GetName() != mRecordName.Get())
        {
            MATTER_TRACE_INSTANT("TXT not applicable", "Resolver");
            return CHIP_NO_ERROR;
        }
        return OnTxtRecord(data, packetRange);
    case QType::A: {
        if (data.GetName() != mTargetHostName.Get())
        {
            MATTER_TRACE_INSTANT("IPv4 not applicable", "Resolver");
            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_INSTANT("IPv6 not applicable", "Resolver");
            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
