#include "backlogrequester.h"
 
-#include <QDebug>
+#include <QObject>
 
-#include "backlogmanager.h"
+#include "clientbacklogmanager.h"
 
-BacklogRequester::BacklogRequester(bool buffering, BacklogManager *backlogManager)
+BacklogRequester::BacklogRequester(bool buffering, ClientBacklogManager *backlogManager)
   : backlogManager(backlogManager),
     _isBuffering(buffering)
 {
 // ========================================
 //  FIXED BACKLOG REQUESTER
 // ========================================
-FixedBacklogRequester::FixedBacklogRequester(BacklogManager *backlogManager)
+FixedBacklogRequester::FixedBacklogRequester(ClientBacklogManager *backlogManager)
   : BacklogRequester(true, backlogManager),
     _backlogCount(500)
 {
 void FixedBacklogRequester::requestBacklog() {
   QList<BufferId> allBuffers = allBufferIds();
   setWaitingBuffers(allBuffers);
+  backlogManager->emitMessagesRequested(QObject::tr("Requesting a total of up to %1 backlog messages for %2 buffers").arg(_backlogCount * allBuffers.count()).arg(allBuffers.count()));
   foreach(BufferId bufferId, allBuffers) {
     backlogManager->requestBacklog(bufferId, _backlogCount, -1);
   }
 
 #include "networkmodel.h"
 #include "types.h"
 
-class BacklogManager;
+class ClientBacklogManager;
 
 class BacklogRequester {
 public:
     PerBufferFixed
   };
 
-  BacklogRequester(bool buffering, BacklogManager *backlogManger);
+  BacklogRequester(bool buffering, ClientBacklogManager *backlogManger);
   virtual inline ~BacklogRequester() {}
 
   inline bool isBuffering() { return _isBuffering; }
   inline void setWaitingBuffers(const QList<BufferId> &buffers) { _buffersWaiting = buffers.toSet(); }
   inline void setWaitingBuffers(const QSet<BufferId> &buffers) { _buffersWaiting = buffers; }
   inline void addWaitingBuffer(BufferId buffer) { _buffersWaiting << buffer; }
-  BacklogManager *backlogManager;
+
+  ClientBacklogManager *backlogManager;
 
 private:
   bool _isBuffering;
 // ========================================
 class FixedBacklogRequester : public BacklogRequester {
 public:
-  FixedBacklogRequester(BacklogManager *backlogManager);
+  FixedBacklogRequester(ClientBacklogManager *backlogManager);
   virtual void requestBacklog();
 
 private:
 
   connect(this, SIGNAL(connected()), mainUi, SLOT(connectedToCore()));
   connect(this, SIGNAL(disconnected()), mainUi, SLOT(disconnectedFromCore()));
 
+  // attach backlog manager
+  p->synchronize(backlogManager());
+  connect(backlogManager(), SIGNAL(messagesReceived(BufferId, int)), _messageModel, SLOT(messagesReceived(BufferId, int)));
 }
 
 /*** public static methods ***/
   connect(bufferSyncer(), SIGNAL(bufferRenamed(BufferId, QString)), this, SLOT(bufferRenamed(BufferId, QString)));
   signalProxy()->synchronize(bufferSyncer());
 
-  // attach backlog manager
-  signalProxy()->synchronize(backlogManager());
-
   // create a new BufferViewManager
   _bufferViewManager = new BufferViewManager(signalProxy(), this);
 
 
 
 #include <ctime>
 
+#include <QDebug>
+
 ClientBacklogManager::ClientBacklogManager(QObject *parent)
   : BacklogManager(parent),
     _requester(0)
   if(msgs.isEmpty())
     return;
 
+  emit messagesReceived(bufferId, msgs.count());
+
   MessageList msglist;
   foreach(QVariant v, msgs) {
     Message msg = v.value<Message>();
 
 
   virtual const QMetaObject *syncMetaObject() const { return &BacklogManager::staticMetaObject; }
 
+  // helper for the backlogRequester, as it isn't a QObject and can't emit itself
+  inline void emitMessagesRequested(const QString &msg) const { emit messagesRequested(msg); }
+
 public slots:
   virtual void receiveBacklog(BufferId bufferId, int lastMsgs, int offset, QVariantList msgs);
   void requestInitialBacklog();
 
 signals:
-  void messagesProcessed(const QString &);
+  void messagesReceived(BufferId bufferId, int count) const;
+  void messagesRequested(const QString &) const;
+  void messagesProcessed(const QString &) const;
 
 private:
   bool isBuffering();
 
  ***************************************************************************/
 
 #include "messagefilter.h"
+
 #include "buffersettings.h"
+#include "client.h"
+#include "messagemodel.h"
 
 MessageFilter::MessageFilter(QAbstractItemModel *source, QObject *parent)
   : QSortFilterProxyModel(parent),
   }
   return _validBuffers.contains(id);
 }
+
+void MessageFilter::requestBacklog() {
+  QSet<BufferId>::const_iterator bufferIdIter = _validBuffers.constBegin();
+  while(bufferIdIter != _validBuffers.constEnd()) {
+    Client::messageModel()->requestBacklog(*bufferIdIter);
+    bufferIdIter++;
+  }
+}
 
 
 public slots:
   void messageTypeFilterChanged();
+  void requestBacklog();
 
 private:
   void init();
 
 
 #include "messagemodel.h"
 
-#include "message.h"
-
 #include <QEvent>
 
+#include "clientbacklogmanager.h"
+#include "client.h"
+#include "message.h"
+#include "networkmodel.h"
+
 class ProcessBufferEvent : public QEvent {
 public:
   inline ProcessBufferEvent() : QEvent(QEvent::User) {}
   return false;
 }
 
-
-
 bool MessageModel::insertMessage(const Message &msg, bool fakeMsg) {
   MsgId id = msg.msgId();
   int idx = indexForId(id);
   qDeleteAll(_messageList);
   _messageList.clear();
   endRemoveRows();
+  _messagesWaiting.clear();
 }
 
-
-
 // returns index of msg with given Id or of the next message after that (i.e., the index where we'd insert this msg)
 int MessageModel::indexForId(MsgId id) {
   if(_messageList.isEmpty() || id <= _messageList.value(0)->msgId())
   _nextDayChange = _nextDayChange.addSecs(86400);
 }
 
-/**********************************************************************************/
+void MessageModel::requestBacklog(BufferId bufferId) {
+  if(_messagesWaiting.contains(bufferId))
+    return;
+
+  static const int REQUEST_COUNT = 500;
+
+  for(int i = 0; i < _messageList.count(); i++) {
+    if(_messageList.at(i)->bufferId() == bufferId) {
+      _messagesWaiting[bufferId] = REQUEST_COUNT;
+      Client::backlogManager()->emitMessagesRequested(tr("Requesting %1 messages from backlog for buffer %2:%3")
+                                                     .arg(REQUEST_COUNT)
+                                                     .arg(Client::networkModel()->networkName(bufferId))
+                                                     .arg(Client::networkModel()->bufferName(bufferId)));
+      Client::backlogManager()->requestBacklog(bufferId, REQUEST_COUNT, _messageList.at(i)->msgId().toInt());
+      return;
+    }
+  }
+}
+
+void MessageModel::messagesReceived(BufferId bufferId, int count) {
+  if(!_messagesWaiting.contains(bufferId))
+    return;
+
+  _messagesWaiting[bufferId] -= count;
+  if(_messagesWaiting[bufferId] <= 0)
+    _messagesWaiting.remove(bufferId);
+}
 
+// ========================================
+//  MessageModelItem
+// ========================================
 MessageModelItem::MessageModelItem(const Message &msg) :
   _timestamp(msg.timestamp()),
   _msgId(msg.msgId()),
 
 
   void clear();
 
+public slots:
+  void requestBacklog(BufferId bufferId);
+  void messagesReceived(BufferId bufferId, int count);
+
 protected:
   virtual MessageModelItem *createMessageModelItem(const Message &) = 0;
   virtual void customEvent(QEvent *event);
   QList<Message> _messageBuffer;
   QTimer _dayChangeTimer;
   QDateTime _nextDayChange;
+  QHash<BufferId, int> _messagesWaiting;
 };
 
 // **************************************************
 
 
 #include "backlogmanager.h"
 
-#include <QDebug>
-
-BacklogManager::BacklogManager(QObject *parent)
-  : SyncableObject(parent)
-{
-}
-
 QVariantList BacklogManager::requestBacklog(BufferId bufferId, int lastMsgs, int offset) {
   emit backlogRequested(bufferId, lastMsgs, offset);
   return QVariantList();
 
   Q_OBJECT
 
 public:
-  BacklogManager(QObject *parent = 0);
+  BacklogManager(QObject *parent = 0) : SyncableObject(parent) {}
 
 public slots:
   virtual QVariantList requestBacklog(BufferId bufferId, int lastMsgs = -1, int offset = -1);
 
 }
 
 void ChatScene::requestBacklog() {
-  static const int REQUEST_COUNT = 500;
-  int backlogSize = model()->rowCount();
-  if(isSingleBufferScene() && backlogSize != 0 && _lastBacklogSize + REQUEST_COUNT <= backlogSize) {
-    QModelIndex msgIdx = model()->index(0, 0);
-    while((Message::Type)(model()->data(msgIdx, ChatLineModel::TypeRole).toInt()) == Message::DayChange) {
-      msgIdx = msgIdx.sibling(msgIdx.row() + 1, 0);
-    }
-    MsgId msgId = model()->data(msgIdx, ChatLineModel::MsgIdRole).value<MsgId>();
-    BufferId bufferId = model()->data(msgIdx, ChatLineModel::BufferIdRole).value<BufferId>();
-    _lastBacklogSize = backlogSize;
-    Client::backlogManager()->requestBacklog(bufferId, REQUEST_COUNT, msgId.toInt());
-  }
+  MessageFilter *filter = qobject_cast<MessageFilter*>(model());
+  if(filter)
+    return filter->requestBacklog();
+  return;
 }
 
 int ChatScene::sectionByScenePos(int x) {
 
   connect(showStatusbar, SIGNAL(toggled(bool)), statusBar(), SLOT(setVisible(bool)));
   connect(showStatusbar, SIGNAL(toggled(bool)), this, SLOT(saveStatusBarStatus(bool)));
 
+  connect(Client::backlogManager(), SIGNAL(messagesRequested(const QString &)), this, SLOT(showStatusBarMessage(const QString &)));
   connect(Client::backlogManager(), SIGNAL(messagesProcessed(const QString &)), this, SLOT(showStatusBarMessage(const QString &)));
 }
 
   connect(Client::bufferViewManager(), SIGNAL(bufferViewConfigDeleted(int)), this, SLOT(removeBufferView(int)));
   connect(Client::bufferViewManager(), SIGNAL(initDone()), this, SLOT(loadLayout()));
 
-  Client::backlogManager()->requestInitialBacklog();
   setConnectedState();
+  Client::backlogManager()->requestInitialBacklog();
 }
 
 void MainWin::setConnectedState() {
 }
 
 void MainWin::showStatusBarMessage(const QString &message) {
-  statusBar()->showMessage(message, 10);
+  statusBar()->showMessage(message, 10000);
 }