/*********************************************************************************************
 * Mozilla License
 * Just a meantime project to see the ability of qt, the framework that my OS might be based on
 * And for those linux users that believe in the power of notes
 *********************************************************************************************/

#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QtGui>
#include <QtCore>
#include <QGroupBox>
#include <QPushButton>
#include <QToolButton>
#include <QVBoxLayout>
#include <QLabel>
#include <QTextEdit>
#include <QSettings>
#include <QSplitter>
#include <QSystemTrayIcon>
#include <QMenu>
#include <QProgressDialog>
#include <QAction>
#include <QAutostart>
#include <QtGlobal>
#include <QWidget>
#include <QQuickView>
#include <QQmlContext>
#include <QVariant>
#include <QJsonObject>
#include <QObject>
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QByteArray>
#include <QQmlApplicationEngine>

#include "nodedata.h"
#include "notelistmodel.h"
#include "notelistview.h"
#include "nodetreemodel.h"

#if defined(UPDATE_CHECKER)
#  include "updaterwindow.h"
#endif

#include "dbmanager.h"
#include "customDocument.h"
#include "aboutwindow.h"
#include "framelesswindow.h"
#include "nodetreeview.h"
#include "editorsettingsoptions.h"

// 定义订阅状态枚举
L_DECLARE_ENUM(SubscriptionStatus, NoSubscription, Active, ActivationLimitReached, Expired, Invalid,
               EnteredGracePeriod, GracePeriodOver, NoInternetConnection, UnknownError)

namespace Ui {
class MainWindow;
}

// 前向声明类
class TreeViewLogic;
class ListViewLogic;
class NoteEditorLogic;
class TagPool;
class SplitterStyle;

#if defined(Q_OS_WINDOWS) || defined(Q_OS_WIN)
// #if defined(__MINGW32__) || defined(__GNUC__)
using MainWindowBase = QMainWindow;
// #else
//  using MainWindowBase = CFramelessWindow;
// #endif
#elif defined(Q_OS_MACOS)
using MainWindowBase = CFramelessWindow;
#else
using MainWindowBase = QMainWindow;
#endif

// 主窗口类
class MainWindow : public MainWindowBase
{
    Q_OBJECT

public:
    enum class ShadowType { Linear = 0, Radial };

    enum class ShadowSide {
        Left = 0,
        Right,
        Top,
        Bottom,
        TopLeft,
        TopRight,
        BottomLeft,
        BottomRight
    };

    enum class StretchSide {
        None = 0,
        Left,
        Right,
        Top,
        Bottom,
        TopLeft,
        TopRight,
        BottomLeft,
        BottomRight
    };

    Q_ENUM(ShadowType)
    Q_ENUM(ShadowSide)
    Q_ENUM(StretchSide)

    // 构造函数
    explicit MainWindow(QWidget *parent = nullptr);
    // 析构函数
    ~MainWindow() override;

