/*
 *
 *    Copyright (c) 2020 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 "RecordWriter.h"

namespace mdns {
namespace Minimal {

SerializedQNameIterator RecordWriter::PreviousName(size_t index) const
{
    if (index >= kMaxCachedReferences)
    {
        return SerializedQNameIterator();
    }

    uint16_t offset = mPreviousQNames[index];
    if (offset == kInvalidOffset)
    {
        return SerializedQNameIterator();
    }

    return SerializedQNameIterator(BytesRange(mOutput->Buffer(), mOutput->Buffer() + mOutput->WritePos()),
                                   mOutput->Buffer() + offset);
}

RecordWriter & RecordWriter::WriteQName(const FullQName & qname)
{
    size_t qNameWriteStart = mOutput->WritePos();
    bool isFullyCompressed = true;

    for (uint16_t i = 0; i < qname.nameCount; i++)
    {

        // find out if the record part remaining already is located somewhere
        FullQName remaining;
        remaining.names     = qname.names + i;
        remaining.nameCount = qname.nameCount - i;

        // Try to find a valid offset
        chip::Optional<uint16_t> offset = FindPreviousName(remaining);

        if (offset.HasValue())
        {
            // Pointer to offset: set the highest 2 bits
            mOutput->Put16(offset.Value() | 0xC000);

            if (mOutput->Fit() && !isFullyCompressed)
            {
                RememberWrittenQnameOffset(qNameWriteStart);
            }
            return *this;
        }

        mOutput->Put8(static_cast<uint8_t>(strlen(qname.names[i])));
        mOutput->Put(qname.names[i]);
        isFullyCompressed = false;
    }
    mOutput->Put8(0); // end of qnames

    if (mOutput->Fit())
    {
        RememberWrittenQnameOffset(qNameWriteStart);
    }
    return *this;
}

RecordWriter & RecordWriter::WriteQName(const SerializedQNameIterator & qname)
{
    size_t qNameWriteStart = mOutput->WritePos();
    bool isFullyCompressed = true;

    SerializedQNameIterator copy = qname;
    while (true)
    {
        chip::Optional<uint16_t> offset = FindPreviousName(copy);

        if (offset.HasValue())
        {
            // Pointer to offset: set the highest 2 bits
            // We guarantee that offsets saved are <= kMaxReuseOffset
            mOutput->Put16(offset.Value() | 0xC000);

            if (mOutput->Fit() && !isFullyCompressed)
            {
                RememberWrittenQnameOffset(qNameWriteStart);
            }
            return *this;
        }

        if (!copy.Next())
        {
            break;
        }

        if (!copy.IsValid())
        {
            break;
        }

        mOutput->Put8(static_cast<uint8_t>(strlen(copy.Value())));
        mOutput->Put(copy.Value());
        isFullyCompressed = false;
    }
    mOutput->Put8(0); // end of qnames

    if (mOutput->Fit())
    {
        RememberWrittenQnameOffset(qNameWriteStart);
    }
    return *this;
}

void RecordWriter::RememberWrittenQnameOffset(size_t offset)
{
    if (offset > kMaxReuseOffset)
    {
        // cannot represent this offset properly
        return;
    }

    for (unsigned short & previousName : mPreviousQNames)
    {
        if (previousName == kInvalidOffset)
        {
            previousName = offset;
            return;
        }
    }
}

} // namespace Minimal
} // namespace mdns
