/* Copyright (c) 2020-2022 The Creators of Simphone

   See the file COPYING.LESSER.txt for copying permission.
*/

#ifndef TRANSFERS_H
#define TRANSFERS_H

#include <QDialog>
#include <QTimer>
#include <QTableWidgetItem>
#include <QPushButton>
#include <QAction>
#include <QFileInfo>
#include <QBitArray>

namespace Ui {
class Transfers;
}

class Contact;
class Transfer;
class TransferProgress;

class SimError
{
public:
  QString m_name;
  QString m_simerr;
  int m_simres;
  //SimError() {}
  SimError(const QString & name, const QString & error, int simres)
    : m_name(name), m_simerr(error), m_simres(simres) {}
};

class Transfers : public QDialog
{
  Q_OBJECT

  typedef QDialog Parent;

public:
  explicit Transfers(QWidget * parent, Contact * contact, int msgNdx);
  ~Transfers() Q_DECL_OVERRIDE;

  bool eventFilter(QObject * obj, QEvent * event) Q_DECL_OVERRIDE;
  void changeEvent(QEvent * event) Q_DECL_OVERRIDE;

private slots:
  void initLabelsToolTips();
  void onSignalLogout();

  void onSignalSettingsChanged();
  void onSignalContactAdded(int);
  void onSignalContactChanged(unsigned id);

  void onSignalTransferState(unsigned id, qlonglong xferId, const char * type);
  void onSignalTransfer(unsigned id, qlonglong xferId, const QString & oldName, const QString & newName);

  void onViewMenuTriggered(QAction * action);
  void onSortIndicatorChanged(int index, Qt::SortOrder order);

  void onCustomContextMenuHeader(const QPoint & pos);
  void onCustomContextMenu(const QPoint & pos);

  void onRowClicked(const QModelIndex & index);
  void onRowDoubleClicked(const QModelIndex & index);

  void onTimerTimeout(char update = 0);

  void on_buttonBox_clicked(QAbstractButton * button = 0);
  void on_buttonBox_accepted();

public:
  void saveSettings(bool reset);

  QString convertFileSize(qlonglong n) const;
  static QChar convertFileName(QString & fileName);

  bool hasViewSentPaths() const { return m_viewSent->isChecked() && m_viewPaths->isChecked(); } // two lines per row

  bool isTransferFound(Contact * contact, const QString & fileName, bool ignore = false);
  QHash<qlonglong, Transfer *>::Iterator findTransfer(Contact * contact, qlonglong xferId);

  static void refTransfer(Transfer * transfer);
  static void derefTransfer(Transfer * transfer);

  Transfer * newTransfer(Contact * contact, qlonglong xferId, QString * fileName = 0) const;
  Transfer * newFile(Contact * contact, int type, qlonglong ndx, const QFileInfo & info, QString * fileName = 0);
  Transfer * newFilter(int type, qlonglong xferId, const QString & xferTagName, qlonglong xferTs);

  void setFilter(int msgNdx);
  bool setTransfer(Contact * contact, Transfer * transfer, const char * type, qlonglong xferId, bool prepend);

  void setColWidth(int * width, const QString & fileName) const;
  void setTimeUnits(int units);

  int getTimeUnits() const { return m_viewTime[1]->isChecked() * 2 + m_viewTime[0]->isChecked(); }
  static int getSelectedRows(const QItemSelectionModel * model, int * row = 0);

  QVariant getCurrent(Transfer * transfer, char field = 0);
  QString getToolTip(Transfer * transfer);

  static QString getMessage(qlonglong simId, int msgNdx, qlonglong * xferId = 0, qlonglong * xferTs = 0);

  static int getTransferState(const char * type, int simres = 0);
  static bool compareTransfers(const Transfer * left, const Transfer * right);

  static void countTransfers(qlonglong simId, int type, int * nok);
  static void changeDirectory(bool init);

  static void sendFiles(Contact * contact);
  static void showErrors(const std::vector<SimError> & errorList, QString error);

  Ui::Transfers * ui;
  Contact * m_contact;

  std::vector<Transfer *> m_transfers;
  QHash<qlonglong, Transfer *> m_handles;
  QHash<QString, Transfer *> m_files;
  QSet<qlonglong> m_filters;
  QBitArray m_contacts;
  QHash<Contact *, TransferProgress *> m_current;
  QTimer m_timer;
  QColor m_colors[7];
  QAction * m_viewFinished;
  QAction * m_viewSent;
  QAction * m_viewPaths;
  QAction * m_viewTime[2];
  QPushButton * m_pauseButton;
  QPushButton * m_startButton;
  QPushButton * m_updateButton;
  qlonglong m_minIndex;
  qlonglong m_maxIndex;
  qlonglong m_fileIndex;
  qint64 m_createTime;
  qint64 m_updateTime;
  qint64 m_lastTime;
  int m_colWidth[6];
  int m_addWidth;
  int m_frameRow;
  int m_lastRow;
  int m_precision;
  int m_count;
  char m_sortOrder[7];
  bool m_update;
  char m_dialog; // 0 - all transfers, 1 - per contact, 2 - per transfer
};

#endif
