/***************************************************************************
 *   Copyright (C) 2004-2015 by Pere Constans
 *   constans@molspaces.com
 *   cb2Bib version 1.9.2. Licensed under the GNU GPL version 3.
 *   See the LICENSE file that comes with this distribution.
 ***************************************************************************/
#include "c2bFileDialog.h"
#include "c2bSettings.h"

#include <QDialogButtonBox>
#include <QLineEdit>
#include <QPushButton>
#include <QTimer>


c2bFileDialog::c2bFileDialog(QWidget* parentw, const QString& caption, const QString& fpath, const QString& ffilter)
    : QFileDialog(parentw, caption, fpath, ffilter)
{
    setModal(true);
    settings = c2bSettingsP;
#ifdef Q_OS_UNIX
    // Distinguish executable files
    fip = new fileIconProvider();
    setIconProvider(fip);
#endif
}

c2bFileDialog::~c2bFileDialog()
{
#ifdef Q_OS_UNIX
    delete fip;
#endif
}


QString c2bFileDialog::getFilename(QWidget* parentw, const QString& caption, const QString& path, const QString& filter)
{
    c2bFileDialog* dlg = new c2bFileDialog(parentw, _caption(tr("Select a filename"), caption), _path(path), filter);
    dlg->setConfirmOverwrite(false);
    dlg->setFileMode(AnyFile);
    dlg->setAcceptMode(AcceptSave);
    dlg->setLabelText(QFileDialog::Accept, "Select");
    const QString fn(dlg->exec(path));
    delete dlg;
    return fn;
}

QString c2bFileDialog::getOpenFilename(QWidget* parentw, const QString& caption, const QString& path, const QString& filter)
{
    c2bFileDialog* dlg = new c2bFileDialog(parentw, _caption(tr("Select a filename"), caption), _path(path), filter);
    dlg->setFileMode(ExistingFile);
    dlg->setLabelText(QFileDialog::Accept, "Select");
    const QString fn(dlg->exec(path));
    delete dlg;
    return fn;
}

QStringList c2bFileDialog::getOpenFilenames(QWidget* parentw, const QString& caption, const QString& path, const QString& filter)
{
    c2bFileDialog* dlg = new c2bFileDialog(parentw, _caption(tr("Select filenames"), caption), _path(path), filter);
    dlg->setFileMode(ExistingFiles);
    dlg->setLabelText(QFileDialog::Accept, "Select");
    const QString fn(dlg->exec(path));
    QStringList fns;
    if (!fn.isEmpty())
        fns = dlg->selectedFiles();
    delete dlg;
    return fns;
}

QString c2bFileDialog::getSaveFilename(QWidget* parentw, const QString& caption, const QString& path, const QString& filter)
{
    c2bFileDialog* dlg = new c2bFileDialog(parentw, _caption(tr("Save As"), caption), _path(path), filter);
    dlg->setFileMode(AnyFile);
    dlg->setAcceptMode(AcceptSave);
    const QString fn(dlg->exec(path));
    delete dlg;
    return fn;
}

QString c2bFileDialog::getExistingDirectory(QWidget* parentw, const QString& caption, const QString& path)
{
    c2bFileDialog* dlg = new c2bFileDialog(parentw, _caption("Select directory", caption), _dirpath(path), QString());
    dlg->setFileMode(DirectoryOnly);
    dlg->setLabelText(QFileDialog::Accept, "Select");
    const QString fn(dlg->exec(QString()));
    delete dlg;
    return fn;
}

QString c2bFileDialog::getSystemFilename(QWidget* parentw, const QString& caption, const QString& path, const QString& filter)
{
    c2bFileDialog* dlg = new c2bFileDialog(parentw, _caption(tr("Select a filename"), caption), _path(path), filter);
    dlg->setFileMode(AnyFile);
    dlg->setLabelText(QFileDialog::Accept, "Select");
    dlg->setFilter(QDir::Drives | QDir::AllDirs | QDir::NoDotAndDotDot | QDir::System);
    dlg->setNameFilterDetailsVisible(false);
    const QString fn(dlg->exec(path));
    delete dlg;
    return fn;
}

