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

#include <lib/support/logging/CHIPLogging.h>

#include <algorithm>

using namespace chip;

namespace mdns {
namespace Minimal {

constexpr chip::System::Clock::Timeout ActiveResolveAttempts::kMaxRetryDelay;

void ActiveResolveAttempts::Reset()

{
    for (auto & item : mRetryQueue)
    {
        item.attempt.Clear();
    }
}

void ActiveResolveAttempts::Complete(const PeerId & peerId)
{
    for (auto & item : mRetryQueue)
    {
        if (item.attempt.Matches(peerId))
        {
            item.attempt.Clear();
            return;
        }
    }

#if CHIP_MINMDNS_HIGH_VERBOSITY
    // This may happen during boot time adverisements: nodes come online
    // and advertise their IP without any explicit queries for them
    ChipLogProgress(Discovery, "Discovered node without a pending query");
#endif
}

void ActiveResolveAttempts::Complete(const chip::Dnssd::DiscoveredNodeData & data)
{
    for (auto & item : mRetryQueue)
    {
        if (item.attempt.Matches(data))
        {
            item.attempt.Clear();
            return;
        }
    }
}

void ActiveResolveAttempts::CompleteIpResolution(SerializedQNameIterator targetHostName)
{
    for (auto & item : mRetryQueue)
    {
        if (item.attempt.MatchesIpResolve(targetHostName))
        {
            item.attempt.Clear();
            return;
        }
    }
}

void ActiveResolveAttempts::MarkPending(const chip::PeerId & peerId)
{
    MarkPending(ScheduledAttempt(peerId, /* firstSend */ true));
}

void ActiveResolveAttempts::MarkPending(const chip::Dnssd::DiscoveryFilter & filter, const chip::Dnssd::DiscoveryType type)
{
    MarkPending(ScheduledAttempt(filter, type, /* firstSend */ true));
}

void ActiveResolveAttempts::MarkPending(ScheduledAttempt::IpResolve && resolve)
{
    MarkPending(ScheduledAttempt(std::move(resolve), /* firstSend */ true));
}

void ActiveResolveAttempts::MarkPending(ScheduledAttempt && attempt)
{
    // Strategy when picking the peer id to use:
    //   1 if a matching peer id is already found, use that one
    //   2 if an 'unused' entry is found, use that
    //   3 otherwise expire the one with the largest nextRetryDelay
    //     or if equal nextRetryDelay, pick the one with the oldest
    //     queryDueTime

    RetryEntry * entryToUse = &mRetryQueue[0];

    for (size_t i = 1; i < kRetryQueueSize; i++)
    {
        if (entryToUse->attempt.Matches(attempt))
        {
            break; // best match possible
        }

        RetryEntry * entry = mRetryQueue + i;

        // Rule 1: attempt match always matches
        if (entry->attempt.Matches(attempt))
        {
            entryToUse = entry;
            continue;
        }

        // Rule 2: select unused entries
        if (!entryToUse->attempt.IsEmpty() && entry->attempt.IsEmpty())
        {
            entryToUse = entry;
            continue;
        }
        if (entryToUse->attempt.IsEmpty())
        {
            continue;
        }

        // Rule 3: both choices are used (have a defined node id):
        //    - try to find the one with the largest next delay (oldest request)
        //    - on same delay, use queryDueTime to determine the oldest request
        //      (the one with the smallest  due time was issued the longest time
        //       ago)
        if (entry->nextRetryDelay > entryToUse->nextRetryDelay)
        {
            entryToUse = entry;
        }
        else if ((entry->nextRetryDelay == entryToUse->nextRetryDelay) && (entry->queryDueTime < entryToUse->queryDueTime))
        {
            entryToUse = entry;
        }
    }

    if ((!entryToUse->attempt.IsEmpty()) && (!entryToUse->attempt.Matches(attempt)))
    {
        // TODO: node was evicted here, if/when resolution failures are
        // supported this could be a place for error callbacks
        //
        // Note however that this is NOT an actual 'timeout' it is showing
        // a burst of lookups for which we cannot maintain state. A reply may
        // still be received for this peer id (query was already sent on the
        // network)
        ChipLogError(Discovery, "Re-using pending resolve entry before reply was received.");
    }

    entryToUse->attempt        = attempt;
    entryToUse->queryDueTime   = mClock->GetMonotonicTimestamp();
    entryToUse->nextRetryDelay = System::Clock::Seconds16(1);
}

Optional<System::Clock::Timeout> ActiveResolveAttempts::GetTimeUntilNextExpectedResponse() const
{
    Optional<System::Clock::Timeout> minDelay = Optional<System::Clock::Timeout>::Missing();

    chip::System::Clock::Timestamp now = mClock->GetMonotonicTimestamp();

    for (auto & entry : mRetryQueue)
    {
        if (entry.attempt.IsEmpty())
        {
            continue;
        }

        if (now >= entry.queryDueTime)
        {
            // found an entry that needs processing right now
            return Optional<System::Clock::Timeout>::Value(0);
        }

        System::Clock::Timeout entryDelay = entry.queryDueTime - now;
        if (!minDelay.HasValue() || (minDelay.Value() > entryDelay))
        {
            minDelay.SetValue(entryDelay);
        }
    }

    return minDelay;
}

Optional<ActiveResolveAttempts::ScheduledAttempt> ActiveResolveAttempts::NextScheduled()
{
    chip::System::Clock::Timestamp now = mClock->GetMonotonicTimestamp();

    for (auto & entry : mRetryQueue)
    {
        if (entry.attempt.IsEmpty())
        {
            continue; // not a pending item
        }

        if (entry.queryDueTime > now)
        {
            continue; // not yet due
        }

        if (entry.nextRetryDelay > kMaxRetryDelay)
        {
            ChipLogError(Discovery, "Timeout waiting for mDNS resolution.");
            entry.attempt.Clear();
            continue;
        }

        entry.queryDueTime = now + entry.nextRetryDelay;
        entry.nextRetryDelay *= 2;

        Optional<ScheduledAttempt> attempt = MakeOptional(entry.attempt);
        entry.attempt.firstSend            = false;

        return attempt;
    }

    return Optional<ScheduledAttempt>::Missing();
}

bool ActiveResolveAttempts::IsWaitingForIpResolutionFor(SerializedQNameIterator hostName) const
{
    for (auto & entry : mRetryQueue)
    {
        if (entry.attempt.IsEmpty())
        {
            continue; // not a pending item
        }

        if (!entry.attempt.IsIpResolve())
        {
            continue;
        }

        if (hostName == entry.attempt.IpResolveData().hostName.Content())
        {
            return true;
        }
    }

    return false;
}

} // namespace Minimal
} // namespace mdns