    // 设置主窗口可见性
    void setMainWindowVisibility(bool state);

public slots:
    // 保存最近选择的文件夹标签
    void saveLastSelectedFolderTags(bool isFolder, const QString &folderPath,
                                    const QSet<int> &tagId);
    // 保存展开的文件夹
    void saveExpandedFolder(const QStringList &folderPaths);
    // 保存最近选择的笔记
    void saveLastSelectedNote(const QSet<int> &notesId);
    // 从样式按钮改变编辑器字体类型
    void changeEditorFontTypeFromStyleButtons(FontTypeface::Value fontType, int chosenFontIndex);
    // 从样式按钮改变编辑器字体大小
    void changeEditorFontSizeFromStyleButtons(FontSizeAction::Value fontSizeAction);
    // 从样式按钮改变编辑器文本宽度
    void changeEditorTextWidthFromStyleButtons(EditorTextWidth::Value editorTextWidth);
    // 重置编辑器设置
    void resetEditorSettings();
    // 设置主题
    void setTheme(Theme::Value theme);
    // 设置看板可见性
    void setKanbanVisibility(bool isVisible);
    // 折叠笔记列表
    void collapseNoteList();
    // 展开笔记列表
    void expandNoteList();
    // 折叠文件夹树
    void collapseFolderTree();
    // 展开文件夹树
    void expandFolderTree();
    // 设置Markdown启用状态
    void setMarkdownEnabled(bool isMarkdownEnabled);
    // 设置窗口置顶
    void stayOnTop(bool checked);
    // 将当前笔记移至回收站
    void moveCurrentNoteToTrash();
    // 切换编辑器设置
    void toggleEditorSettings();
    // 从快速视图设置编辑器设置可见性
    void setEditorSettingsFromQuickViewVisibility(bool isVisible);
    // 设置编辑器设置滚动条位置
    void setEditorSettingsScrollBarPosition(double position);
    // 设置激活成功的状态
    void setActivationSuccessful(QString licenseKey, bool removeGracePeriodStartedDate = true);
    // 检查专业版
    void checkProVersion();
    // 获取用户许可密钥
    QVariant getUserLicenseKey();

protected:
    // 重新绘制事件
    void paintEvent(QPaintEvent *event) override;
    // 重新调整事件
    void resizeEvent(QResizeEvent *event) override;
    // 关闭事件
    void closeEvent(QCloseEvent *event) override;
    // 鼠标按下事件
    void mousePressEvent(QMouseEvent *event) override;
    // 鼠标移动事件
    void mouseMoveEvent(QMouseEvent *event) override;
    // 移动事件
    void moveEvent(QMoveEvent *event) override;
    // 鼠标释放事件
    void mouseReleaseEvent(QMouseEvent *event) override;
    // 鼠标双击事件
    void mouseDoubleClickEvent(QMouseEvent *event) override;
    // 离开事件
    void leaveEvent(QEvent *) override;
    // 变更事件
    void changeEvent(QEvent *event) override;
    // 事件过滤器
    bool eventFilter(QObject *object, QEvent *event) override;

private:
    // UI界面指针
    Ui::MainWindow *ui;

    // 设置数据库指针
    QSettings *m_settingsDatabase;
    // 清除按钮
    QToolButton *m_clearButton;
    // 搜索按钮
    QToolButton *m_searchButton;
    // 绿色最大化按钮
    QPushButton *m_greenMaximizeButton;
    // 红色关闭按钮
    QPushButton *m_redCloseButton;
    // 黄色最小化按钮
    QPushButton *m_yellowMinimizeButton;
    // 交通灯布局
    QHBoxLayout m_trafficLightLayout;
    // 新笔记按钮
    QPushButton *m_newNoteButton;
    // 点点按钮
    QPushButton *m_dotsButton;
    // 全局设置按钮
    QPushButton *m_globalSettingsButton;
    // 切换树视图按钮
    QPushButton *m_toggleTreeViewButton;
    // 切换文本视图按钮
    QPushButton *m_switchToTextViewButton;
    // 切换看板视图按钮
    QPushButton *m_switchToKanbanViewButton;
    // 文本编辑器
    CustomDocument *m_textEdit;
    // 笔记编辑器逻辑
    NoteEditorLogic *m_noteEditorLogic;
    // 搜索框
    QLineEdit *m_searchEdit;
    // 编辑器日期标签
    QLabel *m_editorDateLabel;
    // 分割器
    QSplitter *m_splitter;
    // 笔记列表小部件
    QWidget *m_noteListWidget;
    // 文件夹小部件
    QWidget *m_foldersWidget;
    // 系统托盘图标
    QSystemTrayIcon *m_trayIcon;
#if !defined(Q_OS_MAC)
    // 恢复动作
    QAction *m_restoreAction;
    // 退出动作
    QAction *m_quitAction;
#endif

