#ifndef TRANSFERMODEL_H
#define TRANSFERMODEL_H

#include <QAbstractTableModel>
#include <QItemSelectionModel>
#include <QModelIndex>
#include <QVariant>
#include <QList>
#include <QSet>
#include <QIcon>
#include <QString>
#include <unordered_map>
#include <unordered_set>
#include <set>
#include <vector>
#include <memory>

#include "StructEnumDefinition.h"
#include "Environment.h"

#include "../../../interface/FacilityInterface.h"
#include "../../../interface/PathTreeStr.h"

/// \brief model to store the transfer list
class TransferModel : public QAbstractTableModel
{
    Q_OBJECT
public:
    /// \brief the transfer item displayed. The source/destination full paths are NOT stored as
    /// strings here: at 50M files that is tens of GB of RAM (a second copy of the whole path set,
    /// on top of the engine's). Instead each holds a 4-byte node id into pathTreeStr; the path is
    /// resolved on demand for the (viewport-only) display. Same list, same order -- only the
    /// element representation changes. See PathTreeStr.h.
    struct TransfertItem
    {
        uint64_t id;
        uint32_t srcNode;///< node id into pathTreeStr for the source full path
        uint32_t dstNode;///< node id into pathTreeStr for the destination full path
        std::string size;
    };
    /// \brief the transfer item with progression
    struct ItemOfCopyListWithMoreInformations
    {
        uint64_t currentReadProgression,currentWriteProgression;
        Ultracopier::ItemOfCopyList generalData;
        Ultracopier::ActionTypeCopyList actionType;
        bool custom_with_progression;
    };
    /// \brief returned first transfer item
    struct currentTransfertItem
    {
        uint64_t id;
        bool haveItem;
        std::string from;
        std::string to;
        std::string current_file;
        int progressBar_read,progressBar_write;
    };

    TransferModel();

    virtual int columnCount(const QModelIndex& parent = QModelIndex()) const;
    virtual QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const;
    virtual int rowCount(const QModelIndex& parent = QModelIndex()) const;
    virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
    virtual bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole);

    std::vector<uint64_t> synchronizeItems(const std::vector<Ultracopier::ReturnActionOnCopyList>& returnActions);
    void setFacilityEngine(FacilityInterface * facilityEngine);

    int search(const std::string &text,bool searchNext);
    int searchPrev(const std::string &text);

    void setFileProgression(std::vector<Ultracopier::ProgressionItem> &progressionList);

    currentTransfertItem getCurrentTransfertItem() const;

    uint64_t firstId() const;
protected:
    /* Stored by pointer so that erasing/moving an entry shifts cheap 8-byte
       handles instead of move-assigning each TransfertItem (3 std::string).
       Same list, same order, same behaviour -- only the element representation
       changes. This is what kept the GUI thread from freezing in -O0/debug
       builds where the per-string moves are not inlined. */
    std::vector<std::unique_ptr<TransfertItem> > transfertItemList;///< To have a transfer list for the user
    PathTreeStr pathTreeStr;///< memory-compact storage for the rows' source/destination full paths (see PathTreeStr.h)
    std::set<uint64_t> startId,stopId;///< To show what is started, what is stopped
    std::unordered_map<uint64_t,ItemOfCopyListWithMoreInformations> internalRunningOperation;///< to have progression and stat
private:
    int loop_size,index_for_loop;
    int sub_loop_size,sub_index_for_loop;
    int row,column;
    FacilityInterface * facilityEngine;
    std::string search_text;
    /// \brief index from start the search, decresed by remove before it
    int currentIndexSearch;
    bool haveSearchItem;
    uint64_t searchId;
    static QIcon *start;
    static QIcon *stop;
signals:
    #ifdef ULTRACOPIER_PLUGIN_DEBUG
    /// \brief To debug source
    void debugInformation(const Ultracopier::DebugLevel &level,std::string fonction,std::string text,std::string file,int ligne) const;
    #endif
};

#endif // TRANSFERMODEL_H
