/*
  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) version 2.
*/

/*
  Copyright (C) 2008 Eli J. MacKenzie <argonel at gmail.com>
*/


#ifndef IRCQUEUE_H
#define IRCQUEUE_H

class Server;

//channel.cpp, outputfilter.cpp, query.cpp, server.cpp, statuspanel.cpp

/**
 * A message from or to an IRC server.
 *
 * Contains all we know about the message, which currently consists of the text, the time it was created,
 * and its original encoding. (Since currently these objects are only used internally, we know the message
 * is Unicode.)
 */
struct IRCMessage
{
    IRCMessage() : t(TQTime::currentTime()) //, codec(TQTextCodec::codecForName("utf8"))
    {} ///< this constructor required for TQValueList, do not use

    /**
        Make a new IRCMessage with timestamp of TQTime::currentTime().

        Note the constructor takes a TQString, not a const TQString& or a TQString *. If you want to modify the
        contained text, put it back with setText.
    */
    IRCMessage(TQString i) : s(i), t(TQTime::currentTime()) //, codec(TQTextCodec::codecForName("utf8"))
    {}

    TQString text() { return s; }
    int age() { return t.elapsed(); }
    TQTime time() { return t; }
    void setText(TQString text) { s=text; }
private:
    TQString s;
    TQTime t;

    //FIXME wire this up
    //TQTextCodec* codec;
    //operator const char * () const { return codec->fromUnicode(text()); } 

};

/**
* Provides a self-sending queue of IRCMessages.
*
* Messages enqueued in this server can only be erased via reset() or sent to the attached server.
* The server and the emptying rates cannot be changed, if you want to do that construct a new queue.

*/
class IRCQueue: public TQObject
{
    TQ_OBJECT
  

public:
    struct EmptyingRate
    {
        enum RateType {
            Lines, ///< Lines per interval.
            Bytes  ///< Bytes per interval. Not implemented. FIXME
        };
        EmptyingRate(int rate=6, int msec_interval=50000, RateType type=Lines):
                m_rate(rate), m_interval(msec_interval), m_type(type)
        {
        }

        int nextInterval(int byte_size, int msec_since_last);

        int m_rate;
        int m_interval;
        RateType m_type;
        bool isValid()  { return m_rate > 0; }
    };

    IRCQueue(Server *server, EmptyingRate& rate, int myindex=0);
    ~IRCQueue();

    void enqueue(TQString line);
    void reset();
    EmptyingRate& getRate();// { return &m_rate; }

    bool isValid() { return m_rate.isValid(); }
    bool isEmpty() { return m_pending.isEmpty(); }

    //WTF? why are there two of these.
    //These are decoupled for a reason, what is it?
    int currentWait(); ///< Time in ms that the front has been waiting
    int elapsed(); ///< How long has the queue been running since it was last started?

    int nextSize(); ///< Current size of front
    int pendingMessages() { return m_pending.count(); }
    int linesSent() const; ///< count of lines sent by this queue
    int bytesSent() const; ///< count of bytes sent by this queue

    ///Time in milliseconds that the previous message waited
    int lastWait() { return m_lastWait; }

public slots:
    void sent(int bytes, int encodedBytes, IRCQueue *); ///< feedback statistics
    void sendNow(); ///< dumps a line to the socket
    void serverOnline(bool on); ///< server tells us that the socket is ready

protected:
    TQString pop(); ///< pops front, sets statistics
    void adjustTimer(); ///< sets the next timer interval
    bool doSend(); ///< pops front and tells the server to send it. returns true if we sent something
    EmptyingRate& m_rate;

private:
    TQValueList<IRCMessage> m_pending;
    TQTimer *m_timer;
    bool m_blocked;
    bool m_online;
    Server *m_server;

    TQTime m_startedAt;
    TQTime m_lastSent, m_globalLastSent;
    int m_linesSent, m_globalLinesSent;
    int m_bytesSent, m_globalBytesSent;
    int m_lastWait;
    int m_myIndex;
};

extern IRCQueue::EmptyingRate staticrates[];

#endif
