/*******************************************************************************
**
** SPDX-FileCopyrightText: Copyright 2023 Open Mobile Platform LLC <community@omp.ru>
** SPDX-License-Identifier: BSD-3-Clause
** This file is part of the OfficeViewer project.
**
** Redistribution and use in source and binary forms,
** with or without modification, are permitted provided
** that the following conditions are met:
**
** * Redistributions of source code must retain the above copyright notice,
**   this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright notice,
**   this list of conditions and the following disclaimer
**   in the documentation and/or other materials provided with the distribution.
** * Neither the name of the copyright holder nor the names of its contributors
**   may be used to endorse or promote products derived from this software
**   without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
** AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
** THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
** FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
** IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
** OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
** LOSS OF USE, DATA, OR PROFITS;
** OR BUSINESS INTERRUPTION)
** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE)
** ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
** EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**
*******************************************************************************/


#pragma once

#include "documentproviderglobal.h"
#include <atomic>
#include <QFileInfo>
#include <QImage>
#include <QMap>
#include <QMutex>
#include <QObject>
#include <QThreadPool>

class DOCUMENTPROVIDER_EXPORT ImagesCache : public QObject
{
    Q_OBJECT

public:
    struct CacheKey
    {
        CacheKey(const QString &filePath, int pageNumber, const QSize &imageSize, const QRect &rectTile, qreal zoom)
            : fileId(filePath)
            , pageNumber(pageNumber)
            , imageSize(imageSize)
            , rect(rectTile)
            , zoom(zoom)
        {}

        bool operator==(const CacheKey &other) const
        {
            return pageNumber == other.pageNumber && fileId == other.fileId && imageSize == other.imageSize && rect == other.rect
                   && zoom == other.zoom;
        }

        QString fileId;
        int pageNumber;
        QSize imageSize;
        QRect rect;
        qreal zoom;
    };

public:
    ImagesCache(const QString &pathCache, QObject *parent = nullptr);

    ~ImagesCache();

    bool loadImage(const QString &fileId, int pageNumber, const QSize &canvasSize, const QRect &rectTile, qreal zoom);
    void insertImage(const QString &fileId, int pageNumber, const QImage &image, const QRect &rectTile, qreal zoom);

    void loadCache();
    void saveFile(const QString &filePathCache, int pageNumber, const QSize &imageSize, const QRect &rectTile, qreal zoom);
    QString makeCachePath(const QString &fileId, int pageNumber, const QSize &imageSize, const QRect &rectTile, qreal zoom);

signals:
    void imageLoaded(const QString &fileId, int pageNumber, const QImage &image, const QRect &rectTile, qreal zoom);
    void checksumCalculated(const QString &filePath, const QByteArray &checksum);

private:
    QString m_path;
    qint64 m_limit;            // bytes
    qint64 m_currentCacheSize; // bytes
    QHash<quint32, QFileInfo> m_cache;
    QMap<QDateTime, quint32> m_cacheSortedByCreated;
    QHash<CacheKey, QImage> m_writeQueue;
    std::atomic_bool m_loading;
    QThreadPool m_threadPool;
    QMutex m_mutex;
};