    // 笔记列表视图
    NoteListView *m_listView;
    // 笔记列表模型
    NoteListModel *m_listModel;
    // 列表视图逻辑
    ListViewLogic *m_listViewLogic;
    // 节点树视图
    NodeTreeView *m_treeView;
    // 节点树模型
    NodeTreeModel *m_treeModel;
    // 树视图逻辑
    TreeViewLogic *m_treeViewLogic;
#if QT_VERSION >= QT_VERSION_CHECK(6, 2, 0)
    // 看板快速视图
    QQuickView m_kanbanQuickView;
    // 看板小部件
    QWidget *m_kanbanWidget;
#endif
    // 编辑器设置快速视图
    QQuickView m_editorSettingsQuickView;
    // 编辑器设置小部件
    QWidget *m_editorSettingsWidget;
    // 标签池
    TagPool *m_tagPool;
    // 数据库管理器
    DBManager *m_dbManager;
    // 数据库线程
    QThread *m_dbThread;
    // 分割器样式
    SplitterStyle *m_splitterStyle;
#if defined(UPDATE_CHECKER)
    // 更新窗口
    UpdaterWindow m_updater;
#endif
    // 关于窗口
    AboutWindow m_aboutWindow;
    // 拉伸边
    StretchSide m_stretchSide;
    // 自启动
    Autostart m_autostart;
    // 鼠标按下坐标
    int m_mousePressX;
    int m_mousePressY;
    // 回收站计数器
    int m_trashCounter;
    // 布局边距
    int m_layoutMargin;
    // 阴影宽度
    int m_shadowWidth;
    // 节点树宽度
    int m_nodeTreeWidth;
    // 小编辑器宽度
    int m_smallEditorWidth;
    // 大编辑器宽度
    int m_largeEditorWidth;
    // 能否移动窗口
    bool m_canMoveWindow;
    // 能否调整窗口大小
    bool m_canStretchWindow;
    // 临时标志
    bool m_isTemp;
    // 列表视图滚动条隐藏标志
    bool m_isListViewScrollBarHidden;
    // 操作运行标志
    bool m_isOperationRunning;
#if defined(UPDATE_CHECKER)
    // 不显示更新窗口标志
    bool m_dontShowUpdateWindow;
#endif
    // 始终置顶标志
    bool m_alwaysStayOnTop;
    // 使用本机窗口框架标志
    bool m_useNativeWindowFrame;
    // 隐藏到托盘标志
    bool m_hideToTray;

    // 样式表
    QString m_styleSheet;

    // Serif字体列表
    QStringList m_listOfSerifFonts;
    // Sans Serif字体列表
    QStringList m_listOfSansSerifFonts;
    // Mono字体列表
    QStringList m_listOfMonoFonts;
    // 选择的Serif字体索引
    int m_chosenSerifFontIndex;
    // 选择的Sans Serif字体索引
    int m_chosenSansSerifFontIndex;
    // 选择的Mono字体索引
    int m_chosenMonoFontIndex;
    // 编辑器中等字体大小
    int m_editorMediumFontSize;
    // 当前字体大小
    int m_currentFontPointSize;
    struct m_charsLimitPerFont
    {
        int mono;
        int serif;
        int sansSerif;
    } m_currentCharsLimitPerFont;
    // 当前字体类型
    FontTypeface::Value m_currentFontTypeface;
    // 当前字体家族
    QString m_currentFontFamily;
    // 当前选定字体
    QFont m_currentSelectedFont;
    // 显示字体
    QString m_displayFont;
    // 当前主题
    Theme::Value m_currentTheme;
    // 当前编辑器文本颜色
    QColor m_currentEditorTextColor;
    // 非编辑器小部件可见性标志
    bool m_areNonEditorWidgetsVisible;
#if !defined(Q_OS_MAC)
    // 文本编辑滚动条定时器
    QTimer *m_textEditScrollBarTimer;
    // 文本编辑滚动条定时器持续时间
    int m_textEditScrollBarTimerDuration;
#endif
    // 帧右上小部件可见性标志
    bool m_isFrameRightTopWidgetsVisible;
    // 从快速视图可见的编辑器设置标志
    bool m_isEditorSettingsFromQuickViewVisible;
    // 专业版激活标志
    bool m_isProVersionActivated;
    // 本地许可数据
    QSettings *m_localLicenseData;
    // 支付详情
    QJsonObject m_paymentDetails;
    // 订阅状态
    SubscriptionStatus::Value m_subscriptionStatus;
    // 订阅窗口快速视图
    QQuickView m_subscriptionWindowQuickView;
    // 订阅窗口小部件
    QWidget *m_subscriptionWindowWidget;
    // 订阅窗口引擎
    QQmlApplicationEngine m_subscriptionWindowEngine;
    // 订阅窗口
    QWindow *m_subscriptionWindow;
    // 购买数据备用1
    QString m_purchaseDataAlt1;
    // 购买数据备用2
    QString m_purchaseDataAlt2;
    // 数据缓冲区
    QByteArray *m_dataBuffer;
    // 网络访问管理器
    QNetworkAccessManager *m_netManager;
    // 备用请求1
    QNetworkRequest m_reqAlt1;
    // 备用请求2
    QNetworkRequest m_reqAlt2;
    // 第一次尝试的网络购买数据回复
    QNetworkReply *m_netPurchaseDataReplyFirstAttempt;
    // 第二次尝试的网络购买数据回复
    QNetworkReply *m_netPurchaseDataReplySecondAttempt;
    // 用户许可密钥
    QString m_userLicenseKey;
    // 主菜单
    QMenu m_mainMenu;
    // 购买或管理订阅动作
    QAction *m_buyOrManageSubscriptionAction;

