/*Copyright (C) 2010-2023 Duncan Deveaux

This file is part of Hikou no mizu.

Hikou no mizu is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

Hikou no mizu is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with Hikou no mizu.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "PeerActivity.hpp"
#include "PeerList.hpp"

void PeerActivity::update(const std::chrono::seconds &duration,
                          const std::set<std::uint16_t> &immunePeers)
{
    std::map<std::uint16_t, std::chrono::seconds>::iterator it;
    for (it = m_activity.begin(); it != m_activity.end(); ++it)
    {
        if (immunePeers.count(it->first) == 0)
            it->second += duration;
    }
}

void PeerActivity::updatePeerList(const PeerList &peerList,
                                  const std::chrono::seconds &resetValue)
{
    std::map<std::uint16_t, std::chrono::seconds> updatedActivity;

    for (const ConnectedPeer &peer : peerList.getPlayers())
    {
        std::map<std::uint16_t, std::chrono::seconds>::const_iterator it =
            m_activity.find(peer.peerID);

        if (it == m_activity.end()) //Add a new unknown active peer
            updatedActivity[peer.peerID] = resetValue;
        else //Maintain the known peer
            updatedActivity[peer.peerID] = it->second;
    }

    m_activity = updatedActivity;
}

void PeerActivity::reportActivity(std::uint16_t peerID,
                                  const std::chrono::seconds &resetValue)
{
    std::map<std::uint16_t, std::chrono::seconds>::iterator it =
        m_activity.find(peerID);

    if (it != m_activity.end())
        it->second = resetValue;
}

std::vector<std::uint16_t> PeerActivity::getInactivePeers(
    const std::chrono::seconds &timeout) const
{
    std::vector<std::uint16_t> inactive;

    std::map<std::uint16_t, std::chrono::seconds>::const_iterator it;
    for (it = m_activity.begin(); it != m_activity.end(); ++it)
    {
        if (it->second >= timeout)
            inactive.push_back(it->first);
    }

    return inactive;
}