QString c2bFileDialog::exec(const QString& path)
{
    readSettings();
    _current_file = path;
    const QStringList fnf(nameFilters().filter(QFileInfo(path).completeSuffix() + ')', Qt::CaseInsensitive));
    if (fnf.count() > 0)
        selectNameFilter(fnf.at(0));
    QTimer::singleShot(250, this, SLOT(selectCurrentFile()));
    QString sfn;
    if (QFileDialog::exec() == QDialog::Accepted)
    {
        const QStringList selected(selectedFiles());
        if (selected.count() > 0)
            sfn = selected.first();
    }
    writeSettings();
    return QDir::toNativeSeparators(QDir::cleanPath(sfn));
}

void c2bFileDialog::accept()
{
    // Set suffix for getSaveFilename dialog
    if (acceptMode() == AcceptSave)
    {
        QString suffix(selectedNameFilter());
        QRegExp sre("\\*\\.([\\w\\.]+)");
        if (sre.indexIn(suffix) != -1)
        {
            suffix = sre.cap(1);
            setDefaultSuffix(suffix);
        }
    }
    QFileDialog::accept();
}

void c2bFileDialog::selectCurrentFile()
{
    // Bug fix for Qt 4.4 not giving correct selection
    const QString fn(_filename(_current_file));
    QLineEdit* le = findChild<QLineEdit*>();
    if (le)
    {
        le->setText(fn);
        le->selectAll();
    }
}

void c2bFileDialog::readSettings()
{
    // Size
    resize(settings->value("c2bFileDialog/size", sizeHint()).toSize());

    // History
    QStringList _history(settings->value("c2bFileDialog/history").toStringList());
    _history.removeAll(directory().absolutePath());
    qSort(_history);
    setHistory(_history);
}

void c2bFileDialog::writeSettings()
{
    // Size
    settings->setValue("c2bFileDialog/size", size());

    // History
    if (result() == QDialog::Accepted)
    {
        // Unique paths, keeping the newest history entries
        QStringList _history(history());
        _history.append(directory().absolutePath());
        _history.removeAll(QDir::homePath());
        _history.removeAll(QDir::rootPath());
        QStringList chronological(settings->value("c2bFileDialog/history").toStringList());
        chronological.append(_history.last());
        // Discard repeated
        _history.clear();
        for (int i = chronological.count() - 1; i > -1; --i)
            if (!_history.contains(chronological.at(i)))
            {
                _history.prepend(chronological.at(i));
                if (_history.count() > 10)
                    break;
            }
        settings->setValue("c2bFileDialog/history", _history);
    }
}

QString c2bFileDialog::_caption(const QString& generic, const QString& caption)
{
    if (caption.isEmpty())
        return generic + " - cb2Bib";
    else
        return caption + " - cb2Bib";
}

QString c2bFileDialog::_filename(const QString& path)
{
    if (path.isEmpty())
        return path;
    else
        return QFileInfo(path).fileName();
}

QString c2bFileDialog::_path(const QString& path)
{
    if (path.isEmpty())
        return QDir::homePath();
    else
        return QFileInfo(path).absolutePath();
}

QString c2bFileDialog::_dirpath(const QString& path)
{
    if (path.isEmpty())
        return QDir::homePath();
    else
        return QFileInfo(path + '/').absolutePath();
}


/***************************************************************************
 Class fileIconProvider
 ***************************************************************************/

fileIconProvider::fileIconProvider() : QFileIconProvider()
{
    _exec_icon = QIcon(":/icons/icons/application-x-executable.png");
}

fileIconProvider::~fileIconProvider()
{}


QIcon fileIconProvider::icon(const QFileInfo&  info) const
{
    if (info.isExecutable() && !info.isDir())
        return _exec_icon;
    else
        return QFileIconProvider::icon(info);
}
