/*
 *
 *    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 the Device Description profile, containing
 *      data semantics and methods to specify and query device specific
 *      characteristics that pertain to Weave.
 *
 *      The Device Description profile is used to communicate device
 *      specific characteristics between Weave nodes.  This information
 *      is communicated via the IdentifyRequest and IdentifyResponse
 *      message types, the former used to query for devices matching a
 *      filter, and the latter used to respond with a payload detailing
 *      some or all of the device specific characteristics.  Such
 *      characteristics include the device vendor, make and model, as
 *      well as network information including MAC addresses and connections.
 */

#include <string.h>
#include <ctype.h>

#include <Weave/Core/WeaveCore.h>
#include "DeviceDescription.h"
#include <Weave/Core/WeaveEncoding.h>
#include <Weave/Core/WeaveTLV.h>
#include <Weave/Core/WeaveVendorIdentifiers.hpp>
#include <Weave/Support/CodeUtils.h>
#include <Weave/Support/SerialNumberUtils.h>

using namespace nl::Weave::TLV;
using namespace nl::Weave::Profiles;
using namespace nl::Weave::Encoding;

namespace nl {
namespace Weave {
namespace Profiles {
namespace DeviceDescription {

enum
{
    kTextKey_VendorId                           = 'V',  // [ 1-4 hex digits ] Code identifying product vendor.
    kTextKey_ProductId                          = 'P',  // [ 1-4 hex digits ] Code identifying product.
    kTextKey_ProductRevision                    = 'R',  // [ 1-4 hex digits ] Code identifying product revision.
    kTextKey_ManufacturingDate                  = 'D',  // [ 4 or 6 decimal digits ] Calendar date of manufacture in YYMM or YYMMDD form.
    kTextKey_SerialNumber                       = 'S',  // [ 1-32 char string ] Device serial number.
    kTextKey_DeviceId                           = 'E',  // [ 8 hex digits ] Weave Device Id / device unique id.
    kTextKey_Primary802154MACAddress            = 'L',  // [ 8 hex digits ] MAC address for device's primary 802.15.4 interface.
    kTextKey_PrimaryWiFiMACAddress              = 'W',  // [ 6 hex digits ] MAC address for device's primary WiFi interface.
    kTextKey_RendezvousWiFiESSID                = 'I',  // [ 1-32 char string ] ESSID for device's WiFi rendezvous network.
    kTextKey_PairingCode                        = 'C',  // [ 1-16 char string ] The pairing code for the device.
    kTextKey_PairingCompatibilityVersionMajor   = 'J',  // [ 1-4 hex digits ] Pairing software compatibility major version.
    kTextKey_PairingCompatibilityVersionMinor   = 'N',  // [ 1-4 hex digits ] Pairing software compatibility minor version.

    kEncodingVersion                            = '1',
    kKeySeparator                               = ':',
    kValueTerminator                            = '$'
};


class TextDescriptorWriter
{
public:
    TextDescriptorWriter(char *buf, uint32_t bufSize)
    {
        mBuf = mWritePoint = buf;
        mBufEnd = buf + bufSize;
    }

    WEAVE_ERROR WriteHex(char fieldId, uint16_t val)
    {
        WEAVE_ERROR err = WEAVE_NO_ERROR;
        uint16_t len;

        if (val < 0x0010)
            len = 1;
        else if (val < 0x0100)
            len = 2;
        else if (val < 0x1000)
            len = 3;
        else
            len = 4;

        VerifyOrExit(mWritePoint + len + 3 < mBufEnd, err = WEAVE_ERROR_BUFFER_TOO_SMALL);

        *mWritePoint++ = fieldId;
        *mWritePoint++ = kKeySeparator;

        if (len == 4)
            *mWritePoint++ = HexDigit((val >> 12) & 0xF);
        if (len >= 3)
            *mWritePoint++ = HexDigit((val >> 8) & 0xF);
        if (len >= 2)
            *mWritePoint++ = HexDigit((val >> 4) & 0xF);
        *mWritePoint++ = HexDigit(val & 0xF);

        *mWritePoint++ = kValueTerminator;

    exit:
        return err;
    }

    WEAVE_ERROR WriteHex(char fieldId, const uint8_t *val, uint32_t valLen)
    {
        WEAVE_ERROR err = WEAVE_NO_ERROR;

        VerifyOrExit(mWritePoint + valLen + 3 < mBufEnd, err = WEAVE_ERROR_BUFFER_TOO_SMALL);

        *mWritePoint++ = fieldId;
        *mWritePoint++ = kKeySeparator;

        for (; valLen > 0; val++, valLen--)
        {
            *mWritePoint++ = HexDigit(*val >> 4);
            *mWritePoint++ = HexDigit(*val & 0xF);
        }

        *mWritePoint++ = kValueTerminator;

    exit:
        return err;
    }

    WEAVE_ERROR WriteString(char fieldId, const char *val)
    {
        WEAVE_ERROR err = WEAVE_NO_ERROR;
        uint32_t len;

        len = strlen(val);

        VerifyOrExit(mWritePoint + len + 3 < mBufEnd, err = WEAVE_ERROR_BUFFER_TOO_SMALL);
        VerifyOrExit(strchr(val, '$') == NULL, err = WEAVE_ERROR_INVALID_ARGUMENT);

        *mWritePoint++ = fieldId;
        *mWritePoint++ = kKeySeparator;
        memcpy(mWritePoint, val, len);
        mWritePoint += len;

        *mWritePoint++ = kValueTerminator;

    exit:
        return err;
    }

