/*
    SPDX-FileCopyrightText: 2012 Joris Guisson <joris.guisson@gmail.com>

    SPDX-License-Identifier: GPL-2.0-or-later
*/

#ifndef BT_CONNECTIONLIMIT_H
#define BT_CONNECTIONLIMIT_H

#include <QMap>
#include <ktorrent_export.h>
#include <util/constants.h>
#include <util/sha1hash.h>

#include <memory>

namespace bt
{
/*!
 * \headerfile peer/connectionlimit.h
 * \brief Maintains the connection limit. It uses a Token for that.
 */
class KTORRENT_EXPORT ConnectionLimit
{
public:
    ConnectionLimit();
    virtual ~ConnectionLimit();

    //! Get the total number of connections currently in use
    [[nodiscard]] bt::Uint32 totalConnections() const
    {
        return global_total;
    }

    /*!
     * Set the connection limits
     * \param global_limit Global limit
     * \param torrent_limit Per torrent limit
     **/
    void setLimits(bt::Uint32 global_limit, bt::Uint32 torrent_limit);

    /*!
     * \headerfile peer/connectionlimit.h
     * \brief Token representing the allowance to open a connection.
     * When the token is destroyed, it will be automatically released.
     */
    class KTORRENT_EXPORT Token
    {
    public:
        Token(ConnectionLimit &limit, const bt::SHA1Hash &hash);
        ~Token();

        //! Get the info hash
        [[nodiscard]] const bt::SHA1Hash &infoHash() const
        {
            return hash;
        }

    private:
        ConnectionLimit &limit;
        bt::SHA1Hash hash;
    };

    /*!
     * Request a token for a given torrent
     * \param hash Info hash of the torrent
     * \return ConnectionLimit::Token::Ptr a valid token if a connection can be opened, a nullptr if not
     **/
    std::unique_ptr<Token> acquire(const SHA1Hash &hash);

protected:
    /*!
     * Release one Token. Will be done by destructor of Token.
     * \param token The Token
     **/
    void release(const Token &token);

private:
    bt::Uint32 global_limit;
    bt::Uint32 global_total;
    bt::Uint32 torrent_limit;
    QMap<SHA1Hash, bt::Uint32> torrent_totals;
};

}

#endif // BT_CONNECTIONLIMIT_H
