#pragma once

#include "PlayerSession.hpp"
#include "SessionId.hpp"

#include "message_protocol/MessageConnection.hpp"
#include "message_protocol/PeerId.hpp"

#include <memory>
#include <unordered_map>
#include <vector>

namespace tw::net {

class PlayerSessionRegistry {
    std::vector<PlayerSession*> m_session_vec;

    std::unordered_map<SessionId, std::unique_ptr<PlayerSession>> m_session_map;

    // Sessions are identified by a dense id of their own, so the wider peer id
    // the network layer assigns stays at the boundary.
    std::unordered_map<msg::PeerId, SessionId> m_peer_sessions;

    SessionId generate_session_id();

public:
    const std::vector<PlayerSession*>& sessions() const {
        return m_session_vec;
    }

    PlayerSession* session(SessionId id) {
        auto session = m_session_map.find(id);
        return session != m_session_map.end() ? session->second.get() : nullptr;
    }

    /** The session belonging to a peer, or zero if the peer has none. */
    SessionId session_for_peer(msg::PeerId peer) const {
        auto session = m_peer_sessions.find(peer);
        return session != m_peer_sessions.end() ? session->second : 0;
    }

    SessionId register_session(msg::PeerId peer, msg::MessageConnection* connection);

    void unregister_session(SessionId);
};

}