    WEAVE_ERROR WriteDate(char fieldId, uint16_t year, uint8_t month, uint8_t day)
    {
        WEAVE_ERROR err = WEAVE_NO_ERROR;
        uint16_t len;

        len = (day != 0) ? 9 : 7;

        VerifyOrExit(mWritePoint + len < mBufEnd, err = WEAVE_ERROR_BUFFER_TOO_SMALL);

        *mWritePoint++ = fieldId;
        *mWritePoint++ = kKeySeparator;

        year -= 2000;
        VerifyOrExit(year < 100, err = WEAVE_ERROR_INVALID_ARGUMENT);
        VerifyOrExit(month >= 1 && month <= 12, err = WEAVE_ERROR_INVALID_ARGUMENT);
        VerifyOrExit(day <= 31, err = WEAVE_ERROR_INVALID_ARGUMENT);

        *mWritePoint++ = '0' + (year / 10);
        *mWritePoint++ = '0' + (year % 10);

        *mWritePoint++ = '0' + (month / 10);
        *mWritePoint++ = '0' + (month % 10);

        if (day != 0)
        {
            *mWritePoint++ = '0' + (day / 10);
            *mWritePoint++ = '0' + (day % 10);
        }

        *mWritePoint++ = kValueTerminator;

    exit:
        return err;
    }

    WEAVE_ERROR WriteVersion()
    {
        if (mWritePoint + 1 > mBufEnd)
            return WEAVE_ERROR_INVALID_ARGUMENT;
        *mWritePoint++ = kEncodingVersion;
        return WEAVE_NO_ERROR;
    }

    WEAVE_ERROR Finalize()
    {
        if (mWritePoint + 1 > mBufEnd)
            return WEAVE_ERROR_INVALID_ARGUMENT;
        *mWritePoint = 0;
        return WEAVE_NO_ERROR;
    }

    uint32_t GetLengthWritten()
    {
        return mWritePoint - mBuf;
    }

private:
    char *mBuf;
    char *mWritePoint;
    char *mBufEnd;

    char HexDigit(uint8_t val)
    {
        return (val < 10) ? '0' + val : 'A' + (val - 10);
    }
};

class TextDescriptorReader
{
public:
    TextDescriptorReader(const char *val, uint32_t valLen)
    {
        mVal = val;
        mValEnd = val + valLen;
        mReadPoint = val;

        while (mReadPoint < mValEnd && isspace(*mReadPoint))
            mReadPoint++;

        mFieldEnd = val;

        Version = (mReadPoint < mValEnd) ? *mReadPoint : 0;
        Key = 0;
    }

    char Version;
    char Key;

    WEAVE_ERROR Next()
    {
        mReadPoint = mFieldEnd + 1;

        while (mReadPoint < mValEnd && isspace(*mReadPoint))
            mReadPoint++;

        if (mReadPoint >= mValEnd)
        {
            Key = 0;
            return WEAVE_END_OF_INPUT;
        }

        mFieldEnd = (const char *)memchr(mReadPoint, '$', mValEnd - mReadPoint);
        if (mFieldEnd == NULL)
            return WEAVE_ERROR_INVALID_DEVICE_DESCRIPTOR;
        Key = *mReadPoint;
        return WEAVE_NO_ERROR;
    }

    WEAVE_ERROR ReadString(char *buf, uint32_t bufSize)
    {
        if (Key == 0)
            return WEAVE_ERROR_INCORRECT_STATE;
        uint32_t len = mFieldEnd - mReadPoint - 2;
        if (len > bufSize - 1)
            return WEAVE_ERROR_BUFFER_TOO_SMALL;
        memcpy(buf, mReadPoint + 2, len);
        buf[len] = 0;
        return WEAVE_NO_ERROR;
    }

    WEAVE_ERROR ReadHex(uint16_t& val)
    {
        val = 0;
        if (Key == 0)
            return WEAVE_ERROR_INCORRECT_STATE;
        const char *p = mReadPoint + 2;
        if (p >= mFieldEnd)
            return WEAVE_ERROR_INVALID_DEVICE_DESCRIPTOR;
        for (; p < mFieldEnd; p++)
        {
            int8_t digitVal = HexDigitValue(*p);
            if (digitVal < 0)
                return WEAVE_ERROR_INVALID_DEVICE_DESCRIPTOR;
            val = (val << 4) | digitVal;
        }
        return WEAVE_NO_ERROR;
    }

    WEAVE_ERROR ReadHex(uint8_t *buf, uint32_t bufLen)
    {
        if (Key == 0)
            return WEAVE_ERROR_INCORRECT_STATE;
        uint32_t len = mFieldEnd - mReadPoint - 2;
        if ((len & 1) != 0 || len / 2 != bufLen)
            return WEAVE_ERROR_INVALID_DEVICE_DESCRIPTOR;
        for (const char *p = mReadPoint + 2; p < mFieldEnd; p += 2, buf++)
        {
            int8_t highDigitVal = HexDigitValue(p[0]);
            int8_t lowDigitVal = HexDigitValue(p[1]);
            if (highDigitVal < 0 || lowDigitVal < 0)
                return WEAVE_ERROR_INVALID_DEVICE_DESCRIPTOR;
            *buf = (uint8_t)((highDigitVal << 4) | lowDigitVal);
        }
        return WEAVE_NO_ERROR;
    }

    WEAVE_ERROR ReadDate(uint16_t& year, uint8_t& month, uint8_t& day)
    {
        if (Key == 0)
            return WEAVE_ERROR_INCORRECT_STATE;
        uint32_t len = mFieldEnd - mReadPoint - 2;
        if (len != 4 && len != 6)
            return WEAVE_ERROR_INVALID_DEVICE_DESCRIPTOR;
        int8_t v = DecimalDigitPairValue(mReadPoint[2], mReadPoint[3]);
        if (v < 0)
            return WEAVE_ERROR_INVALID_DEVICE_DESCRIPTOR;
        year = 2000 + v;
        v = DecimalDigitPairValue(mReadPoint[4], mReadPoint[5]);
        if (v < 1 || v > 12)
            return WEAVE_ERROR_INVALID_DEVICE_DESCRIPTOR;
        month = v;
        if (len == 6)
        {
            v = DecimalDigitPairValue(mReadPoint[6], mReadPoint[7]);
            if (v < 1 || v > 31)
                return WEAVE_ERROR_INVALID_DEVICE_DESCRIPTOR;
            day = v;
        }
        else
            day = 0;
        return WEAVE_NO_ERROR;
    }

private:
    const char *mVal;
    const char *mValEnd;
    const char *mReadPoint;
    const char *mFieldEnd;

