/*******************************************************************************
**
** 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 <QSharedPointer>
#include "documentprovider.h"

class QThreadPool;
class BasePage;
class BaseBookmark;
struct CommentData;

class DOCUMENTPROVIDER_EXPORT BaseDocument : public QObject
{
    Q_OBJECT

    Q_PROPERTY(DocumentStatus status READ status NOTIFY statusChanged)
    Q_PROPERTY(QString path READ path WRITE setPath NOTIFY pathChanged)
    Q_PROPERTY(int count READ count NOTIFY countChanged)
    Q_PROPERTY(bool processing READ processing NOTIFY processingChanged)
    Q_PROPERTY(int loadingProgress READ loadingProgress NOTIFY loadingProgressChanged)
    Q_PROPERTY(int error READ error NOTIFY errorChanged)
    Q_PROPERTY(QString fileName READ fileName NOTIFY fileNameChanged)
    Q_PROPERTY(BaseDocumentProvider::DocumentType documentType READ documentType NOTIFY documentTypeChanged)
    Q_PROPERTY(QList<QString> pageNames READ pageNames NOTIFY pageNamesChanged)
    Q_PROPERTY(int pageIndex READ pageIndex WRITE setPageIndex NOTIFY pageIndexChanged)
    Q_PROPERTY(Mode mode READ mode WRITE setMode NOTIFY modeChanged)

public:
    enum class DocumentStatus
    {
        Null,
        Loading,
        Ready,
        Error
    };
    Q_ENUM(DocumentStatus)

    enum class PageLoadStatus
    {
        Success,
        Fail
    };
    Q_ENUM(PageLoadStatus)

    enum class SearchDirection
    {
        SearchForward,
        SearchBackward
    };
    Q_ENUM(SearchDirection)

    enum class SearchCommand
    {
        CmdFind,
        CmdFindAll,
        CmdReplace,
        CmdReplaceAl,
    };
    Q_ENUM(SearchCommand)

    enum class Mode
    {
        ModeView,
        ModeSearch,
        ModeSelect
    };
    Q_ENUM(Mode)

    struct Marker {
        enum Type {
            Unknown,
            Start,
            End
        };
        Type type = Unknown;
        int pageIndex = -1;
        QPointF pos;
    };

    struct InternalPosition
    {
        QPointF pos;
        int pageIndex = -1;
        qreal zoom;
    };

    explicit BaseDocument(QObject *parent = nullptr);
    virtual ~BaseDocument();

    DocumentStatus status() const;
    int loadingProgress() const;
    bool processing() const;
    int pageIndex() const;
    Mode mode() const;
    void setMode(Mode newMode);

    virtual QThreadPool *threadPool() const = 0;
    virtual QString path() const;
    virtual QSizeF pageSize(int pageNumber) const = 0;
    virtual int count() const = 0;
    virtual QSharedPointer<BasePage> loadPage(int pageIndex) = 0;
    virtual void startLoadBookmarks() const = 0;
    virtual QVector<BaseBookmark *> bookmarks() const = 0;
    virtual int fileVersion() const = 0;
    virtual bool saveDocumentAs(const QString &path, const QString &format) const = 0;
    virtual BaseDocumentProvider::DocumentType documentType() const = 0;
    virtual QList<QString> pageNames() const = 0;
    virtual QString fileName() const = 0; 
    virtual int error() const = 0;
    virtual void mousePress(const InternalPosition &internaPos) = 0;
    virtual void mouseRelease(const InternalPosition &internaPos) = 0;
    virtual void mouseDoubleClick(const InternalPosition &internaPos) = 0;
    virtual void startSelectText(const InternalPosition &internaPos) = 0;
    virtual void endSelectText(const InternalPosition &internaPos) = 0;
    virtual void resetSelectText() = 0;
    virtual QList<QRect> currentHighlightedSearch(int pageIndex) const = 0;
    virtual QList<QRect> allHighlightedSearch(int pageIndex) const = 0;
    virtual QList<QPair<QString, QRect>> cellSelected(int pageIndex) const = 0;
    virtual QList<QRect> highlightedTextArea(int pageIndex) const = 0;
    virtual QString slsectionText() const = 0;
    virtual QList<QPair<CommentData, QRect>> comments(int pageIndex) const = 0;
    virtual QPair<Marker, Marker> selectionMarkers() const = 0;
    virtual QPair<int, QRect> cursor() const = 0;

public slots:
    virtual void setPath(const QString &path) = 0;
    virtual void sendUnoCommand(const QString &command, const QString &arguments, bool notifyWhenFinished = true) = 0;
    virtual void getUnoCommandValues(const QString &command) = 0;
    virtual void goToCell(const QString &adressCell) = 0;
    virtual void startSearch(const QString &string, BaseDocument::SearchDirection direction, const QPointF &startPosition) = 0;
    virtual void stopSearch() = 0;
    void setLoadingProgress(int loadingProgress);
    void setProcessing(bool processing);
    void setPageIndex(int newPageIndex);

signals:
    void statusChanged(BaseDocument::DocumentStatus status);
    void pathChanged(const QString &path);
    void pageLoaded(int pageNumber, BaseDocument::PageLoadStatus loadStatus);
    void bookmarksLoaded();
    void fileVersionChanged(int version);
    void loadingProgressChanged(int loadingProgress);
    void processingChanged(bool processing);
    void documentTypeChanged();
    void pageNamesChanged();  
    void fileNameChanged();
    void countChanged();
    void errorChanged();
    void hyperlinkClicked(const QString &hyperlink);
    void cellClicked(const QString &content);
    void areaVisibleUpdated(const QRect &rectArea);
    void highlightedUpdated(const QList<QRect> &areaRects, int pageIndex);
    void commentsUpdated(int pageIndex);
    void highlightedAllUpdated();
    void invalidateRect(const QRect &rect, int pageIndex);
    void cellSelectedUpdated(const QList<QRect> &areaRects, int pageIndex);
    void textSelectedUpdated(const QList<QRect> &rects, int pageIndex);
    void showInfo(const QString &info);
    void pageIndexChanged(int pageIndex);
    void saveAsStatusChanged(const QString &path, const QString &format, bool status);
    void cursorChanged(const QRect &rectCursor, int pageIndex);
    void selectionMarkerChanged();
    void selectionTextChanged();
    void modeChanged();

protected:
    DocumentStatus m_status;
    QString m_path;
    int m_loadingProgress;
    bool m_processing;
    int m_pageIndex;
    Mode m_mode;
};