    // 检查格式是否已应用
    bool alreadyAppliedFormat(const QString &formatChars);
    // 应用格式
    void applyFormat(const QString &formatChars);
    // 设置主窗口
    void setupMainWindow();
    // 设置字体
    void setupFonts();
    // 设置托盘图标
    void setupTrayIcon();
    // 设置快捷键
    void setupKeyboardShortcuts();
    // 设置分割器
    void setupSplitter();
    // 设置按钮
    void setupButtons();
    // 设置信号与槽
    void setupSignalsSlots();
#if defined(UPDATE_CHECKER)
    // 自动检查更新
    void autoCheckForUpdates();
#endif
    // 设置搜索框
    void setupSearchEdit();
    // 设置订阅窗口
    void setupSubscrirptionWindow();
    // 设置编辑器样式表
    void setupTextEditStyleSheet(int paddingLeft, int paddingRight);
    // 对齐文本编辑器文本
    void alignTextEditText();
    // 设置文本编辑器
    void setupTextEdit();
#if QT_VERSION >= QT_VERSION_CHECK(6, 2, 0)
    // 设置看板视图
    void setupKanbanView();
#endif
    // 设置数据库
    void setupDatabases();
    // 设置模型视图
    void setupModelView();
    // 设置全局设置菜单
    void setupGlobalSettingsMenu();
    // 初始化设置数据库
    void initializeSettingsDatabase();
    // 为滚动区域设置布局
    void setLayoutForScrollArea();
    // 设置按钮和字段的启用状态
    void setButtonsAndFieldsEnabled(bool doEnable);
    // 重置格式
    void resetFormat(const QString &formatChars);
    // 恢复状态
    void restoreStates();
    // 从版本0.9.0迁移
    void migrateFromV0_9_0();
    // 执行导入
    void executeImport(const bool replace);
    // 从版本0.9.0迁移笔记
    void migrateNoteFromV0_9_0(const QString &notePath);
    // 从版本0.9.0迁移回收站
    void migrateTrashFromV0_9_0(const QString &trashPath);
    // 根据字体类型设置当前字体
    void setCurrentFontBasedOnTypeface(FontTypeface::Value selectedFontTypeFace);
    // 设置右侧小部件可见性
    void setVisibilityOfFrameRightWidgets(bool isVisible);
    // 设置非编辑器小部件可见性
    void setVisibilityOfFrameRightNonEditor(bool isVisible);
    // 设置窗口按钮可见性
    void setWindowButtonsVisible(bool isVisible);
    // 显示编辑器设置
    void showEditorSettings();
    // 更新选定的编辑器设置选项
    void updateSelectedOptionsEditorSettings();
    // 添加阴影
    void dropShadow(QPainter &painter, ShadowType type, ShadowSide side);
    // 使用渐变填充矩形
    void fillRectWithGradient(QPainter &painter, QRect rect, QGradient &gradient);
    // 高斯分布
    double gaussianDist(double x, const double center, double sigma) const;
    // 调整并定位编辑器设置窗口
    void resizeAndPositionEditorSettingsWindow();
    // 获取支付详情信号与槽
    void getPaymentDetailsSignalsSlots();
    // 验证许可证信号与槽
    void verifyLicenseSignalsSlots();
    // 获取订阅状态
    void getSubscriptionStatus();

    // 设置边距
    void setMargins(QMargins margins);

private slots:
    // 初始化数据
    void InitData();

