/*
 * historydlg.h
 * Copyright (C) 2001-2010  Justin Karneges, Michail Pishchagin, Evgeny Khryukin
 *
 * 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, see <https://www.gnu.org/licenses/>.
 *
 */

#ifndef HISTORYDLG_H
#define HISTORYDLG_H

#include "advwidget.h"
#include "eventdb.h"
#include "historycontactlistmodel.h"
#include "ui_history.h"

class DisplayProxy;
class PsiAccount;
class PsiContact;
class UserListItem;

namespace XMPP {
class Jid;
}

class SearchProxy : public QObject {
    Q_OBJECT

public:
    SearchProxy(PsiCon *p, DisplayProxy *d);
    void find(const QString &str, const QString &acc_id, const XMPP::Jid &jid, int dir);
    int  totalFound() const { return total_found; }
    int  cursorPosition() const { return general_pos; }

private slots:
    void handleResult();

signals:
    void found(int);
    void needRequest();

private:
    struct Position {
        QDateTime date;
        int       num;
    } position;
    void       reset();
    EDBHandle *getEDBHandle();
    void       movePosition(int dir);
    int        invertSearchPosition(const Position &pos, int dir);
    void       handleFoundData(const EDBResult &r);
    void       handlePadding(const EDBResult &r);

private:
    int                general_pos;
    int                total_found;
    bool               active;
    int                direction;
    QString            s_string;
    QHash<qint64, int> map;
    QVector<Position>  list;
    PsiCon            *psi;
    DisplayProxy      *dp;
    QString            acc_;
    XMPP::Jid          jid_;
    enum RequestType { ReqFind, ReqPadding };
    RequestType reqType;
};

class DisplayProxy : public QObject {
    Q_OBJECT

public:
    DisplayProxy(PsiCon *p, PsiTextView *v);

    void setEmoticonsFlag(bool f) { emoticons = f; }
    void setFormattingFlag(bool f) { formatting = f; }
    void setSentColor(const QString &c) { sentColor = c; }
    void setReceivedColor(const QString &c) { receivedColor = c; }

    bool canBackward() const { return can_backward; }
    bool canForward() const { return can_forward; }

    void displayEarliest(const QString &acc_id, const XMPP::Jid &jid);
    void displayLatest(const QString &acc_id, const XMPP::Jid &jid);
    void displayFromDate(const QString &acc_id, const XMPP::Jid &jid, const QDateTime date);
    void displayNext();
    void displayPrevious();
    bool moveSearchCursor(int dir, int n);
    void displayWithSearchCursor(const QString &acc_id, const XMPP::Jid &jid, QDateTime start, int dir,
                                 const QString &s_str, int num);
    bool isMessage(const QTextCursor &cursor) const;

private slots:
    void handleResult();

signals:
    void updated();
    void searchCursorMoved();

private:
    EDBHandle *getEDBHandle();
    void       resetSearch();
    void       updateQueryParams(int dir, int increase, QDateTime date = QDateTime());
    void       displayResult(const EDBResult &r, int dir);
    QString    getNick(PsiAccount *pa, const XMPP::Jid &jid) const;

private:
    QString   acc_;
    XMPP::Jid jid_;
    struct {
        int       direction;
        int       offset;
        QDateTime date;
    } queryParams;
    struct {
        int     searchPos;
        int     cursorPos;
        int     searchDir;
        QString searchString;
    } searchParams;
    enum RequestType { ReqNone, ReqDate, ReqEarliest, ReqLatest, ReqNext, ReqPrevious };
    RequestType  reqType;
    PsiCon      *psi;
    PsiTextView *viewWid;
    bool         formatting;
    bool         emoticons;
    bool         can_backward;
    bool         can_forward;
    QString      sentColor;
    QString      receivedColor;
};

class HistoryDlg : public AdvancedWidget<QDialog> {
    Q_OBJECT

public:
    HistoryDlg(const XMPP::Jid &, PsiAccount *);
    virtual ~HistoryDlg();

private slots:
    void openSelectedContact();
    void getLatest();
    void getEarliest();
    void getPrevious();
    void getNext();
    void getDate();
    void refresh();
    void findMessages();
    void edbFinished();
    void highlightBlocks();
    void changeAccount(const QString accountName);
    void removeHistory();
    void exportHistory();
    void openChat();
    void doMenu();
    void removedContact(PsiContact *);
    void optionUpdated(const QString &option);
    void autoCopy();
    void viewUpdated();
    void showFoundResult(int rows);
    void updateSearchHint();
    void startRequest();

protected:
    bool eventFilter(QObject *, QEvent *);

private:
    void                     setFilterModeEnabled(bool enable);
    void                     setButtons();
    void                     setLooks(QWidget *w);
    QFont                    fontForOption(const QString &option);
    void                     resetWidgets();
    void                     listAccounts();
    UserListItem            *currentUserListItem() const;
    void                     stopRequest();
    void                     showProgress(int max);
    void                     incrementProgress();
    bool                     selectContact(const QString &accId, const Jid &jid);
    bool                     selectContact(const QStringList &ids);
    void                     selectDefaultContact(const QModelIndex &prefer_parent = QModelIndex(), int prefer_row = 0);
    void                     saveFocus();
    void                     restoreFocus();
    EDBHandle               *getEDBHandle();
    QString                  getCurrentAccountId() const;
    HistoryContactListModel *contactListModel();
    void                     setShortcuts();

    class Private;
    Private                 *d;
    Ui::HistoryDlg           ui_;
    HistoryContactListModel *_contactListModel;
    QWidget                 *lastFocus;
    DisplayProxy            *displayProxy;
    SearchProxy             *searchProxy;
};

#endif // HISTORYDLG_H
