#ifndef CHAT_PROXY_MODEL_H_
#define CHAT_PROXY_MODEL_H_

#include <QSortFilterProxyModel>

#include "ChatModel.hpp"

// =============================================================================
// Fetch the L last filtered chat entries.
// =============================================================================

// Cannot be used as a nested class by Qt and `Q_OBJECT` macro
// must be used in header c++ file.
class ChatModelFilter : public QSortFilterProxyModel {
  Q_OBJECT;

public:
  ChatModelFilter (QObject *parent = Q_NULLPTR);

  ChatModel::EntryType getEntryTypeFilter () {
    return m_entry_type_filter;
  }

  void setEntryTypeFilter (ChatModel::EntryType type);

protected:
  bool filterAcceptsRow (int source_row, const QModelIndex &parent) const override;

private:
  ChatModel m_chat_model;
  ChatModel::EntryType m_entry_type_filter = ChatModel::EntryType::GenericEntry;
};

// =============================================================================

class ChatProxyModel : public QSortFilterProxyModel {
  Q_OBJECT;

  Q_PROPERTY(
    QString sipAddress
    READ getSipAddress
    WRITE setSipAddress
    NOTIFY sipAddressChanged
  );

public:
  ChatProxyModel (QObject *parent = Q_NULLPTR);

  Q_INVOKABLE void loadMoreEntries ();
  Q_INVOKABLE void setEntryTypeFilter (ChatModel::EntryType type);
  Q_INVOKABLE void removeEntry (int id);

  Q_INVOKABLE void removeAllEntries () {
    static_cast<ChatModel *>(m_chat_model_filter.sourceModel())->removeAllEntries();
  }

  Q_INVOKABLE void sendMessage (const QString &message) {
    static_cast<ChatModel *>(m_chat_model_filter.sourceModel())->sendMessage(message);
  }

signals:
  void sipAddressChanged (const QString &sipAddress);
  void moreEntriesLoaded (int n);

  void entryTypeFilterChanged (ChatModel::EntryType type);

protected:
  bool filterAcceptsRow (int source_row, const QModelIndex &source_parent) const override;

private:
  QString getSipAddress () const {
    return static_cast<ChatModel *>(m_chat_model_filter.sourceModel())->getSipAddress();
  }

  void setSipAddress (const QString &sip_address) {
    static_cast<ChatModel *>(m_chat_model_filter.sourceModel())->setSipAddress(
      sip_address
    );
  }

  ChatModelFilter m_chat_model_filter;
  int m_n_max_displayed_entries = ENTRIES_CHUNK_SIZE;

  static const unsigned int ENTRIES_CHUNK_SIZE;
};

#endif // CHAT_PROXY_MODEL_H_