    inline int8_t HexDigitValue(char digit)
    {
        if (digit >= '0' && digit <= '9')
            return digit - '0';
        if (digit >= 'A' && digit <= 'F')
            return (digit - 'A') + 10;
        if (digit >= 'a' && digit <= 'f')
            return (digit - 'a') + 10;
        return -1;
    }

    inline int8_t DecimalDigitPairValue(char digit1, char digit2)
    {
        if (digit1 < '0' || digit1 > '9' || digit2 < '0' || digit2 > '9')
            return -1;
        return (digit1 - '0') * 10 + (digit2 - '0');
    }
};


WeaveDeviceDescriptor::WeaveDeviceDescriptor()
{
    memset(this, 0, sizeof(*this));
}

/**
 * Clears the device description
 */
void WeaveDeviceDescriptor::Clear()
{
    memset(this, 0, sizeof(*this));
}

/**
 * Encodes the provided device descriptor as text written to the supplied buffer.
 *
 * @param[in]   desc            A reference to the Weave Device Descriptor to encode.
 * @param[out   buf             A pointer to a buffer where the encoded text will be written.
 * @param[in]   bufLen          The length of the supplied buffer.
 * @param[out]  outEncodedLen   A reference to the length variable that will be overwritten
 *                              with the number of characters written to the buffer.
 *
 * @retval #WEAVE_ERROR_BUFFER_TOO_SMALL    If the supplied buffer is too small for the generated
 *                                         text description.
 * @retval #WEAVE_ERROR_INVALID_ARGUMENT    If a descriptor field is invalid.
 * @retval #WEAVE_NO_ERROR                  On success.
 */
WEAVE_ERROR WeaveDeviceDescriptor::EncodeText(const WeaveDeviceDescriptor& desc, char *buf, uint32_t bufLen, uint32_t& outEncodedLen)
{
    WEAVE_ERROR err;
    TextDescriptorWriter writer(buf, bufLen);

    err = writer.WriteVersion();
    SuccessOrExit(err);

    if (desc.VendorId != 0)
    {
        err = writer.WriteHex(kTextKey_VendorId, desc.VendorId);
        SuccessOrExit(err);
    }

    if (desc.ProductId != 0)
    {
        err = writer.WriteHex(kTextKey_ProductId, desc.ProductId);
        SuccessOrExit(err);
    }

    if (desc.ProductRevision != 0)
    {
        err = writer.WriteHex(kTextKey_ProductRevision, desc.ProductRevision);
        SuccessOrExit(err);
    }

    if (desc.ManufacturingDate.Year != 0 && desc.ManufacturingDate.Month != 0)
    {
        err = writer.WriteDate(kTextKey_ManufacturingDate, desc.ManufacturingDate.Year, desc.ManufacturingDate.Month, desc.ManufacturingDate.Day);
        SuccessOrExit(err);
    }

    if (desc.SerialNumber[0] != 0)
    {
        err = writer.WriteString(kTextKey_SerialNumber, desc.SerialNumber);
        SuccessOrExit(err);
    }

    if (desc.DeviceId != 0)
    {
        uint64_t val = BigEndian::HostSwap64(desc.DeviceId);
        err = writer.WriteHex(kTextKey_DeviceId, (const uint8_t *)&val, sizeof(val));
        SuccessOrExit(err);
    }

    if (!IsZeroBytes(desc.Primary802154MACAddress, sizeof(desc.Primary802154MACAddress)))
    {
        err = writer.WriteHex(kTextKey_Primary802154MACAddress, desc.Primary802154MACAddress, sizeof(desc.Primary802154MACAddress));
        SuccessOrExit(err);
    }

    if (!IsZeroBytes(desc.PrimaryWiFiMACAddress, sizeof(desc.PrimaryWiFiMACAddress)))
    {
        err = writer.WriteHex(kTextKey_PrimaryWiFiMACAddress, desc.PrimaryWiFiMACAddress, sizeof(desc.PrimaryWiFiMACAddress));
        SuccessOrExit(err);
    }

    if (desc.RendezvousWiFiESSID[0] != 0)
    {
        err = writer.WriteString(kTextKey_RendezvousWiFiESSID, desc.RendezvousWiFiESSID);
        SuccessOrExit(err);
    }

    if (desc.PairingCode[0] != 0)
    {
        err = writer.WriteString(kTextKey_PairingCode, desc.PairingCode);
        SuccessOrExit(err);
    }

    if (desc.PairingCompatibilityVersionMajor != 0)
    {
        err = writer.WriteHex(kTextKey_PairingCompatibilityVersionMajor, desc.PairingCompatibilityVersionMajor);
        SuccessOrExit(err);
    }

    if (desc.PairingCompatibilityVersionMinor != 0)
    {
        err = writer.WriteHex(kTextKey_PairingCompatibilityVersionMinor, desc.PairingCompatibilityVersionMinor);
        SuccessOrExit(err);
    }

    err = writer.Finalize();
    SuccessOrExit(err);

    outEncodedLen = writer.GetLengthWritten();

exit:
    return err;
}

/**
 * Encodes the provided device descriptor as Weave TLV written to the supplied buffer.
 *
 * @param[in]   desc            A reference to the Weave Device Descriptor to encode.
 * @param[out]  buf             A pointer to a buffer where the encoded text will be written.
 * @param[in]   bufLen          The length of the supplied buffer.
 * @param[out]  outEncodedLen   A reference to the length variable that will be overwritten
 *                              with the number of characters written to the buffer.
 *
 * @retval #WEAVE_NO_ERROR  On success.
 * @retval other            Other Weave or platform-specific error codes indicating that an error
 *                          occurred preventing the encoding of the TLV.
 */
WEAVE_ERROR WeaveDeviceDescriptor::EncodeTLV(const WeaveDeviceDescriptor& desc, uint8_t *buf, uint32_t bufLen, uint32_t& outEncodedLen)
{
    WEAVE_ERROR err;
    TLVWriter writer;

    writer.Init(buf, bufLen);

    err = EncodeTLV(desc, writer);
    SuccessOrExit(err);

    err = writer.Finalize();
    SuccessOrExit(err);

    outEncodedLen = writer.GetLengthWritten();

exit:
    return err;
}

/**
 * Encodes the provided device descriptor as Weave TLV written using the provided
 * pre-initialized TLVWriter object.  This is used to add the device description to
 * larger TLV output.
 *
 * @param[in]   desc        A reference to the Weave Device Descriptor to encode.
 * @param[in]   writer      A reference to the pre-initialized TLVWriter object to be used.
 *
 * @retval #WEAVE_NO_ERROR  On success.
 * @retval other            Other Weave or platform-specific error codes indicating that an error
 *                          occurred preventing the encoding of the TLV.
 */
WEAVE_ERROR WeaveDeviceDescriptor::EncodeTLV(const WeaveDeviceDescriptor& desc, nl::Weave::TLV::TLVWriter& writer)
{
    WEAVE_ERROR err;
    TLVType outerContainer;

    err = writer.StartContainer(ProfileTag(kWeaveProfile_DeviceDescription, kTag_WeaveDeviceDescriptor), kTLVType_Structure, outerContainer);
    SuccessOrExit(err);

    if (desc.VendorId != 0)
    {
        err = writer.Put(ContextTag(kTag_VendorId), desc.VendorId);
        SuccessOrExit(err);
    }

    if (desc.ProductId != 0)
    {
        err = writer.Put(ContextTag(kTag_ProductId), desc.ProductId);
        SuccessOrExit(err);
    }

    if (desc.ProductRevision != 0)
    {
        err = writer.Put(ContextTag(kTag_ProductRevision), desc.ProductRevision);
        SuccessOrExit(err);
    }

    if (desc.ManufacturingDate.Year != 0 && desc.ManufacturingDate.Month != 0)
    {
        uint16_t encodedDate;
        err = EncodeManufacturingDate(desc.ManufacturingDate.Year, desc.ManufacturingDate.Month, desc.ManufacturingDate.Day, encodedDate);
        SuccessOrExit(err);
        err = writer.Put(ContextTag(kTag_ManufacturingDate), encodedDate);
        SuccessOrExit(err);
    }

    if (desc.SerialNumber[0] != 0)
    {
        err = writer.PutString(ContextTag(kTag_SerialNumber), desc.SerialNumber);
        SuccessOrExit(err);
    }

    if (!IsZeroBytes(desc.Primary802154MACAddress, sizeof(desc.Primary802154MACAddress)))
    {
        err = writer.PutBytes(ContextTag(kTag_Primary802154MACAddress), desc.Primary802154MACAddress, sizeof(desc.Primary802154MACAddress));
        SuccessOrExit(err);
    }

    if (!IsZeroBytes(desc.PrimaryWiFiMACAddress, sizeof(desc.PrimaryWiFiMACAddress)))
    {
        err = writer.PutBytes(ContextTag(kTag_PrimaryWiFiMACAddress), desc.PrimaryWiFiMACAddress, sizeof(desc.PrimaryWiFiMACAddress));
        SuccessOrExit(err);
    }

    if (desc.RendezvousWiFiESSID[0] != 0)
    {
        err = writer.PutString(ContextTag(kTag_RendezvousWiFiESSID), desc.RendezvousWiFiESSID);
        SuccessOrExit(err);
    }

    if (desc.PairingCode[0] != 0)
    {
        err = writer.PutString(ContextTag(kTag_PairingCode), desc.PairingCode);
        SuccessOrExit(err);
    }

    if (desc.DeviceId != 0)
    {
        err = writer.Put(ContextTag(kTag_DeviceId), desc.DeviceId);
        SuccessOrExit(err);
    }

    if (desc.FabricId != 0)
    {
        err = writer.Put(ContextTag(kTag_FabricId), desc.FabricId);
        SuccessOrExit(err);
    }

    if (desc.SoftwareVersion[0] != 0)
    {
        err = writer.PutString(ContextTag(kTag_SoftwareVersion), desc.SoftwareVersion);
        SuccessOrExit(err);
    }

    if (desc.PairingCompatibilityVersionMajor != 0)
    {
        err = writer.Put(ContextTag(kTag_PairingCompatibilityVersionMajor), desc.PairingCompatibilityVersionMajor);
        SuccessOrExit(err);
    }

    if (desc.PairingCompatibilityVersionMinor != 0)
    {
        err = writer.Put(ContextTag(kTag_PairingCompatibilityVersionMinor), desc.PairingCompatibilityVersionMinor);
        SuccessOrExit(err);
    }

    if ((desc.DeviceFeatures & kFeature_HomeAlarmLinkCapable) != 0)
    {
        err = writer.PutBoolean(ContextTag(kTag_DeviceFeature_HomeAlarmLinkCapable), true);
        SuccessOrExit(err);
    }

    if ((desc.DeviceFeatures & kFeature_LinePowered) != 0)
    {
        err = writer.PutBoolean(ContextTag(kTag_DeviceFeature_LinePowered), true);
        SuccessOrExit(err);
    }

    err = writer.EndContainer(outerContainer);
    SuccessOrExit(err);

exit:
    return err;
}

/**
 * Decodes the contents of the provided data buffer into a Weave Device Descriptor object.
 *
 * @param[in]   data            A pointer to a buffer containing text or TLV encoded Weave Device
 *                              Descriptor data.
 * @param[in]   dataLen         The length of the provided buffer.
 * @param[out]  outDesc         A reference to the Device Descriptor object to be populated.
 *
 * @retval #WEAVE_ERROR_INVALID_DEVICE_DESCRIPTOR   If the provided buffer is invalid.
 * @retval #WEAVE_NO_ERROR                          On success.
 * @retval other                                    Other Weave or platform-specific error codes indicating that an error
 *                                                  occurred preventing the decoding of the TLV.
 */
WEAVE_ERROR WeaveDeviceDescriptor::Decode(const uint8_t *data, uint32_t dataLen, WeaveDeviceDescriptor& outDesc)
{
    if (dataLen == 0)
        return WEAVE_ERROR_INVALID_DEVICE_DESCRIPTOR;

    // Automatically detect a TLV-encoded descriptor by looking for the TLV structure encoding.  A proper TLV-encoded
    // device descriptor will begin with a structure having either a fully-qualified or implicit profile-specific tag
    // of 0000000E:1.  E.g.:
    //
    //     Fully-qualified: D5 00 00 0E 00 01 00
    //     Implicit:        95 01 00
    //
    if ((dataLen > 3 && data[0] == 0x95 && data[1] == 0x01 && data[2] == 0x00) ||
        (dataLen > 7 && data[0] == 0xD5 && data[1] == 0x00 && data[2] == 0x00 && data[3] == 0x0E && data[4] == 0x00 && data[5] == 0x01 && data[6] == 0x00))
        return DecodeTLV(data, dataLen, outDesc);

    // If the descriptor is not TLV-encoded, assume its in text format.
    return DecodeText((const char *)data, dataLen, outDesc);
}

/**
 * Decodes the contents of the provided text data buffer into a Weave Device Descriptor object.
 *
 * @param[in]   data            A pointer to a buffer containing text encoded Weave Device
 *                              Descriptor data.
 * @param[in]   dataLen         The length of the provided buffer.
 * @param[out]  outDesc         A reference to the Device Descriptor object to be populated.
 *
 * @retval #WEAVE_ERROR_UNSUPPORTED_DEVICE_DESCRIPTOR_VERSION If the encoded data version is
 *                                                  unsupported.
 * @retval #WEAVE_ERROR_INVALID_DEVICE_DESCRIPTOR   If the encoded data is not formated correctly.
 * @retval #WEAVE_ERROR_INCORRECT_STATE             If an inconsistent state is encountered by the
 *                                                  decoder.
 * @retval #WEAVE_ERROR_BUFFER_TOO_SMALL            If the end of the buffer is reached during
 *                                                  decoding.
 * @retval #WEAVE_NO_ERROR                          On success.
 */
WEAVE_ERROR WeaveDeviceDescriptor::DecodeText(const char *data, uint32_t dataLen, WeaveDeviceDescriptor& outDesc)
{
    WEAVE_ERROR err;
    TextDescriptorReader reader(data, dataLen);
    bool vendorIdIncluded = false;
    bool mfgDateIncluded = false;
    bool serialNumIncluded = false;

    if (reader.Version != kEncodingVersion)
        return WEAVE_ERROR_UNSUPPORTED_DEVICE_DESCRIPTOR_VERSION;

    while ((err = reader.Next()) == WEAVE_NO_ERROR)
    {
        switch (reader.Key)
        {
        case kTextKey_VendorId:
            err = reader.ReadHex(outDesc.VendorId);
            SuccessOrExit(err);
            vendorIdIncluded = true;
            break;
        case kTextKey_ProductId:
            err = reader.ReadHex(outDesc.ProductId);
            SuccessOrExit(err);
            break;
        case kTextKey_ProductRevision:
            err = reader.ReadHex(outDesc.ProductRevision);
            SuccessOrExit(err);
            break;
        case kTextKey_ManufacturingDate:
            err = reader.ReadDate(outDesc.ManufacturingDate.Year, outDesc.ManufacturingDate.Month, outDesc.ManufacturingDate.Day);
            SuccessOrExit(err);
            mfgDateIncluded = true;
            break;
        case kTextKey_SerialNumber:
            err = reader.ReadString(outDesc.SerialNumber, sizeof(outDesc.SerialNumber));
            SuccessOrExit(err);
            serialNumIncluded = true;
            break;
        case kTextKey_DeviceId:
        {
            uint64_t val;
            err = reader.ReadHex((uint8_t *)&val, sizeof(val));
            SuccessOrExit(err);
            outDesc.DeviceId = BigEndian::HostSwap64(val);
            break;
        }
        case kTextKey_Primary802154MACAddress:
            err = reader.ReadHex(outDesc.Primary802154MACAddress, sizeof(outDesc.Primary802154MACAddress));
            SuccessOrExit(err);
            break;
        case kTextKey_PrimaryWiFiMACAddress:
            err = reader.ReadHex(outDesc.PrimaryWiFiMACAddress, sizeof(outDesc.PrimaryWiFiMACAddress));
            SuccessOrExit(err);
            break;
        case kTextKey_RendezvousWiFiESSID:
            err = reader.ReadString(outDesc.RendezvousWiFiESSID, sizeof(outDesc.RendezvousWiFiESSID));
            SuccessOrExit(err);
            break;
        case kTextKey_PairingCode:
            err = reader.ReadString(outDesc.PairingCode, sizeof(outDesc.PairingCode));
            SuccessOrExit(err);
            break;
        case kTextKey_PairingCompatibilityVersionMajor:
            err = reader.ReadHex(outDesc.PairingCompatibilityVersionMajor);
            SuccessOrExit(err);
            break;
        case kTextKey_PairingCompatibilityVersionMinor:
            err = reader.ReadHex(outDesc.PairingCompatibilityVersionMinor);
            SuccessOrExit(err);
            break;
        default:
            // ignore unknown keys
            break;
        }
    }

    if (err == WEAVE_END_OF_INPUT)
        err = WEAVE_NO_ERROR;

    // Absence of a vendor id in a *text* device descriptor implies Nest.
    if (!vendorIdIncluded)
        outDesc.VendorId = nl::Weave::kWeaveVendor_NestLabs;

    // If the device was manufactured by Nest and the manufacturing date was not included in the descriptor,
    // then extract the date from the serial number if included.  Since the serial number only includes the
    // week of manufacture, this date will correspond to the first day (Sunday) of the corresponding week.
    //
    // Note: we ignore any errors and just leave the manufacturing date field empty if the serial number
    // can't be parsed.
    //
    if (outDesc.VendorId == nl::Weave::kWeaveVendor_NestLabs && !mfgDateIncluded && serialNumIncluded)
        ExtractManufacturingDateFromSerialNumber(outDesc.SerialNumber, outDesc.ManufacturingDate.Year,
            outDesc.ManufacturingDate.Month, outDesc.ManufacturingDate.Day);

exit:
    return err;
}

/**
 * Decodes the contents of the provided TLV data buffer into a Weave Device Descriptor object.
 *
 * @param[in]   data            A pointer to a buffer containing text encoded Weave Device
 *                              Descriptor data.
 * @param[in]   dataLen         The length of the provided buffer.
 * @param[out]  outDesc         A reference to the Device Descriptor object to be populated.
 *
 * @retval #WEAVE_ERROR_WRONG_TLV_TYPE          If this is not Device Description TLV.
 * @retval #WEAVE_ERROR_UNEXPECTED_TLV_ELEMENT  If more TLV data is encountered after the
 *                                              Device Description.
 * @retval #WEAVE_NO_ERROR                      On success.
 * @retval other                                Other Weave or platform-specific error codes indicating that an error
 *                                              occurred preventing the encoding of the TLV.
 */
WEAVE_ERROR WeaveDeviceDescriptor::DecodeTLV(const uint8_t *data, uint32_t dataLen, WeaveDeviceDescriptor& outDesc)
{
    WEAVE_ERROR err;
    TLVReader reader;

    reader.Init(data, dataLen);

    // Treat an implicit profile tag as specifying the Device Description profile.
    reader.ImplicitProfileId = kWeaveProfile_DeviceDescription;

    err = reader.Next();
    SuccessOrExit(err);

    VerifyOrExit(reader.GetTag() == ProfileTag(kWeaveProfile_DeviceDescription, kTag_WeaveDeviceDescriptor), err = WEAVE_ERROR_WRONG_TLV_TYPE);

    err = DecodeTLV(reader, outDesc);
    SuccessOrExit(err);

    err = reader.Next();
    VerifyOrExit(err == WEAVE_END_OF_TLV, err = WEAVE_ERROR_UNEXPECTED_TLV_ELEMENT);
    err = WEAVE_NO_ERROR;

exit:
    return err;
}

/**
 * Decodes the Device Description using the provided pre-initialized TLVReader.
 *
 * @param[in]   reader          A reference to the pre-initialized TLVReader.
 * @param[out]  outDesc         A reference to the Device Descriptor object to be populated.
 *
 * @retval #WEAVE_ERROR_INVALID_TLV_ELEMENT     If invalid Device Description information is found
 *                                              in the TLV data.
 * @retval #WEAVE_NO_ERROR                      On success.
 * @retval other                                Other Weave or platform-specific error codes indicating that an error
 *                                              occurred that prevented the decoding of the TLV.
 */
WEAVE_ERROR WeaveDeviceDescriptor::DecodeTLV(nl::Weave::TLV::TLVReader& reader, WeaveDeviceDescriptor& outDesc)
{
    WEAVE_ERROR err;
    TLVType outerContainer;

    outDesc.Clear();

    err = reader.EnterContainer(outerContainer);
    SuccessOrExit(err);

    while ((err = reader.Next()) == WEAVE_NO_ERROR)
    {
        uint64_t tag = reader.GetTag();
        if (tag == ContextTag(kTag_VendorId))
        {
            err = reader.Get(outDesc.VendorId);
            SuccessOrExit(err);
            VerifyOrExit(outDesc.VendorId != 0, err = WEAVE_ERROR_INVALID_TLV_ELEMENT);
        }
        else if (tag == ContextTag(kTag_ProductId))
        {
            err = reader.Get(outDesc.ProductId);
            SuccessOrExit(err);
            VerifyOrExit(outDesc.ProductId != 0, err = WEAVE_ERROR_INVALID_TLV_ELEMENT);
        }
        else if (tag == ContextTag(kTag_ProductRevision))
        {
            err = reader.Get(outDesc.ProductRevision);
            SuccessOrExit(err);
            VerifyOrExit(outDesc.ProductRevision != 0, err = WEAVE_ERROR_INVALID_TLV_ELEMENT);
        }
        else if (tag == ContextTag(kTag_ManufacturingDate))
        {
            uint16_t encodedDate;
            err = reader.Get(encodedDate);
            SuccessOrExit(err);
            err = DecodeManufacturingDate(encodedDate, outDesc.ManufacturingDate.Year, outDesc.ManufacturingDate.Month, outDesc.ManufacturingDate.Day);
            SuccessOrExit(err);
        }
        else if (tag == ContextTag(kTag_SerialNumber))
        {
            err = reader.GetString(outDesc.SerialNumber, sizeof(outDesc.SerialNumber));
            SuccessOrExit(err);
            VerifyOrExit(outDesc.SerialNumber[0] != 0, err = WEAVE_ERROR_INVALID_TLV_ELEMENT);
        }
        else if (tag == ContextTag(kTag_Primary802154MACAddress))
        {
            VerifyOrExit(reader.GetLength() == 8, err = WEAVE_ERROR_INVALID_TLV_ELEMENT);
            err = reader.GetBytes(outDesc.Primary802154MACAddress, sizeof(outDesc.Primary802154MACAddress));
            SuccessOrExit(err);
        }
        else if (tag == ContextTag(kTag_PrimaryWiFiMACAddress))
        {
            VerifyOrExit(reader.GetLength() == 6, err = WEAVE_ERROR_INVALID_TLV_ELEMENT);
            err = reader.GetBytes(outDesc.PrimaryWiFiMACAddress, sizeof(outDesc.PrimaryWiFiMACAddress));
            SuccessOrExit(err);
        }
        else if (tag == ContextTag(kTag_RendezvousWiFiESSID))
        {
            err = reader.GetString(outDesc.RendezvousWiFiESSID, sizeof(outDesc.RendezvousWiFiESSID));
            SuccessOrExit(err);
            VerifyOrExit(outDesc.RendezvousWiFiESSID[0] != 0, err = WEAVE_ERROR_INVALID_TLV_ELEMENT);
        }
        else if (tag == ContextTag(kTag_PairingCode))
        {
            err = reader.GetString(outDesc.PairingCode, sizeof(outDesc.PairingCode));
            SuccessOrExit(err);
            VerifyOrExit(outDesc.PairingCode[0] != 0, err = WEAVE_ERROR_INVALID_TLV_ELEMENT);
        }
        else if (tag == ContextTag(kTag_SoftwareVersion))
        {
            const uint8_t *swVer;
            uint32_t swVerLen = reader.GetLength();
            err = reader.GetDataPtr(swVer);
            SuccessOrExit(err);
            if (swVerLen > kMaxSoftwareVersionLength)
                swVerLen = kMaxSoftwareVersionLength;
            memcpy(outDesc.SoftwareVersion, swVer, swVerLen);
            outDesc.SoftwareVersion[swVerLen] = 0;
        }
        else if (tag == ContextTag(kTag_DeviceId))
        {
            err = reader.Get(outDesc.DeviceId);
            SuccessOrExit(err);
        }
        else if (tag == ContextTag(kTag_FabricId))
        {
            err = reader.Get(outDesc.FabricId);
            SuccessOrExit(err);
        }
        else if (tag == ContextTag(kTag_PairingCompatibilityVersionMajor))
        {
            err = reader.Get(outDesc.PairingCompatibilityVersionMajor);
            SuccessOrExit(err);
            VerifyOrExit(outDesc.PairingCompatibilityVersionMajor != 0, err = WEAVE_ERROR_INVALID_TLV_ELEMENT);
        }
        else if (tag == ContextTag(kTag_PairingCompatibilityVersionMinor))
        {
            err = reader.Get(outDesc.PairingCompatibilityVersionMinor);
            SuccessOrExit(err);
            VerifyOrExit(outDesc.PairingCompatibilityVersionMinor != 0, err = WEAVE_ERROR_INVALID_TLV_ELEMENT);
        }
        else {
            uint32_t flag;
            if (tag == ContextTag(kTag_DeviceFeature_HomeAlarmLinkCapable))
                flag = kFeature_HomeAlarmLinkCapable;
            else if (tag == ContextTag(kTag_DeviceFeature_LinePowered))
                flag = kFeature_LinePowered;
            else
                flag = 0;
            if (flag)
            {
                bool val;
                err = reader.Get(val);
                SuccessOrExit(err);
                if (val)
                    outDesc.DeviceFeatures |= flag;
            }
        }
        // Ignore unknown tags.
    }

    VerifyOrExit(err == WEAVE_END_OF_TLV, );

    err = reader.ExitContainer(outerContainer);
    SuccessOrExit(err);

exit:
    return err;
}

WEAVE_ERROR WeaveDeviceDescriptor::EncodeManufacturingDate(uint16_t year, uint8_t month, uint8_t day, uint16_t& outEncodedDate)
{
    if (year < 2001 || year > 2099 || month < 1 || month > 12 || day > 31)
        return WEAVE_ERROR_INVALID_ARGUMENT;
    outEncodedDate =   (year - 2000)
                     + ((month - 1) * 100)
                     + (day * 12 * 100);
    return WEAVE_NO_ERROR;
}

WEAVE_ERROR WeaveDeviceDescriptor::DecodeManufacturingDate(uint16_t encodedDate, uint16_t& outYear, uint8_t& outMonth, uint8_t& outDay)
{
    outYear = (encodedDate % 100) + 2000;
    outMonth = ((encodedDate / 100) % 12) + 1;
    outDay = (encodedDate / 1200);
    if (outDay > 31)
        return WEAVE_ERROR_INVALID_ARGUMENT;
    return WEAVE_NO_ERROR;
}

/**
 * Check if the specified buffer contains only zeros.
 *
 * @param[in]   buf         A pointer to a buffer.
 * @param[in]   len         The length of the buffer.
 *
 * @retval  TRUE    if the buffer contains only zeros.
 * @retval  FALSE   if the buffer contains any non-zero values.
 */
bool WeaveDeviceDescriptor::IsZeroBytes(const uint8_t *buf, uint32_t len)
{
    for (; len > 0; len--, buf++)
        if (*buf != 0)
            return false;
    return true;
}

/**
 * Encodes this IdentifyRequestMessage object into the provided Inet buffer.
 *
 * @param[inout]    msgBuf      A pointer to the Inet buffer to write the Identify
 *                              Request message to.
 *
 * @retval  #WEAVE_NO_ERROR unconditionally.
 */
WEAVE_ERROR IdentifyRequestMessage::Encode(PacketBuffer *msgBuf) const
{
    uint8_t *p;

    p = msgBuf->Start();
    LittleEndian::Write64(p, TargetFabricId);
    LittleEndian::Write32(p, TargetModes);
    LittleEndian::Write16(p, TargetVendorId);
    LittleEndian::Write16(p, TargetProductId);
    msgBuf->SetDataLength(p - msgBuf->Start());

    return WEAVE_NO_ERROR;
}

/**
 * Decodes an Identify Request message from an Inet buffer into the provided
 * IdentifyRequestMessage object.
 *
 * @param[in]       msgBuf          A pointer to the Inet buffer to decode the Identify Request
 *                                  message from.
 * @param[in]       msgDestNodeId   The destination node ID of the message being decoded.
 * @param[inout]    msg             A reference to the IdentifyRequestMessage to populate.
 *
 * @retval #WEAVE_ERROR_INVALID_MESSAGE_LENGTH  If the provided buffer is an invalid length.
 * @retval #WEAVE_NO_ERROR                      On success.
 */
WEAVE_ERROR IdentifyRequestMessage::Decode(PacketBuffer *msgBuf, uint64_t msgDestNodeId, IdentifyRequestMessage& msg)
{
    WEAVE_ERROR err = WEAVE_NO_ERROR;
    const uint8_t *p;

    VerifyOrExit(msgBuf->DataLength() == 16, err = WEAVE_ERROR_INVALID_MESSAGE_LENGTH);

    memset(&msg, 0, sizeof(msg));
    p = msgBuf->Start();
    msg.TargetFabricId = LittleEndian::Read64(p);
    msg.TargetModes = LittleEndian::Read32(p);
    msg.TargetVendorId = LittleEndian::Read16(p);
    msg.TargetProductId = LittleEndian::Read16(p);
    msg.TargetDeviceId = msgDestNodeId;

exit:
    return err;
}

/**
 * Encodes this IdentifyResponseMessage object into the provided message buffer.
 *
 * @param[inout]    msgBuf      A pointer to the Inet buffer to write the Identify
 *                              Response message to.
 *
 * @retval #WEAVE_NO_ERROR  On success.
 * @retval other            Other Weave or platform-specific error codes indicating that an error
 *                          occurred preventing the encoding of the IdentifyResponseMessage.
 */
WEAVE_ERROR IdentifyResponseMessage::Encode(PacketBuffer *msgBuf)
{
    WEAVE_ERROR err;
    uint32_t msgLen;

    err = WeaveDeviceDescriptor::EncodeTLV(DeviceDesc, msgBuf->Start(), msgBuf->AvailableDataLength(), msgLen);
    if (err == WEAVE_NO_ERROR)
        msgBuf->SetDataLength(msgLen);

    return err;
}

/**
 * Decodes an Identify Response message from an Inet buffer into the provided
 * IdentifyResponseMessage object.
 *
 * @param[in]       msgBuf          A pointer to the Inet buffer to decode the Identify Request
 *                                  message from.
 * @param[in]       msgDestNodeId   The destination node ID of the message being decoded.
 * @param[out]      msg             A reference to the IdentifyRequestMessage to populate.
 *
 * @retval #WEAVE_ERROR_WRONG_TLV_TYPE          If this is not Device Description TLV.
 * @retval #WEAVE_ERROR_UNEXPECTED_TLV_ELEMENT  If more TLV data is encountered after the
 *                                              Device Description.
 * @retval #WEAVE_NO_ERROR                      On success.
 * @retval other                                Other Weave or platform-specific error codes indicating that an error
 *                                              occurred preventing the decoding of the IdentifyResponseMessage.
 */
WEAVE_ERROR IdentifyResponseMessage::Decode(PacketBuffer *msgBuf, IdentifyResponseMessage& msg)
{
    return WeaveDeviceDescriptor::DecodeTLV(msgBuf->Start(), msgBuf->DataLength(), msg.DeviceDesc);
}

IdentifyDeviceCriteria::IdentifyDeviceCriteria()
{
    Reset();
}

/**
 * Resets this Identify Device Criteria object to be least restrictive,
 * that is, matching any.
 */
void IdentifyDeviceCriteria::Reset()
{
    TargetFabricId = kTargetFabricId_Any;
    TargetModes = kTargetDeviceMode_Any;
    TargetVendorId = 0xFFFF; // Any vendor
    TargetProductId = 0xFFFF; // Any product
    TargetDeviceId = kAnyNodeId;
}

/**
 * Compare two fabric IDs to determine if they match (considering wildcard values).
 *
 * @param[in]   fabricId        The fabric ID to test.
 * @param[in]   targetFabricId  The fabric ID to test against.
 *
 * @retval TRUE     if the fabric ids match.
 * @retval FALSE    if the fabric ids do not match.
 */
NL_DLL_EXPORT bool MatchTargetFabricId(uint64_t fabricId, uint64_t targetFabricId)
{
    if (targetFabricId == kTargetFabricId_Any)
        return true;

    if (targetFabricId == kTargetFabricId_NotInFabric)
        return (fabricId == kFabricIdNotSpecified);

    if (targetFabricId == kTargetFabricId_AnyFabric)
        return (fabricId != kFabricIdNotSpecified);

    return (targetFabricId == fabricId);
}


} // namespace DeviceDescription
} // namespace Profiles
} // namespace Weave
} // namespace nl
