/***************************************************************************
 *   Copyright (C) 2007 by Anistratov Oleg                                 *
 *   ower@users.sourceforge.net                                            *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License version 2        *
 *   as published by the Free Software Foundation;                         *
 *                                                                         *
 *   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.                          *
 *                                                                         *
 ***************************************************************************/
#ifndef CHANNELWGT_H
#define CHANNELWGT_H

#include <QWidget>
#include <QString>
#include <QPushButton>
#include <QTextEdit>
#include <QUdpSocket>
#include <QHostInfo>
#include <QLineEdit>
#include <QHostAddress>
#include <QTabWidget>
#include <QSplitter>
#include <QCheckBox>
#include <QList>
#include <QTimer>
#include <QFile>
#include <QComboBox>
#include <QGridLayout>
#include <QStackedWidget>
#include <QTime>
#include <QEvent>

#include "abstractchatcore.h"
#include "userinfo.h"

class ChatWgt;
class MsgHistory;
class UsersList;
class UsersListWgt;
class StatusEditWgt;
class ChatTextWgt;
class InputRichTextWgt;
class Message;
class StatusEditWgt;
class UserWgt;
class UsersStatisticsWgt;
class UsersStatisticsModel;

struct Smile;
struct QC_DatagramHeader;

/**
  @author Anistratov Oleg <ower@users.sourceforge.net>
*/
class ChannelWgt : public QWidget
{
  Q_OBJECT
  private:
    QFile*          m_logFile;
    quint8          m_status;
    quint8          m_oldStatus;

    QGridLayout*    mw_grid;
    QStackedWidget* mw_chatTextStack;
    ChatWgt*        m_parent;
    AbstractChatCore::ChannelType m_type; // 0 - common, 1 - private
    /// m_destUid is UserID in server mode and IP address in serverless
    quint64         m_destUid;
    QString         m_name;

    MsgHistory*     m_chatMsgs;
    UsersList*      m_users;
    quint32         m_usersNum;
    quint16         m_passwordSize;
    quint32         m_messageSize;

    bool            m_displayInfoMsgs;
    bool            m_soundOnMessageIn;

    QTimer*        m_refreshTimer;
    // информация об изменении статуса отсылается не моментально, а через определенный промежуток времени
    QTimer*        m_statusChangedTimer;
    QTimer*        m_initTimer;

    ChatTextWgt*          mw_chatText;
    ChatTextWgt*          mw_clearChatText; // without system messages
    InputRichTextWgt*     mw_inputText;
    UsersListWgt*         mw_usersList;
    UsersStatisticsModel* m_usersModel;
    UsersStatisticsWgt*   mw_usersStatistics;
    QStackedWidget*       mw_usersStack;

    QPushButton*   m_sendBtn;
    QPushButton*   m_refreshUlBtn;
    QCheckBox*     m_sysMessagesChbx;

    QFile*         m_file;
    StatusEditWgt* m_statusWgt;
    QString        m_statusDescription;

    QList<Smile>*  m_smilesFromSender;

    QHostAddress   m_msgsReqAddr;
    uint           m_msgsReqNum;
    QTime          m_msgsReqSent;
    QTime          m_msgsReqReceived;

    mutable QByteArray     m_parametrs;

    QVector<QSplitter*> m_splitters;

    int            m_requestsRest;

  private:
    QPixmap* drawUsersIcon(const QPixmap*, UserInfo*);

  public:
    ChannelWgt(QString name_, QWidget* = 0, AbstractChatCore::ChannelType = AbstractChatCore::Common, quint64 = 0);
    ~ChannelWgt();

    void retranslate();

    void processData      (QC_DatagramHeader* Hdr);
    void getSmilesFromData(QC_DatagramHeader* Hdr);
    void addUser          (QC_DatagramHeader* Hdr);
    void hideUser         (QC_DatagramHeader* Hdr);
    void addUserInfo      (QC_DatagramHeader* Hdr);
    void addUserInfo      (UserWgt*, QC_DatagramHeader* Hdr);
    void addMsg           (QC_DatagramHeader* Hdr);
    void addAvatar        (QC_DatagramHeader* Hdr);
    void addMsg2Chat      (Message* msg);
    void sendInfoAnswer   (QC_DatagramHeader* Hdr);
    void sendStatusAnswer (quint64, bool = 0, bool = 0);

    UserWgt* findUser (quint64) const;
    const QString  &  name      () const {return m_name;}
    quint64           destUid   () const {return m_destUid;}
    quint32           type      () const {return m_type;}
    InputRichTextWgt* inputText () const {return mw_inputText;}

    void initChannel    ();
    void rebuildChatText();
    void msgsNumAnswer  (QC_DatagramHeader* );

    void emitSomeData(AbstractChatCore::DataType, const QString & = "", quint64 = 0) const;

    QByteArray saveState() const;
    void restoreState(const QByteArray&);

    void logMessage(QC_DatagramHeader* Hdr);

  public slots:
    void setFocus2InputText  ();
    void slot_msgOut         ();
    void slot_refreshUL      (); // UL - users list
    void slot_deepRefreshUL  ();
    void addInfoMsg          (QC_DatagramHeader* Hdr);
    void slot_chbxInfChgd    ();
    void setSndOnMsgIn       (bool b) {m_soundOnMessageIn = b;}

    void slot_infoRequest  (UserWgt*);
    void slot_statusRequest() const {emitSomeData(AbstractChatCore::STATUS_REQUEST);}
    void slot_connected    () const {emitSomeData(AbstractChatCore::CONNECTED, "Connected");}
    void slot_disconnected () const {emitSomeData(AbstractChatCore::DISCONNECTED, "Disconnected");}

    void slot_statusChanged   ();
    void slot_startStatusChangedTimer();
    void slot_finMsgsHistoryReq();
    void slot_changeUlRefreshInterval(uint);
    void slot_changeUlDeepRefreshInterval(uint);

    void slot_controlSplitter(int, int);
    void updateUsersView();
    void nextStatusRequest();
    void redrawIcons();

    void setAnimationsRunning(bool b);

  protected:
    void keyPressEvent(QKeyEvent* ev);
    void changeEvent(QEvent *ev)
    {
      if(ev->type() == QEvent::LanguageChange)
        retranslate();
      else
        QWidget::changeEvent(ev);
    }

  signals:
    void statusAnswer    (const QString &, quint64, AbstractChatCore::ChannelType, bool changed = 0, bool = 0);
    void avatarAnswer    (const QString &, quint64, AbstractChatCore::ChannelType);
    void infStatusChanged(const QString &, quint64, AbstractChatCore::ChannelType);
    void infoAnswer      (const QString &, quint64, AbstractChatCore::ChannelType, uchar);
    void sendMsgsHistory (const QString &, quint64, const QByteArray &, AbstractChatCore::ChannelType);
    void sendMsgsNum     (const QString &, quint64, quint32, AbstractChatCore::ChannelType);
    void sendSomeData    (const QString &, quint64, AbstractChatCore::DataType, const QString &, AbstractChatCore::ChannelType, QByteArray*) const;
    void sendMessage     (const QString &, quint64, AbstractChatCore::ChannelType, QTextDocument*);

    void wantActivate    ();
    void rebuildChat     (short type);
    void showStatusDescriptionDlg();
    void wantSaveState(const QString &, const QByteArray &);
};

#endif
