/***
   This file is part of fly-ocr.

   Copyright (C) 2016-2020 Sandro Mani <manisandro@gmail.com>
   Copyright (C) 2021 LLC "RusBITech-Astra" (https://astralinux.ru)

    Based on gImageReader source code by Sandro Mani under the GNU
    General Public License (GPL) version 3 or later

   Foobar is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.

   Foobar is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with fly-ocr. If not, see <https://www.gnu.org/licenses/>.
***/

#ifndef UTILS_H
#define UTILS_H

#include <functional>
#include <memory>
#include <QDialogButtonBox>
#include <QMessageBox>
#include <QMutex>
#include <QQueue>
#include <QString>
#include <QWaitCondition>

class QMimeData;
class QSpinBox;
class QDoubleSpinBox;
class QUrl;

namespace Utils
{
QString documentsFolder();
QString makeOutputFilename(const QString& filename);

bool busyTask(const std::function<bool()>& f, const QString& msg);

void setSpinBlocked(QSpinBox* spin, int value);
void setSpinBlocked(QDoubleSpinBox* spin, double value);

bool handleSourceDragEvent(const QMimeData* mimeData);
bool isSupported(const QMimeData* mimeData);
void handleSourceDropEvent(const QMimeData* mimeData);

QString getSpellingLanguage(const QString& lang = QString(), const QString& defaultLanguage = QString());

QDialogButtonBox::StandardButton messageBox(QWidget* parent, const QString& title, const QString& text, const QString& body, QMessageBox::Icon icon, QDialogButtonBox::StandardButtons buttons);

template<typename T>
class AsyncQueue
{
public:
    bool empty()
    {
        QMutexLocker locker(&m_mutex);
        return m_queue.isEmpty();
    }
    void enqueue(const T& item)
    {
        QMutexLocker locker(&m_mutex);
        m_queue.enqueue(item);
        m_cond.wakeOne();
    }
    T dequeue()
    {
        QMutexLocker locker(&m_mutex);
        if (m_queue.isEmpty()) {
            while (m_queue.isEmpty()) {
                m_cond.wait(&m_mutex);
            }
        }
        return m_queue.dequeue();
    }

private:
    QQueue<T> m_queue;
    QMutex m_mutex;
    QWaitCondition m_cond;
};
}

#endif
