#include "filesystemwidget.h"
#include <QSettings>
#include <QVBoxLayout>
#include <QContextMenuEvent>
#include <QMenu>
#include <QSettings>
#include <QHeaderView>
#include <QMimeDatabase>

FilesystemWidget::FilesystemWidget(QAbstractItemModel *model, QWidget *parent) : QWidget(parent)
  , m_model(model)
{
    m_listView = new QListView(this);
    m_listView->setModel(model);

    QVBoxLayout *layout = new QVBoxLayout(this);
    layout->addWidget(m_listView);

    setLayout(layout);

    connect(m_listView->selectionModel(), &QItemSelectionModel::currentChanged, this, &FilesystemWidget::fileClicked);
}

void FilesystemWidget::contextMenuEvent(QContextMenuEvent *event)
{
    QMenu menu;
    menu.addAction(tr("Sort by filename"), [this](){ emit sortChanged(QDir::Name); });
    menu.addAction(tr("Sort by time"), [this](){ emit sortChanged(QDir::Time); });
    menu.addAction(tr("Sort by size"), [this](){ emit sortChanged(QDir::Size); });
    menu.addAction(tr("Sort by type"), [this](){ emit sortChanged(QDir::Type); });
    menu.addAction(tr("Reverse"), [this](){ emit reverseSort(); });

    menu.exec(event->globalPos());
}

void FilesystemWidget::selectFile(int row)
{
    QModelIndex index = m_model->index(row, 0);
    m_listView->selectionModel()->select(index, QItemSelectionModel::SelectCurrent);
    m_listView->scrollTo(index);
}

void FilesystemWidget::fileClicked(const QModelIndex &index, const QModelIndex &)
{
    if(index.isValid())
        emit fileSelected(index.row());
}

QVariant FileSystemModel::data(const QModelIndex &index, int role) const
{
    if(role == Qt::ToolTipRole && index.column() == 0)role = Qt::DisplayRole;
    return QFileSystemModel::data(index, role);
}

Filetree::Filetree(QWidget *parent) : QTreeView(parent)
{
    QSettings settings;
    m_rootDir = settings.value("filetree/rootDir", QDir::homePath()).toString();
    m_fileSystemModel = new FileSystemModel(this);
    m_fileSystemModel->setRootPath(m_rootDir);
    m_fileSystemModel->setNameFilters({"*.fits", "*.fit", "*.fz", "*.xisf", "*.jpg", "*.jpeg", "*.png", "*.cr2", "*.nef", "*.dng"});
    m_fileSystemModel->setNameFilterDisables(false);
    if(settings.value("filetree/showHidden", false).toBool())
        m_fileSystemModel->setFilter(m_fileSystemModel->filter() | QDir::Hidden);

    setModel(m_fileSystemModel);
    setRootIndex(m_fileSystemModel->index(m_rootDir));
    header()->restoreState(settings.value("filetree/header").toByteArray());
}

Filetree::~Filetree()
{
    QSettings settings;
    settings.setValue("filetree/rootDir", m_rootDir);
    settings.setValue("filetree/header", header()->saveState());
    settings.setValue("filetree/showHidden", (bool)(m_fileSystemModel->filter() & QDir::Hidden));
}

void Filetree::contextMenuEvent(QContextMenuEvent *event)
{
    QModelIndex index = indexAt(event->pos());
    QFileInfo info = m_fileSystemModel->fileInfo(index);
    QMenu menu;
    QAction *open = nullptr;
    QAction *setRoot = nullptr;
    QAction *copy = nullptr;
    QAction *move = nullptr;
    QAction *indexDir = nullptr;

    if(info.isFile())
        open = menu.addAction(tr("Open"));

    if(info.isDir())
    {
        open = menu.addAction(tr("Open"));
        setRoot = menu.addAction(tr("Set as root"));
        copy = menu.addAction(tr("Copy marked files"));
        move = menu.addAction(tr("Move marked files"));
        indexDir = menu.addAction(tr("Index directory"));
    }
    menu.addSeparator();

    QAction *resetRoot = menu.addAction(tr("Reset root"));
    QAction *goUp = menu.addAction(tr("Go up"));
    QAction *showHidden = menu.addAction(tr("Show hidden files"));
    showHidden->setCheckable(true);
    showHidden->setChecked(m_fileSystemModel->filter() & QDir::Hidden);

    QAction *a = menu.exec(event->globalPos());
    if(a == nullptr)
        return;

    if(a == open)
    {
        emit fileSelected(m_fileSystemModel->filePath(index));
    }
    else if(a == setRoot && index.isValid())
    {
        setRootIndex(index);
        m_rootDir = m_fileSystemModel->filePath(index);
        m_fileSystemModel->setRootPath(m_rootDir);
    }
    else if(a == resetRoot)
    {
        setRootIndex(QModelIndex());
        m_rootDir = QDir::rootPath();
    }
    else if(a == goUp)
    {
        setRootIndex(rootIndex().parent());
        m_rootDir = m_fileSystemModel->filePath(rootIndex().parent());
        m_fileSystemModel->setRootPath(m_rootDir);
    }
    else if(a == copy)
    {
        emit copyFiles(m_fileSystemModel->filePath(index));
    }
    else if(a == move)
    {
        emit moveFiles(m_fileSystemModel->filePath(index));
    }
    else if(a == indexDir)
    {
        emit indexDirectory(m_fileSystemModel->filePath(index));
    }
    else if(a == showHidden)
    {
        auto filter = m_fileSystemModel->filter();
        filter ^= QDir::Hidden;
        m_fileSystemModel->setFilter(filter);
        m_fileSystemModel->setRootPath(m_rootDir);
    }
}

void Filetree::mouseDoubleClickEvent(QMouseEvent *event)
{
    QModelIndex index = indexAt(event->pos());
    QFileInfo info = m_fileSystemModel->fileInfo(index);
    if(info.isFile())
        emit fileSelected(info.filePath());
    else
        QTreeView::mouseDoubleClickEvent(event);
}
