// SPDX-FileCopyrightText: 2018 - 2026 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include "clipboardmodel.h"
#include "itemdelegate.h"
#include "constants.h"
#include "listview.h"
#include "iconbutton.h"
#include "display1interface.h"
#include "display1monitorinterface.h"
#include "dock1interface.h"
#include "tipswidget.h"

#include <DBlurEffectWidget>
#include <DWindowManagerHelper>
#include <DRegionMonitor>
#include <DDBusInterface>
#include <DPlatformWindowHandle>
#include <DGuiApplicationHelper>
#include <DLabel>
#include <DIconButton>
#include <DConfig>
#include <dde-shell/dlayershellwindow.h>

DCORE_USE_NAMESPACE
DWIDGET_USE_NAMESPACE
DGUI_USE_NAMESPACE

class QPushButton;
class QPropertyAnimation;
class QSequentialAnimationGroup;

using DBusDisplay = org::deepin::dde::Display1;
using DisplayMonitor = org::deepin::dde::display1::Monitor;
using DBusDaemonDock = org::deepin::dde::daemon::Dock1;

/*!
 * \~chinese \class MainWindow
 * \~chinese \brief 主窗口类
 */
class MainWindow : public DBlurEffectWidget
{
    Q_OBJECT
    Q_PROPERTY(int width READ getWidth WRITE setFixedWidth)
    Q_PROPERTY(int x READ getX WRITE setX)

public:
    explicit MainWindow(QWidget *parent = nullptr);
    ~MainWindow() override;

    Q_PROPERTY(double Opacity READ opacity NOTIFY OpacityChanged)
    double opacity();

    void setAlwaysShow(bool alwaysShow) {
        m_alwaysShow = alwaysShow;
    }

protected:
    void paintEvent(QPaintEvent *e) override;
    /*!
     * \~chinese \name initConnect
     * \~chinese \brief 重写mouseMoveEvent事件禁止窗口被移动
     */
    virtual void mouseMoveEvent(QMouseEvent *event) override;
    void showEvent(QShowEvent *event) override;
    void hideEvent(QHideEvent *event) override;
    bool event(QEvent *event) override;
    bool eventFilter(QObject *watched, QEvent *event) override;
    void resizeEvent(QResizeEvent *event) override;

signals:
    void OpacityChanged(double value) const;

public Q_SLOTS:
    /*!
     * \~chinese \name Toggle
     * \~chinese \brief 切换主窗口显示或隐藏的状态
     */
    void Toggle();
    /*!
     * \~chinese \name showAni
     * \~chinese \brief 主窗口显示时的动画
     */
    void showAni();
    /*!
     * \~chinese \name hideAni
     * \~chinese \brief 主窗口隐藏时的动画
     */
    void hideAni();

    void Show();
    void Hide();

Q_SIGNALS: // SIGNALS
    void clipboardVisibleChanged(bool visible);

private Q_SLOTS:
    /*!
     * \~chinese \name geometryChanged
     * \~chinese \brief 根据dock和屏幕的大小改变窗口的大小,根据dock的位置调整主窗口的位置
     */
    void geometryChanged();
    /*!
     * \~chinese \name onFrontendWindowRectChanged
     * \~chinese \brief 根据FrontendWindowRectChanged信号传递的dock矩形区域来调整剪贴板的位置
     * \~chinese \param rect Dock的前端窗口矩形区域
     */
    void onFrontendWindowRectChanged(const QRect &rect);
    /*!
     * \~chinese \name setX
     * \~chinese \brief 设置主窗口X轴的起始坐标
     * \~chinese \param X轴坐标位置
     */
    void setX(int x);
    /*!
     * \~chinese \name CompositeChanged
     * \~chinese \brief 是否开启动画效果
     */
    void CompositeChanged();

    void registerMonitor();

    bool clipboardVisible() const { return isVisible(); }

    void updatePrimaryScreen();
    void updateTipsVisibility();

    void initConfig();

private:
    /*!
     * \~chinese \name initUI
     * \~chinese \brief 初始化界面布局
     */
    void initUI();
    /*!
     * \~chinese \name initAni
     * \~chinese \brief 初始化动画效果
     */
    void initAni();
    /*!
     * \~chinese \name initConnect
     * \~chinese \brief 初始化信号与槽的连接
     */
    void initConnect();
    /*!
     * \~chinese \name adjustPosition
     * \~chinese \brief 调整剪切板位置
     */
    void adjustPosition();
    /*!
     * \~chinese \name getDisplayScreen
     * \~chinese \brief 获取显示屏幕的坐标
     */
    QRect getDisplayScreen();
    /*!
     * \~chinese \name screenForDockCenter
     * \~chinese \brief 根据 dock 中心点所在的屏幕，如果找不到则回退到主屏幕
     * \~chinese \param dockRectInDevicePixels Dock 的设备像素矩形
     * \~chinese \return 包含 dock 的屏幕，如果找不到则返回主屏幕
     */
    QScreen *screenForDockCenter(const QRect &dockRectInDevicePixels) const;

    int getWidth() const { return this->width(); }
    int getX() const { return this->pos().x(); }

    /*!
     * \~chinese \name setFocusToItem
     * \~chinese \brief 设置焦点到指定行的 item
     * \~chinese \param row 行号
     * \~chinese \param focusCloseButton 是否将焦点设置到关闭按钮
     */
    void setFocusToItem(int row, bool focusCloseButton = false);

private:
    DBusDisplay *m_displayInter;
    DBusDaemonDock *m_daemonDockInter;
    DDBusInterface *m_appearanceInter;
    DRegionMonitor *m_regionMonitor;

    DWidget *m_content;
    IconButton *m_clearButton;
    ListView *m_listview;
    ClipboardModel *m_model;
    ItemDelegate *m_itemDelegate;
    DWidget *m_placeholderWidget;
    DIconButton *m_placeholderIcon;
    DLabel *m_placeholderLabel;
    TipsWidget *m_tipsWidget;

    QPropertyAnimation *m_xAni;
    QPropertyAnimation *m_widthAni;
    QSequentialAnimationGroup *m_aniGroup;

    QRect m_rect;

    DWindowManagerHelper *m_wmHelper;
    
    QTimer *m_trickTimer;

    bool m_hasComposite = false;

    bool m_alwaysShow = false;

    DGuiApplicationHelper::ColorType m_themeType;
    int m_cornerRadius;
    DPlatformWindowHandle *m_windowHandle;

    bool m_isWayland;
    
    QMargins m_currentMargins;
    
    bool m_showTipsWidget = true;
};

#endif // MAINWINDOW_H
