#ifndef FILEMANAGER_H
#define FILEMANAGER_H

#include <QMainWindow>
#include <QCache>
#include <QFileSystemModel>
#include <QTreeView>
#include <QDialog>
#include <QTabBar>
#include <QHBoxLayout>
#include <QMessageBox>
#include "imageinfodata.h"

namespace Ui {
class FileManager;
class FITSKeyword;
}

class FileManager;

class FileTransfer: public QObject
{
    Q_OBJECT
public:
    explicit FileTransfer(FileManager *fm);
    ~FileTransfer();
public slots:
    void copy(const QStringList &src, const QString &dst);
    void move(const QStringList &src, const QString &dst);
    void cancel();
signals:
    void progress(int percent);
    void finished();
    void error(const QString &title, const QString &text);
private:
    void perform(const QStringList &src, const QString &dst, bool copy);
    struct Action
    {
        QString src;
        QString dst;
        bool dir = false;
    };
    FileManager *_fm;
    bool _run = true;
};

class PathTabBar : public QTabBar
{
    Q_OBJECT
public:
    explicit PathTabBar(const QStringList &tabs);
    QHBoxLayout* createLayout();
    const QStringList& tabPaths() const;
    QString currentTabPath() const;
public slots:
    void pathChanged(const QString &path);
signals:
    void tabChanged(const QString &path);
private:
    QStringList _tabs;
    QString tabName(const QString &path);
};

class FITSSelection : public QDialog
{
    Q_OBJECT
public:
    FITSSelection(const QStringList &keywords, QWidget *parent = nullptr);
    ~FITSSelection();
    QStringList FITSKeywords() const;
private:
    Ui::FITSKeyword *ui;
};

class FileManager : public QMainWindow
{
    Q_OBJECT
public:
    explicit FileManager(const QSet<QString> &openFilter, QWidget *parent = nullptr);
    ~FileManager();
public slots:
    void selectFITSKeywords();
    void copySelectedFilesPaths();
    void pathEdited();
    void copyMoveFiles(Qt::DropAction action, const QStringList &src, const QString &dst);
    QMessageBox::StandardButton overwrite(const QString &dst);
    void errorMessage(const QString &title, const QString &text);
signals:
    void openFile(const QString &path);
    void copy(const QStringList &src, const QString &dst);
    void move(const QStringList &src, const QString &dst);
private:
    Ui::FileManager *ui;
    PathTabBar *_leftTabBar;
    PathTabBar *_rightTabBar;
    QThread *_thread;
    FileTransfer *_fileTransfer;
};

class DirFileSystemModel : public QFileSystemModel
{
    Q_OBJECT
public:
    explicit DirFileSystemModel(QWidget *parentWidget);
    void setDir(const QString &path);
    QString dir() const;
    void setFITSKeywords(const QStringList &keywords);
    const QStringList& FITSKeywords() const;
    Qt::ItemFlags flags(const QModelIndex &index) const override;
    int columnCount(const QModelIndex &parent) const override;
    QVariant data(const QModelIndex &index, int role) const override;
    QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
    bool hasChildren(const QModelIndex &parent) const override;
    bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) override;
public slots:
    void loadFitsKeywords(bool enable);
signals:
    void filesAction(Qt::DropAction action, const QStringList &src, const QString &dst);
private:
    mutable QCache<QString, ImageInfoData> *_cache = nullptr;
    static QCache<QString, ImageInfoData>* getCacheInstance();
    QModelIndex _dir;
    QStringList _fitsKeywords;
    bool _loadFitsKeywords = true;
    QWidget *_parentWidget = nullptr;
};

class DirView : public QTreeView
{
    Q_OBJECT
    DirFileSystemModel *_dirFileSystemModel = nullptr;
    QSet<QString> _openFilter;
public:
    explicit DirView(QWidget *parent = nullptr);
    void setDir(const QString &path);
    QString dir() const;
    void setOpenFilter(const QSet<QString> &openFilter);
    void setFITSKeywords(const QStringList &keywords);
    const QStringList& FITSKeywords() const;
public slots:
    void headerContextMenu(const QPoint &pos);
    void loadFitsKeywords(bool enable);
    void copySelectedFilesPathsToClipboard() const;
signals:
    void dirChanged(const QString &path);
    void openFile(const QString &path);
    void filesAction(Qt::DropAction action, const QStringList &src, const QString &dst);
};

#endif // FILEMANAGER_H
