#ifndef CFRAMELESSWINDOW_H
#define CFRAMELESSWINDOW_H
#include "qsystemdetection.h"
#include <QObject>
#include <QMainWindow>

// A nice frameless window for both Windows and OS X
// Author: Bringer-of-Light
// Github: https://github.com/Bringer-of-Light/Qt-Nice-Frameless-Window
//  Usage: use "CFramelessWindow" as base class instead of "QMainWindow", and enjoy
#ifdef Q_OS_WIN
#include <QWidget>
#include <QList>
#include <QMargins>
#include <QRect>
class CFramelessWindow : public QMainWindow
{
    Q_OBJECT
public:
    explicit CFramelessWindow(QWidget *parent = 0);

public:
    // 设置是否可以通过鼠标调整窗口大小
    // if resizeable is set to false, then the window can not be resized by mouse
    // but still can be resized programtically
    void setResizeable(bool resizeable = true);
    bool isResizeable() { return m_bResizeable; }

    // 设置可调整大小区域的宽度，在此区域内，可以使用鼠标调整窗口大小
    // set border width, inside this aera, window can be resized by mouse
    void setResizeableAreaWidth(int width = 5);

protected:
    // 设置一个标题栏widget，此widget会被当做标题栏对待
    // set a widget which will be treat as SYSTEM titlebar
    void setTitleBar(QWidget *titlebar);

    // 在标题栏控件内，也可以有子控件如标签控件“label1”，此label1遮盖了标题栏，导致不能通过label1拖动窗口
    // 要解决此问题，使用addIgnoreWidget(label1)
    // generally, we can add widget say "label1" on titlebar, and it will cover the titlebar under it
    // as a result, we can not drag and move the MainWindow with this "label1" again
    // we can fix this by add "label1" to a ignorelist, just call addIgnoreWidget(label1)
    void addIgnoreWidget(QWidget *widget);

    bool nativeEvent(const QByteArray &eventType, void *message, long *result);
private slots:
    void onTitleBarDestroyed();

public:
    void setContentsMargins(const QMargins &margins);
    void setContentsMargins(int left, int top, int right, int bottom);
    QMargins contentsMargins() const;
    QRect contentsRect() const;
    void getContentsMargins(int *left, int *top, int *right, int *bottom) const;
public slots:
    void showFullScreen();

private:
    QWidget *m_titlebar;
    QList<QWidget *> m_whiteList;
    int m_borderWidth;

    QMargins m_margins;
    QMargins m_frames;
    bool m_bJustMaximized;

    bool m_bResizeable;
};

#elif defined Q_OS_MAC
#include <QMouseEvent>
#include <QResizeEvent>
#include <QPoint>
class CFramelessWindow : public QMainWindow
{
    Q_OBJECT
public:
    explicit CFramelessWindow(QWidget *parent = 0);

private:
    void initUI();

public:
    // 设置可拖动区域的高度，在此区域内，可以通过鼠标拖动窗口, 0表示整个窗口都可拖动
    // In draggable area, window can be moved by mouse, (height = 0) means that the whole window is draggable
    void setDraggableAreaHeight(int height = 0);

    // 只有OS X10.10及以后系统，才支持OS X原生样式包括：三个系统按钮、窗口圆角、窗口阴影
    // 类初始化完成后，可以通过此函数查看是否已经启用了原生样式。如果未启动，需要自定义关闭按钮、最小化按钮、最大化按钮
    // Native style（three system button/ round corner/ drop shadow） works only on OS X 10.10 or later
    // after init, we should check whether NativeStyle is OK with this function
    // if NOT ok, we should implement close button/ min button/ max button ourself
    bool isNativeStyleOK() { return m_bNativeSystemBtn; }

    // 如果设置setCloseBtnQuit(false)，那么点击关闭按钮后，程序不会退出，而是会隐藏,只有在OS X 10.10 及以后系统中有效
    // if setCloseBtnQuit(false), then when close button is clicked, the application will hide itself instead of quit
    // be carefull, after you set this to false, you can NOT change it to true again
    // this function should be called inside of the constructor function of derived classes, and can NOT be called more than once
    // only works for OS X 10.10 or later
    void setCloseBtnQuit(bool bQuit = true);

    // 启用或禁用关闭按钮，只有在isNativeStyleOK()返回true的情况下才有效
    // enable or disable Close button, only worked if isNativeStyleOK() returns true
    void setCloseBtnEnabled(bool bEnable = true);

    // 启用或禁用最小化按钮，只有在isNativeStyleOK()返回true的情况下才有效
    // enable or disable Miniaturize button, only worked if isNativeStyleOK() returns true
    void setMinBtnEnabled(bool bEnable = true);

    // 启用或禁用zoom（最大化）按钮，只有在isNativeStyleOK()返回true的情况下才有效
    // enable or disable Zoom button(fullscreen button), only worked if isNativeStyleOK() returns true
    void setZoomBtnEnabled(bool bEnable = true);

    bool isCloseBtnEnabled() { return m_bIsCloseBtnEnabled; }
    bool isMinBtnEnabled() { return m_bIsMinBtnEnabled; }
    bool isZoomBtnEnabled() { return m_bIsZoomBtnEnabled; }

protected:
    void mousePressEvent(QMouseEvent *event);
    void mouseReleaseEvent(QMouseEvent *event);
    void mouseMoveEvent(QMouseEvent *event);

private:
    int m_draggableHeight;
    bool m_bWinMoving;
    bool m_bMousePressed;
    QPoint m_MousePos;
    QPoint m_WindowPos;
    bool m_bCloseBtnQuit;
    bool m_bNativeSystemBtn;
    bool m_bIsCloseBtnEnabled, m_bIsMinBtnEnabled, m_bIsZoomBtnEnabled;

    //===============================================
    // TODO
    // 下面的代码是试验性质的
    // tentative code

    // 窗口从全屏状态恢复正常大小时，标题栏又会出现，原因未知。
    // 默认情况下，系统的最大化按钮(zoom button)是进入全屏，为了避免标题栏重新出现的问题，
    // 以上代码已经重新定义了系统zoom button的行为，是其功能变为最大化而不是全屏
    // 以下代码尝试，每次窗口从全屏状态恢复正常大小时，都再次进行设置，以消除标题栏
    // after the window restore from fullscreen mode, the titlebar will show again, it looks like a BUG
    // on OS X 10.10 and later, click the system green button (zoom button) will make the app become fullscreen
    // so we have override it's action to "maximized" in the CFramelessWindow Constructor function
    // but we may try something else such as delete the titlebar again and again...
private:
    bool m_bTitleBarVisible;

    void setTitlebarVisible(bool bTitlebarVisible = false);
    bool isTitlebarVisible() { return m_bTitleBarVisible; }
private slots:
    void onRestoreFromFullScreen();
signals:
    void restoreFromFullScreen();

protected:
    void resizeEvent(QResizeEvent *event);
};
#endif

#endif // CFRAMELESSWINDOW_H
