/*******************************************************************************
**
** 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 <QObject>
#include <QSharedDataPointer>
#include <QSharedPointer>
#include <QImage>
#include <QPointF>
#include <QList>
#include <QFuture>

#include "lodocumentprovider.h"

class LoPageProvider : public QObject
{
    Q_OBJECT
public:

    enum RenderFlags {
        NoFlags = 0,
        // Set if annotations are to be rendered.
        Annot = 0x01,
        // Set if using text rendering optimized for LCD display.
        LCDText = 0x02,
        // Grayscale output.
        GrayScale = 0x08,
        // Limit image cache size.
        LimitImageCache = 0x200,
        // Always use halftone for image stretching.
        ForceHalfTone = 0x400,
        // Render for printing.
        Printing = 0x800,
        // Set to disable anti-aliasing on text.
        NoSmoothText = 0x1000,
        // Set to disable anti-aliasing on images.
        NoSmoothing = 0x2000,
        // Set to disable anti-aliasing on paths.
        NoSmoothPath = 0x4000,
        // Set whether to render in a reverse Byte order, this flag is only used when
        // rendering to a bitmap.
        ReverseByteOrder = 0x10
    };

    struct TaskKey
    {
        TaskKey(int pageNumber, const QRect &renderRect, qreal zoom)
            : pageNumber(pageNumber)
            , renderRect(renderRect)
            , zoom(zoom)
        {}
        bool operator==(const TaskKey &other) const { return pageNumber == other.pageNumber && renderRect == other.renderRect && qFuzzyCompare(zoom, other.zoom); }
        int pageNumber;
        QRect renderRect;
        qreal zoom;
    };

    LoPageProvider(int pageIndex, QSharedPointer<LoDocumentProvider> loProvider);
    virtual ~LoPageProvider();

    int pageIndex() const;
    bool isValid() const;

    QFuture<QSizeF> originalSize() const;
    QFuture<QImage> bitmapFull(qreal pageScale, int renderFlags = 0) const;
    QFuture<QImage> bitmapPart(qreal pageScaleX, qreal pageScaleY, int renderFlags = 0, qreal zoom = 1.0, const QPointF &bias = QPointF(), qreal pageScale = 1.0) const;
    QFuture<QList<QObject *>> words();
    void stopBitmapPart(qreal pageScaleX, qreal pageScaleY, qreal zoom = 1.0, const QPointF &bias = QPointF());
    void stopAllBitmapPart();

private slots:
    void onTileRendered(int pageNumber, const QImage &image, const QRect &documentRect, qreal zoom);

private:
    int m_pageIndex;
    QFutureInterface<QList<QObject *>> m_words;
    mutable QFutureInterface<QSizeF> m_originalSize;
    QSharedPointer<LoDocumentProvider> m_loProvider;
    mutable QHash<TaskKey, QFutureInterface<QImage>> m_taskToItems;
    mutable QMutex m_mutex;
};

Q_DECLARE_METATYPE(LoPageProvider::RenderFlags)
Q_DECLARE_METATYPE(QFuture<QList<QObject *>>);

QDebug operator<<(QDebug debug, const LoPageProvider::TaskKey &taskKey);
