/*
 * Copyright (C) 2022, KylinSoft Co., Ltd.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Library General Public License as
 * published by the Free Software Foundation; either version 2, or
 * (at your option) any later version.
 *
 * This program 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 Library General Public
 * License along with this program; if not, write to the
 * Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */

#ifndef WINDOWMANAGERINTERFACE_H
#define WINDOWMANAGERINTERFACE_H

#include <QObject>
#include <QIcon>
#include <QList>
#include <QMap>
#include <QRect>
#include <QVariantList>
#include <QString>
#include "multitaskviewabstractmodelhandler.h"
#include "screens-manager.h"

class QGSettings;
class Window;

class WindowManagerInterface : public QObject
{
    Q_OBJECT
    Q_PROPERTY(int logicalScreenCount READ logicalScreenCount NOTIFY screenCountChanged)
    Q_PROPERTY(int highlightDesktop READ getCurrentDesktop  WRITE setCurrentDesktop NOTIFY currentDesktopChanged)
    Q_PROPERTY(bool isTabletMode READ isTabletMode NOTIFY tabletModeChanged)
    Q_PROPERTY(bool isTouchState READ isTouchState NOTIFY touchStateChanged)
    Q_PROPERTY(QList<QRect> screenRectList READ screenRectList NOTIFY screenRectListChanged)

public:
    static WindowManagerInterface *getInstance();
    ~WindowManagerInterface();

    Q_INVOKABLE QString getCurrentLanguage() const;
    Q_INVOKABLE QString getUKUIStyleName() const;
    Q_INVOKABLE double getUKUIFontSize() const;
    Q_INVOKABLE QString getUKUIFont() const;
    Q_INVOKABLE int getRadius(QString type) const;
    void setIsOpenGLBackend(bool isOpenGLBackend);

    Q_INVOKABLE QRect getFullScreenGeometry(int desktopIndex, int screenIndex) const;

    // window
    Q_INVOKABLE void removeAppWindow(QString windowId);
    Q_INVOKABLE void moveAppWindowToDesktop(QString windowId, int srcDesktopInex, int destDesktopInex) const;
    Q_INVOKABLE void activateAppWindow(QString windowId);
    Q_INVOKABLE QVariant getWindowIcon(QString windowId);
    Q_INVOKABLE bool hasModalChildWindow(QString windowId);

    // desktop
    Q_INVOKABLE void removeDesktop(int desktopIndex);
    Q_INVOKABLE void moveDesktop(int srcDesktopIndex, int destDesktopIndex);
    Q_INVOKABLE void appendDesktop();
    Q_INVOKABLE void setCurrentDesktop(int desktopIndex);
    Q_INVOKABLE QList<Window> createWindowList(int desktopIndex, int screenIndex);
    Q_INVOKABLE QString getDesktopUuid(int desktopIndex);
    Q_INVOKABLE QString getOutputUuid(int outputIndex);
    Q_INVOKABLE void removeAllAppWindowOnDesktop(int desktopIndex, int screenIndex);
    Q_INVOKABLE bool isCurrentDesktopShowingDesktop() const;
    Q_INVOKABLE bool currentDesktopHasWindow() const;
    void setDesktopName(const int desktopIndex, const QString name);

    int getNumberOfDesktops() const;
    int getCurrentDesktop() const;

    int logicalScreenCount() const;
    bool isTabletMode() const;
    bool isTouchState() const;

    QStringList getDesktopNames() const;
    void saveDesktopNames(const QStringList &nameList);

    QList<QRect> screenRectList();
    void updateScreenRectList();

signals:
    void appWindowCreated();
    void appWindowAdd(const Window &window);
    void appWindowRemoved(QString windowId);
    void appWindowUpdated(const Window &window);
    void appWindowActivated();
    void appWindowDesktopChanged(QString windowId, int oldDesktopIndex,int newDesktopIndex);
    void desktopRemoved(int desktopIndex);
    void desktopAppended(int desktopIndex);
    void desktopMoved(int oldDesktopIndex, int newDesktopIndex);
    void desktopNumberChanged();
    void currentDesktopChanged(int oldCurrentDesktopIndex, int newCurrentDesktopIndex);
    void screenCountChanged();
    void screenSizeChanged();
    void tabletModeChanged(bool);
    void touchStateChanged(bool);
    void screenRectListChanged();
    void logicalScreenCountChanged();

private slots:
    void onMouseCountChanged(const int count);
    void onTouchpadCountChanged(const int count);
    void onScreenSizeChanged();
    void onScreenAdd(Screen *screen);
    void onScreenRemove();

private:
    explicit WindowManagerInterface(QObject *parent = nullptr);
    bool isExtensionMode();
    bool validateDesktopIndex(int desktopIndex) const;
    bool validateScreenIndex(int screenIndex) const;
    void connectSignals();
    int getUKUIRadius(QString type) const;

    /**
     * @brief "TouchState"是否处于无鼠标触摸屏场景
     */
    void initTouchState();
    void updateTouchState();

    /**
     * @brief 异步获取指针类设备数量
     * @param 获取某类设备的dbus方法名称
     * @param callback
     */
    void asyncGetGenericPointerCount(const QString &destination, const QString &path,
                                     const QString &interface, const QString &method);

private:
    QGSettings* m_settings = nullptr;
    bool m_isOpenGLBackend = true;
    MultitaskViewAbstractModelHandler *m_modelhandler = nullptr;
    bool m_isTouchState = false;
    bool m_mouseAvailable = true;
    bool m_touchpadAvailable = true;
    bool m_flagNeedGetMouse = true;
    bool m_flagNeedGetTouchpad = true;
    ScreensManager *m_screenManager = nullptr;
    QList<QRect> m_screenRectList;
};

#endif // WINDOWMANAGERINTERFACE_H
