/***************************************************************************
 *   Copyright (C) 2012 by                                                 *
 *   Joris Guisson <joris.guisson@gmail.com>                               *
 *                                                                         *
 *   This program 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 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program 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 this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.          *
 ***************************************************************************/

#ifndef BT_CONNECTIONLIMIT_H
#define BT_CONNECTIONLIMIT_H

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

namespace bt
{
/**
 * 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
    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);

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

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

        typedef QSharedPointer<Token> Ptr;

    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 0 pointer if not
     **/
    Token::Ptr 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