    // 系统托盘图标激活
    void onSystemTrayIconActivated(QSystemTrayIcon::ActivationReason reason);
    // 新笔记按钮点击
    void onNewNoteButtonClicked();
    // 点点按钮点击
    void onDotsButtonClicked();
    // 切换到看板视图按钮点击
    void onSwitchToKanbanViewButtonClicked();
    // 全局设置按钮点击
    void onGlobalSettingsButtonClicked();
    // 清除按钮点击
    void onClearButtonClicked();
    // 绿色最大化按钮按下
    void onGreenMaximizeButtonPressed();
    // 黄色最小化按钮按下
    void onYellowMinimizeButtonPressed();
    // 红色关闭按钮按下
    void onRedCloseButtonPressed();
    // 绿色最大化按钮点击
    void onGreenMaximizeButtonClicked();
    // 黄色最小化按钮点击
    void onYellowMinimizeButtonClicked();
    // 红色关闭按钮点击
    void onRedCloseButtonClicked();
    // 重置块格式
    void resetBlockFormat();
    // 创建新笔记
    void createNewNote();
    // 向下选择笔记
    void selectNoteDown();
    // 向上选择笔记
    void selectNoteUp();
    // 设置文本焦点
    void setFocusOnText();
    // 全屏窗口
    void fullscreenWindow();
    // 制作代码
    void makeCode();
    // 制作粗体
    void makeBold();
    // 制作斜体
    void makeItalic();
    // 制作删除线
    void makeStrikethrough();
    // 最大化窗口
    void maximizeWindow();
    // 最小化窗口
    void minimizeWindow();
    // 退出应用程序
    void QuitApplication();
#if defined(UPDATE_CHECKER)
    // 检查更新
    void checkForUpdates();
#endif
    // 切换笔记列表
    void toggleNoteList();
    // 切换文件夹树
    void toggleFolderTree();
    // 导入笔记文件
    void importNotesFile();
    // 导出笔记文件
    void exportNotesFile();
    // 恢复笔记文件
    void restoreNotesFile();
    // 增加标题
    void increaseHeading();
    // 减小标题
    void decreaseHeading();
    // 设置标题
    void setHeading(int level);
    // 设置使用本机窗口框架
    void setUseNativeWindowFrame(bool useNativeWindowFrame);
    // 设置隐藏到托盘
    void setHideToTray(bool enabled);
    // 切换始终置顶
    void toggleStayOnTop();
    // 搜索框回车按下
    void onSearchEditReturnPressed();
    // 删除选中笔记
    void deleteSelectedNote();
    // 清除搜索框
    void clearSearch();
    // 显示错误信息
    void showErrorMessage(const QString &title, const QString &content);
    // 设置笔记列表加载状态
    void setNoteListLoading();
    // 选择所有笔记
    void selectAllNotesInList();
    // 更新框架
    void updateFrame();
    // 检查是否是标题栏
    bool isTitleBar(int x, int y) const;
    // 打开订阅窗口
    void openSubscriptionWindow();

signals:
    // 请求节点树
    void requestNodesTree();
    // 请求打开数据库管理器
    void requestOpenDBManager(const QString &path, bool doCreate);
    // 请求恢复笔记
    void requestRestoreNotes(const QString &filePath);
    // 请求导入笔记
    void requestImportNotes(const QString &filePath);
    // 请求导出笔记
    void requestExportNotes(QString fileName);
    // 请求从版本0.9.0迁移笔记
    void requestMigrateNotesFromV0_9_0(QVector<NodeData> &noteList);
    // 请求从版本0.9.0迁移回收站
    void requestMigrateTrashFromV0_9_0(QVector<NodeData> &noteList);
    // 请求从版本1.5.0迁移笔记
    void requestMigrateNotesFromV1_5_0(const QString &path);
    // 请求更改数据库路径
    void requestChangeDatabasePath(const QString &newPath);
    // 主题变化信号
    void themeChanged(QVariant theme);
    // 平台设置信号
    void platformSet(QVariant platform);
    // Qt版本设置信号
    void qtVersionSet(QVariant qtVersion);
    // 编辑器设置显示信号
    void editorSettingsShowed(QVariant data);
    // 主窗口大小改变信号
    void mainWindowResized(QVariant data);
    // 主窗口移动信号
    void mainWindowMoved(QVariant data);
    // 设置显示字体信号
    void displayFontSet(QVariant data);
    // 设置改变信号
    void settingsChanged(QVariant data);
    // 字体改变信号
    void fontsChanged(QVariant data);
    // 切换编辑器设置快捷键触发信号
    void toggleEditorSettingsKeyboardShorcutFired();
    // 编辑器设置滚动条位置改变信号
    void editorSettingsScrollBarPositionChanged(QVariant data);
    // 专业版检查信号
    void proVersionCheck(QVariant data);
    // 尝试获取第二种购买数据
    void tryPurchaseDataSecondAlternative();
    // 远程获取支付详情完成信号
    void fetchingPaymentDetailsRemotelyFinished();
    // 获取支付详情完成信号
    void gettingPaymentDetailsFinished();
    // 订阅状态改变信号
    void subscriptionStatusChanged(QVariant subscriptionStatus);
};

#endif // MAINWINDOW_H