/*******************************************************************************
**
** 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 <documentprovider.h>

#include <QLocalSocket>
#include <QProcess>
#include <QQueue>
#include <QVector>

class Worker;
namespace LoEvent {
    struct Message;
    struct PayloadCallbackEvent;
    struct PayloadUnoEvent;
}

class LoDocumentProvider : public BaseDocumentProvider
{
    Q_OBJECT

public:
    LoDocumentProvider(QObject *parent = nullptr);
    ~LoDocumentProvider();

    void load(const QUrl &filePath) override final;
    void clearDocument() override final;
    QSizeF originalSize(int pageNumber) const;
    QRect originalRect(int pageNumber) const;
    QSize pageSize(int pageNumber) const override final;
    QRect pageRect(int pageNumber) const override final;
    bool supportsTiledRendering() const override final;
    void renderPage(int pageNumber, const QSize &canvasSize, qreal zoom) override final;
    void renderToImage(int pageNumber, const QRect &documentTileRect, const QSize &canvasSize, const QSize &pageSize, qreal zoom, bool forceUpdate = false) override final;
    void resetQueue() override final;
    int tileSize() const override final;
    void stopRenderImage(int pageNumber, const QRect &renderRect, qreal zoom) override final;
    void sendUnoCommand(const QByteArray &command, const QByteArray &arguments, bool notifyWhenFinished = true) override final;
    void sendKeyEvent(int type, int charCode, int keyCode) override final;
    void sendMouseEvent(int type, qreal x, qreal y, int count, int buttons, int modifier, int pageIndex, qreal zoom) override final;
    void sendSelectEvent(int type, qreal x, qreal y, int pageIndex, qreal zoom) override final;
    void setPartIndex(int partIndex) override final;
    void saveDocumentAs(const QString &path, const QString &format) override final;
    void getUnoCommandValues(const QByteArray &command) override final;
    void getTextSelection(const QString &mimeType = QStringLiteral("text/plain;charset=utf-8")) override;
    void close();
    void newMessage();
    QByteArray checksumFile() const;
    qreal shiftY(int pageIndex = 0) const;
    qreal shiftX() const;

    static qreal pixelToTwip(qreal pixels, qreal zoom = 1.0);
    static quint64 twipToPixel(qreal twips , qreal zoom = 1.0);
    static qreal twipToPixelReal(qreal twips , qreal zoom = 1.0);
    static QRect twipRectToPixel(const QRect& rect, qreal zoom, qreal shiftX, qreal shiftY);
    static QRect pixelRectToTwip(const QRect& rect, qreal zoom, qreal shiftX, qreal shiftY);
    static QString makeSocketName();

protected:
    void timerEvent(QTimerEvent *event) override;

private slots:
    void handleMessage(const LoEvent::Message &msg);
    void sendToProcess(const LoEvent::Message &command);

private:
    void socketError(QLocalSocket::LocalSocketError error);
    void imageCacheLoaded(const QString &filePath, int pageNumber, const QImage &image, const QRect &rectTile, qreal zoom);
    void checksumCalculated(const QString &filePath, const QByteArray &checksum);
    void libreofficeCallback(const LoEvent::PayloadCallbackEvent &event);
    void unoCallback(const LoEvent::PayloadUnoEvent &event);

private:
    QProcess m_process;
    QLocalSocket *m_socket;
    QQueue<LoEvent::Message> m_processQueueLok;
    QByteArray m_receivedBuffer;
    QVector<QRect> m_pageRectangles;
    QList<QString> m_pageNames;
    int m_socketReconnectTimer;
    int m_reconnectionAttempts;
    Worker *m_worker;
    QMap<int, QSize> m_currentPageSize;
    qreal m_shiftY;
    qreal m_shiftX;
    QByteArray m_checksumFile;
    QString m_socketName;
};
