/*
 * Copyright (C) 2023 Tianjin KYLIN Information Technology Co., Ltd.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3, 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 General Public License
 * along with this program; if not, see <http://www.gnu.org/licenses/>.
 *
**/
#include "fullbackgroundwidget.h"
#include "../lock-dialog/lockdialogmodel.h"
#include "utils.h"
#include "lockwidget.h"
#include "agreementwindow.h"
#include <QDesktopWidget>
#include <QApplication>
#include <QX11Info>
#include <QTimer>
#include <QPainterPath>
#include <QDBusInterface>
#include <QDBusMessage>
#include <QDebug>
#include <QTimer>
#include <syslog.h>
#include <QWindow>
#include "grab-x11.h"
#include <unistd.h>
#include <X11/extensions/XTest.h>
#include <X11/keysym.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <QPainter>
#include <QScreen>
#include <KWindowSystem>
#include "commonfunc.h"
#include "screensavermode.h"
#include "screensaverwidget.h"

FullBackgroundWidget::FullBackgroundWidget(LockDialogModel *model, QWidget *parent)
    : QWidget(parent)
    , m_modelLockDialog(model)
{
    initCurrentBackground();
    initUI();
    initConnections();
}

FullBackgroundWidget::~FullBackgroundWidget()
{
    if (m_backgrondGradationTimer)
    {
        if (m_backgrondGradationTimer->isActive())
            m_backgrondGradationTimer->stop();
        m_backgrondGradationTimer->disconnect();
        m_backgrondGradationTimer->deleteLater();
    }


}
void FullBackgroundWidget::initUI()
{
    if(QX11Info::isPlatformX11()){
        /*捕获键盘，如果捕获失败，则可能是由于弹出菜单项已经捕获，那么模拟一次esc按键来退出菜单，如果仍捕获失败，则放弃锁屏，避免密码无法输入*/
        if(establishGrab())
            qDebug()<<"establishGrab : true";
        else {
            qDebug()<<"establishGrab : false";
            /*检测当前是否存在弹出菜单，只有存在弹出菜单时，才模拟按键esc*/
            if(checkHasPopupMenu()){
                XTestFakeKeyEvent(QX11Info::display(), XKeysymToKeycode(QX11Info::display(),XK_Escape), True, 1);
                XTestFakeKeyEvent(QX11Info::display(), XKeysymToKeycode(QX11Info::display(),XK_Escape), False, 1);
                XFlush(QX11Info::display());
                sleep(1);
            }
            if(!establishGrab())
            {
                exit(1);
            }
        }
    }

    setMouseTracking(true);
    QDesktopWidget *desktop = QApplication::desktop();
    setGeometry(desktop->geometry());

    if (!m_lockWidget) {
        m_lockWidget = new LockWidget(m_modelLockDialog, this);
        connect(m_lockWidget, &LockWidget::authSucceed, this, &FullBackgroundWidget::onAuthSucceed);
        m_lockWidget->setGeometry(this->geometry());
        m_lockWidget->show();
    }

    /*
     * 还差判断秒级登录或处于登录界面时才显示，等整体开发完后再调试。
     */

    if(m_modelLockDialog->getAgreementWindowShowLoginPrompt()){
        bool hideTitle = m_modelLockDialog->getAgreementWindowHideTitle();
        QString title = m_modelLockDialog->getAgreementWindowPromptTitle();
        QString text = m_modelLockDialog->getAgreementWindowText();

        //文本内容不为空 且 如果配置了标题，则标题不为空
        if(!text.isEmpty() && (hideTitle || (!hideTitle && !text.isEmpty()))){
            m_agreementWindow = new AgreementWindow(hideTitle,title,text,this);
            m_lockWidget->hide();
            m_agreementWindow->setGeometry(this->geometry());
            m_agreementWindow->show();
            connect(m_agreementWindow, &AgreementWindow::switchToGreeter, this,
                    [this]() {
                m_agreementWindow->hide();
                m_lockWidget->show();
                update();
            });
        }
    }

    setWindowFlags(Qt::FramelessWindowHint | Qt::X11BypassWindowManagerHint);
    KWindowSystem::setType(this->winId(), NET::ScreenLock);

    qApp->installNativeEventFilter(this);
    installEventFilter(this);
}

bool FullBackgroundWidget::eventFilter(QObject *obj, QEvent *event)
{
    static bool isFirstActive = true;

    if (!QX11Info::isPlatformX11()) {
        if(event->type() == QEvent::MouseButtonPress || event->type() == QEvent::MouseMove || event->type() == 7){
            if(screenStatus & SCREEN_SAVER && !isBlank){
                onClearScreensaver();
            }
        }
    }

    if(event->type() == QEvent::WindowDeactivate){
         QTimer::singleShot(50,this,SLOT(laterActivate()));
    } else if(event->type() == QEvent::WindowActivate){
        if (isFirstActive) {
            isFirstActive = false;
            syslog(LOG_INFO, "[ukui-screensaver-dialog] window active event!!");
        }
        QTimer::singleShot(500,this,SLOT(setLockState()));
        //QTimer::singleShot(200,this,SLOT(killWindow()));
    }
    return QWidget::eventFilter(obj, event);
}

void FullBackgroundWidget::initConnections()
{
    // 监听全屏窗口变化
    QDesktopWidget *desktop = QApplication::desktop();
    connect(desktop, &QDesktopWidget::resized,
            this, &FullBackgroundWidget::onDesktopResized);
    connect(desktop, &QDesktopWidget::workAreaResized,
            this, &FullBackgroundWidget::onDesktopResized);
     connect(desktop, &QDesktopWidget::primaryScreenChanged,
            this, &FullBackgroundWidget::onDesktopResized);
    connect(desktop, &QDesktopWidget::screenCountChanged,
            this, &FullBackgroundWidget::onDesktopResized);
    // 监听休眠、睡眠、唤醒
    connect(m_modelLockDialog, SIGNAL(prepareForSleep(bool)), this, SLOT(onPrepareForSleep(bool)));
    connect(m_modelLockDialog, &LockDialogModel::currentUserChanged, this, &FullBackgroundWidget::onCurUserChanged);
    connect(m_modelLockDialog, &LockDialogModel::showLock, this, &FullBackgroundWidget::onShowLock);
    connect(m_modelLockDialog, &LockDialogModel::showBlankScreensaver, this, &FullBackgroundWidget::onShowBlankScreensaver);
    connect(m_modelLockDialog, &LockDialogModel::showLockScreensaver, this, &FullBackgroundWidget::onShowLockScreensaver);
    connect(m_modelLockDialog, &LockDialogModel::showScreensaver, this, &FullBackgroundWidget::onShowScreensaver);
    connect(m_modelLockDialog, &LockDialogModel::showSessionIdle, this, &FullBackgroundWidget::onShowSessionIdle);
    connect(m_modelLockDialog, &LockDialogModel::SecondRunParam, this, &FullBackgroundWidget::onSecondRunParam);

}

void FullBackgroundWidget::setLockState()
{
    if(m_bIsLockState == true)
        return ;

    m_bIsLockState = true;
    QString displayNum = QString(qgetenv("DISPLAY")).replace(":", "").replace(".", "_");
    QString sessionDbus = QString("%1%2").arg(QString(SS_DBUS_SERVICE)).arg(displayNum);
    QDBusInterface *interface = new QDBusInterface(sessionDbus,
                                                      SS_DBUS_PATH,
                                                      SS_DBUS_INTERFACE);
    if (!interface->isValid()) {
        delete interface;
        interface = new QDBusInterface(SS_DBUS_SERVICE,
                                       SS_DBUS_PATH,
                                       SS_DBUS_INTERFACE);
    }
    QDBusMessage msg = interface->call("SetLockState");
    if(msg.type() == QDBusMessage::ErrorMessage)
           qDebug() << msg.errorMessage();
    interface->deleteLater();
}

void FullBackgroundWidget::onSecondRunParam(const QString &str)
{
    qDebug()<<"onSecondRunParam"<<str;
    if(str == "SleepLock"){
        onShowBlankScreensaver(0,true);
    }else if(str == "ScreensaverLock"){
        onShowLockScreensaver();
    }else if(str == "StartupLock"){
        onShowLock(true);
    }else if(str == "CmdLock"){
    	onShowLock(true);
    }else if(str == "CloseLock"){
        onShowBlankScreensaver(1000,false);
    }else if(str == "SessionIdle"){
   	onShowLock(false); 
    }
}

void FullBackgroundWidget::onShowBlankScreensaver(int nDelay, bool isHasLock)
{
    show();
    Q_EMIT m_modelLockDialog->lockStateChanged(true);

    if (isHasLock) {
        screenStatus = (ScreenStatus)(screenStatus | SCREEN_SAVER | SCREEN_LOCK);
    } else {
        screenStatus = (ScreenStatus)(screenStatus | SCREEN_SAVER);
    }
    
    for(auto screen : QGuiApplication::screens())
    {
        ScreenSaver *saver = m_modelLockDialog->getScreensaver();
        saver->mode = SaverMode(SAVER_BLANK_ONLY);
        ScreenSaverWidget *saverWidget = new ScreenSaverWidget(saver, this);
        widgetXScreensaverList.push_back(saverWidget);
        saverWidget->setGeometry(screen->geometry());
    }

    setCursor(Qt::BlankCursor);
    isBlank = true;

    if (0 == nDelay) {
        /*在进行压力测试时，可能会出现锁屏界面启动极慢，导致在睡眠之前调用了锁屏，但
        * 锁屏没来得及绑定睡眠唤醒信号，导致唤醒后，锁屏界面没有收到信号从而一直显示黑屏的问题。
        * 因此这里在进入黑色屏保时，通过后台接口，获取一次当前是否应该显示黑色屏保状态*/
        bool ret = Q_EMIT m_modelLockDialog->GetBlankState();
        if(!ret){
            //isBlank = false;
            //onClearScreensaver();
        }
    }else{
    	QTimer::singleShot(nDelay, this, [=](){
            if (isBlank) {
                isBlank = false;
                onClearScreensaver();
            }
        });
    }
}

void FullBackgroundWidget::onShowLock(bool isStartup)
{
    screenStatus = (ScreenStatus)(screenStatus | SCREEN_LOCK);
    m_isStartupMode = isStartup;
    show();
    Q_EMIT m_modelLockDialog->setCurrentUser(m_modelLockDialog->defaultUserName());
    Q_EMIT m_modelLockDialog->lockStateChanged(true);
    if(m_lockWidget)
        m_lockWidget->show();
}

void FullBackgroundWidget::onShowSessionIdle()
{
    onShowScreensaver(); 
    delayLockScreen();
    Q_EMIT m_modelLockDialog->lockStateChanged(true);
}

void FullBackgroundWidget::onShowLockScreensaver()
{
    onShowLock(false);
    onShowScreensaver();
}

void FullBackgroundWidget::onShowScreensaver()
{
    screenStatus = (ScreenStatus)(screenStatus | SCREEN_SAVER);

    for(auto screen : QGuiApplication::screens())
    {
        ScreenSaver *saver = m_modelLockDialog->getScreensaver();
        /*锁屏设置的Qt::WA_TranslucentBackground属性会导致第三方屏保变得透明，因此在使用第三方屏保时
        * 取消该属性，清除屏保时再设置回来*/
        if(saver->path != "/usr/lib/ukui-screensaver/ukui-screensaver-default")
        {
        //	    setAttribute(Qt::WA_TranslucentBackground,false);
        }

        ScreenSaverWidget *saverWidget = new ScreenSaverWidget(saver, this);
        qDebug() << " new ScreenSaverWidget";
        widgetXScreensaverList.push_back(saverWidget);
        //深色模式有一像素的白边，所以主屏幕向左，向右移一个像素点;这种操作后，外显上方仍旧会有一个像素的白边，暂时不对外显做偏移处理
        if(screen == qApp->primaryScreen()) {
            saverWidget->setGeometry(screen->geometry().x()-1, screen->geometry().y()-1,
                                     screen->geometry().width()+1, screen->geometry().height()+1);
        } else {
            saverWidget->setGeometry(screen->geometry());
        }
    }
    show();
    Q_EMIT m_modelLockDialog->lockStateChanged(true);
}

void FullBackgroundWidget::onClearScreensaver()
{
    screenStatus = (ScreenStatus)(screenStatus & ~SCREEN_SAVER);

    for(auto widget : widgetXScreensaverList)
    {
        widget->close();
    }
    widgetXScreensaverList.clear();

    unsetCursor();

    if(screenStatus == UNDEFINED)
    {
        onCloseScreensaver();
    }
    else
    {
        onShowLock(false);
    }

}

void FullBackgroundWidget::delayLockScreen()
{
    qDebug()<<"delayLockScreen"<<m_modelLockDialog->getLockTimeout()<<m_modelLockDialog->getLockEnabled();

    if (!m_timerLock) {
        m_timerLock = new QTimer(this);
        connect(m_timerLock, &QTimer::timeout, this, &FullBackgroundWidget::onLockScreenTimeout);
    }

    if (m_modelLockDialog->getLockTimeout() != -1 && m_modelLockDialog->getLockEnabled()) {
        stopDelayLockScreen();
        m_timerLock->start(m_modelLockDialog->getLockTimeout()*1000);
    }
}

void FullBackgroundWidget::stopDelayLockScreen()
{
    if (m_timerLock && m_timerLock->isActive()) {
        m_timerLock->stop();
    }
}

void FullBackgroundWidget::onLockScreenTimeout()
{
    qDebug()<<"onLockScreenTimeout:"<<m_modelLockDialog->getLockEnabled();
    if (m_modelLockDialog->getLockEnabled()) {
        screenStatus = (ScreenStatus)(screenStatus | SCREEN_LOCK);
    }
    m_timerLock->stop();
}

void FullBackgroundWidget::onCloseScreensaver()
{
    hide();
    Q_EMIT m_modelLockDialog->lockStateChanged(false);
    stopDelayLockScreen();
    screenStatus = UNDEFINED;
}

void FullBackgroundWidget::onShowPowerManager()
{
    show();
    Q_EMIT m_modelLockDialog->lockStateChanged(true);
}

void FullBackgroundWidget::onDesktopResized()
{
    qDebug() << "[FullBackgroundWidget] [onDesktopResized]";
    QDesktopWidget *desktop = QApplication::desktop();
    setGeometry(desktop->geometry());
    if(m_lockWidget)
        this->onCursorMoved(QCursor::pos());
    update();
}

void FullBackgroundWidget::onPrepareForSleep(bool sleep)
{
    ///系统休眠时，会关闭总线，导致设备不可用，发生错误
    ///在系统休眠之前停止认证，在系统唤醒后重新开始认证
    qDebug()<<"onPrepareForSleep:"<<sleep;

    if(!isVisible()){
       return ;
    }
    if(sleep)
    {
        if(m_lockWidget)
            m_lockWidget->stopAuth();
        //uninhibit();
    }
    else
    {
        if(screenStatus & SCREEN_SAVER)
        {
            isBlank = false;
            onClearScreensaver();
        }else{
            repaint();
            if(m_lockWidget)
                m_lockWidget->startAuth();
            //inhibit();
        }
    }

}

void FullBackgroundWidget::mousePressEvent(QMouseEvent *e)
{
    //close();
}

QString FullBackgroundWidget::getFocusWindowName()
{
    Window focus = 0;
    int    rev = 0;

    XGetInputFocus (QX11Info::display(), &focus, &rev);
    return  getWindowNameFromWid(focus);
}

QString FullBackgroundWidget::getWindowNameFromWid(WId window)
{
    XClassHint ch;
    ch.res_name = NULL;
    ch.res_class = NULL;
    XGetClassHint (QX11Info::display(),window, &ch);

    QString nameStr = QString(ch.res_name);

    if (ch.res_name)
        XFree(ch.res_name);
    if (ch.res_class)
        XFree(ch.res_class);

    return nameStr;
}

int FullBackgroundWidget::RegisteSubWnd(quint64 uWndId)
{
    if (!m_listWndIds.contains(uWndId) && m_listWndIds.size() < SUBWND_COUNT_MAX) {
        m_listWndIds.append(uWndId);
        qDebug()<<"RegisterSubWnd:"<<uWndId;
        //QTimer::singleShot(50,this,SLOT(laterActivate()));
        return m_listWndIds.size();
    } else {
        return -1;
    }
}

int FullBackgroundWidget::UnRegisteSubWnd(quint64 uWndId)
{
    if (m_listWndIds.contains(uWndId)) {
        m_listWndIds.removeAll(uWndId);
        qDebug()<<"UnRegisterSubWnd:"<<uWndId;
        //QTimer::singleShot(50,this,SLOT(laterActivate()));
        return m_listWndIds.size();
    } else {
        return -1;
    }
}

QList<quint64> FullBackgroundWidget::GetSubWndIds()
{
    return m_listWndIds;
}

void FullBackgroundWidget::onCursorMoved(const QPoint &pos)
{
    if(!m_lockWidget)
    {
        return;
    }
    bool chkInOneScreen = false;
    for(auto screen : QGuiApplication::screens())
    {
        if(screen == qApp->primaryScreen()){
            qInfo()<<"LockWidget:"<<screen->geometry()<<m_lockWidget->geometry();
            m_lockWidget->hide();
            m_lockWidget->setGeometry(screen->geometry());
            m_lockWidget->show();
            chkInOneScreen = true;
            break;
        }
    }
    if (!chkInOneScreen) {
        for(auto screen : QGuiApplication::screens()) {
            if(!screen){
                /*避免切换时闪烁*/
                qInfo()<<"LockWidget:"<<screen->geometry()<<m_lockWidget->geometry()<<","<<screen;
                m_lockWidget->hide();
                m_lockWidget->setGeometry(screen->geometry());
                m_lockWidget->show();
                chkInOneScreen = true;
                break;
            }
        }
    }
}

void FullBackgroundWidget::fakeFocusIn(WId window)
{
    // We have keyboard grab, so this application will
    // get keyboard events even without having focus.
    // Fake FocusIn to make Qt realize it has the active
    // window, so that it will correctly show cursor in the dialog.
    XEvent ev;
    memset(&ev, 0, sizeof(ev));
    ev.xfocus.display = QX11Info::display();
    ev.xfocus.type = FocusIn;
    ev.xfocus.window = window;
    ev.xfocus.mode = NotifyNormal;
    ev.xfocus.detail = NotifyAncestor;
    XSendEvent( QX11Info::display(), window, False, NoEventMask, &ev );
    XFlush(QX11Info::display());
}

void FullBackgroundWidget::laterActivate()
{
    if(!QX11Info::isPlatformX11())
        return ;
    XSetInputFocus(QX11Info::display(),this->winId(),RevertToParent,CurrentTime);
    activateWindow();
}

void FullBackgroundWidget::showEvent(QShowEvent *event)
{
    if(QX11Info::isPlatformX11())
        tryGrabKeyboard();
}

void FullBackgroundWidget::tryGrabKeyboard()
{
    if (window()->windowHandle() && window()->windowHandle()->setKeyboardGrabEnabled(true)) {
        m_tryGrabTimes = 0;
        return;
    }

    m_tryGrabTimes++;

    if (m_tryGrabTimes == 15) {
        qWarning()<<"setKeyboardGrabEnable failed! focus Window is"<<getFocusWindowName();
        m_tryGrabTimes = 0;
        return;
    }

    QTimer::singleShot(100, this, &FullBackgroundWidget::tryGrabKeyboard);
}

bool FullBackgroundWidget::nativeEventFilter(const QByteArray &eventType, void *message, long *result)
{
    if (qstrcmp(eventType, "xcb_generic_event_t") != 0) {
        return false;
    }
    xcb_generic_event_t *event = reinterpret_cast<xcb_generic_event_t*>(message);
    const uint8_t responseType = event->response_type & ~0x80;


    if (responseType == XCB_FOCUS_OUT) {
        //丢焦点时，检测抢焦点的窗口是否为锁屏的子窗口，比如QMenu,QCombobox等，
        //如果不是子窗口，则重新给锁屏设置一次焦点
        QString focusWindow = getFocusWindowName();
        if(focusWindow == "ukui-screensaver-dialog"){
            return false;
        }else{
            qDebug()<<"focus out. focus window is"<<focusWindow;
        }
        laterActivate();
        qDebug()<<"XCB_FOCUS_OUT !";
    }else if(responseType == XCB_FOCUS_IN){
        //因为弹出菜单会释放键盘抓取，所以在锁屏窗口重新获取到焦点时，重新抓取一次键盘焦点
        qDebug()<<"XCB_FOCUS_IN !";
    }else if(responseType == XCB_GE_GENERIC){
        //因为锁屏抓取了键盘，所以锁屏窗口不管有没有焦点，都能够输入，但仍然需要发送一个
        //虚拟的focusin事件，来激活窗口焦点,同时点击锁屏界面，也能触发锁屏键盘抓取
        xcb_ge_generic_event_t *xc = reinterpret_cast<xcb_ge_generic_event_t*>(event);
        if(xc->event_type == XCB_BUTTON_PRESS){
            if(this->windowHandle()){
                bool grabed = this->windowHandle()->setKeyboardGrabEnabled(true);
                if(!grabed){
                    qDebug()<<"setKeyboardGrabEnable failed! focus Window is"<<getFocusWindowName();
                }
	    }
	    onGlobalButtonPressed(QCursor::pos().x(), QCursor::pos().y());
        }else if(xc->event_type == XCB_BUTTON_RELEASE){
        }else if(xc->event_type == XCB_MOTION_NOTIFY){
            onGlobalButtonDrag(QCursor::pos().x(),QCursor::pos().y());
        }
    }else if(responseType == XCB_BUTTON_PRESS){
	xcb_button_press_event_t *xc = reinterpret_cast<xcb_button_press_event_t*>(event);
        int x = xc->root_x;
        int y = xc->root_y;
        onGlobalButtonPressed(x, y);
        qDebug()<<"---------------------XCB_BUTTON_PRESS:"<<x<<","<<y;
    }else if(responseType == XCB_BUTTON_RELEASE){
	
    }else if(responseType == XCB_MOTION_NOTIFY){
	xcb_motion_notify_event_t *xc = reinterpret_cast<xcb_motion_notify_event_t*>(event);
        int x = xc->root_x;
        int y = xc->root_y;
        onGlobalButtonDrag(x, y);
        qDebug()<<"---------------------XCB_MOTION_NOTIFY:"<<x<<","<<y;
    }else if (responseType == XCB_KEY_PRESS) {
        xcb_key_press_event_t *xc = reinterpret_cast<xcb_key_press_event_t*>(event);
        //qDebug()<<"---------------------XCB_KEY_PRESS:"<<xc->detail;
        onGlobalKeyPress(xc->detail);
     } else if (responseType == XCB_KEY_RELEASE) {
        xcb_key_release_event_t *xc = reinterpret_cast<xcb_key_release_event_t*>(event);
        qDebug()<<"---------------------XCB_KEY_RELEASE:"<<xc->detail;
        onGlobalKeyRelease(xc->detail);
     }
    return false;
}

void FullBackgroundWidget::onCurUserChanged(const QString &strUserName)
{

}

void FullBackgroundWidget::onAuthSucceed(QString strUserName)
{
    if (getenv("USER") == strUserName) {
        onCloseScreensaver();
    } else {
        if (m_modelLockDialog) {
            Q_EMIT m_modelLockDialog->startSession();
        }
    }
}

void FullBackgroundWidget::onGlobalKeyPress(const quint8 &key)
{

}

void FullBackgroundWidget::onGlobalKeyRelease(const quint8 &key)
{
//    if (m_lockWidget && m_lockWidget->isVisible()) {
//        m_lockWidget->onGlobalkeyRelease(key);
//    }
    if(key == 9 && screenStatus == SCREEN_LOCK) {  // "escape"
        bool canShow = true;
        if (m_lockWidget && !m_lockWidget->exitSubWidget())
            canShow = false;
        if (canShow)
            onShowScreensaver();
    } else if(screenStatus & SCREEN_SAVER/* && !isBlank*/) {
        qDebug() << "clearclear" ;
        onClearScreensaver();
    }
}

void FullBackgroundWidget::onGlobalButtonDrag(int xPos, int yPos)
{
    if(screenStatus & SCREEN_SAVER && !isBlank)
    {
        qDebug() << "clearclear" ;
        onClearScreensaver();
    }
}

void FullBackgroundWidget::onGlobalButtonPressed(int xPos, int yPos)
{
    if(screenStatus & SCREEN_SAVER && !isBlank)
    {
        onClearScreensaver();
    }
}

//////////////////////////////////
void FullBackgroundWidget::initCurrentBackground()
{
    loadingAllUserBackground();
    m_backgrondGradationTimer = new QTimer(this);
    connect(m_backgrondGradationTimer, &QTimer::timeout, this, &FullBackgroundWidget::onTransition);

    connect(m_modelLockDialog, &LockDialogModel::setCurrentUser, this, &FullBackgroundWidget::onCurrentUserBackground);
    connect(m_modelLockDialog, &LockDialogModel::currentUserChanged, this, &FullBackgroundWidget::onUpdateUserBackground);

//    update();
}


QString FullBackgroundWidget::getDefaultBackgroundPath()
{
    qDebug() << __LINE__ << __FUNCTION__;

    QString default_background_path = "/usr/share/backgrounds/1-warty-final-ubuntukylin.jpg";
    QFile file(default_background_path);
    if (!file.exists())
    {
        default_background_path = "/usr/share/backgrounds/1-openkylin.jpg";
        QFile file(default_background_path);
        if (!file.exists())
        {
            return "";
        }
    }
    return default_background_path;
}

void FullBackgroundWidget::loadingAllUserBackground()
{
    qWarning() << __LINE__ << __FUNCTION__ ;
    if (!getDefaultBackgroundPath().isEmpty())
        addBackgroundData(getDefaultBackgroundPath());

}

void FullBackgroundWidget::paintEvent(QPaintEvent *event)
{
//    qDebug() << __LINE__ << __FUNCTION__;

    QPainter painter(this);

    for(QScreen *screen : QApplication::screens()){
        //在每个屏幕上绘制背景
        QRect rect = screen->geometry();
        int width = rect.width();
        int height = rect.height();
        QString currentPath = getUserBackgroundPath(m_currentUserName);
        QString resolution = QString("%1x%2").arg(width).arg(height);
        QPair<QString,QString> cunrrentKey(currentPath, resolution);

        QString oldPath = getUserBackgroundPath(m_oldUserName);
        QPair<QString,QString> oldKey(oldPath, resolution);

        //if (m_gradualChanging && m_allBackgroundsMap.contains(m_currentUserName))
        if (m_gradualChanging && m_allBackgroundsDataMap.contains(cunrrentKey))
        {
            //drawBackground(m_allBackgroundsMap[m_currentUserName],m_allBackgroundsMap[m_oldUserName],rect,m_backgroundAlpha);
            drawBackground(m_allBackgroundsDataMap[cunrrentKey],m_allBackgroundsDataMap.contains(oldKey)?m_allBackgroundsDataMap[oldKey]:nullptr,rect,m_backgroundAlpha);
        }
        else
        {
            stopTransition();
//            qWarning() << __LINE__<< __FUNCTION__ << "===============" << m_allBackgroundsMap.contains(m_currentUserName);

            if (m_allBackgroundsDataMap.contains(cunrrentKey))
            {

                //drawPixmap(rect, *m_allBackgroundsMap[m_currentUserName]);
                painter.drawPixmap(rect, *m_allBackgroundsDataMap[cunrrentKey]);
            }
            else
            {
                QString defaultPath = getDefaultBackgroundPath();
                QPair<QString,QString> defaultKey(defaultPath, resolution);
                if (m_allBackgroundsDataMap.contains(defaultKey))
                    painter.drawPixmap(rect, *m_allBackgroundsDataMap[defaultKey]);
            }
        }
    }
    return QWidget::paintEvent(event);
}

bool FullBackgroundWidget::isOpenGradation()
{
    qDebug() << __LINE__ << __FUNCTION__;
    bool isOpenGradation = false;
//    return true;//test 一直触发渐变效果
    if (m_currentUserName.isEmpty() || m_oldUserName.isEmpty())
        return isOpenGradation;
    if (m_currentUserName == m_oldUserName)
        return isOpenGradation;

    if (m_allBackgroundsMap.contains(m_currentUserName))
    {
        int width = QApplication::primaryScreen()->geometry().width();
        int height = QApplication::primaryScreen()->geometry().height();
        QString currentPath = getUserBackgroundPath(m_currentUserName);
        QString resolution = QString("%1x%2").arg(width).arg(height);
        QPair<QString,QString> cunrrentKey(currentPath, resolution);

        QString oldPath = getUserBackgroundPath(m_oldUserName);
        QPair<QString,QString> oldKey(oldPath, resolution);

        if (cunrrentKey != oldKey)
        {
            isOpenGradation = true;
        }
    }

    return isOpenGradation;
}

void FullBackgroundWidget::onUpdateUserBackground(const QString &strUserName)
{
    qWarning() << __LINE__ <<__FUNCTION__ << "==========" << strUserName ;
    if (m_currentUserName == strUserName)
        return;
    m_oldUserName = m_currentUserName;
    m_currentUserName = strUserName;
    //是否需要开启渐变效果
    m_gradualChanging = isOpenGradation();
    qWarning() << __LINE__ <<__FUNCTION__ << "==========" << m_gradualChanging ;

    if (m_gradualChanging)
        startTransition();
    repaint();
}

void FullBackgroundWidget::onTransition()
{
    qWarning() << __LINE__ << __FUNCTION__  ;
    m_backgroundAlpha += 0.05;

    if(m_backgroundAlpha >= 1.0)
        stopTransition();
    repaint();
}

void FullBackgroundWidget::startTransition()
{
    if(!m_backgrondGradationTimer){
         m_backgrondGradationTimer = new QTimer(this);
         connect(m_backgrondGradationTimer, &QTimer::timeout, this, &FullBackgroundWidget::onTransition);
    }
    stopTransition();

    m_backgroundAlpha = 0.0;
    m_gradualChanging = true;

    m_backgrondGradationTimer->start(10);
}
void FullBackgroundWidget::stopTransition()
{
//    qDebug() << __LINE__ << __FUNCTION__;

    if(m_backgrondGradationTimer && m_backgrondGradationTimer->isActive())
        m_backgrondGradationTimer->stop();
    m_backgroundAlpha = 1.0;
    m_gradualChanging = false;
}

void FullBackgroundWidget::drawBackground(QPixmap * backgroundBack, QPixmap * backgroundFront,
                                const QRect &rect, float alpha)
{
//    qDebug() << __LINE__ << __FUNCTION__;

    if(backgroundBack->isNull())
    {
        stopTransition();
        repaint();
        return;
    }

    QPainter painter(this);

    if(backgroundFront == nullptr)
    {

        painter.setOpacity(alpha);
        //QString color = m_configuration->getValue("background-color").toString();
        QColor cor;
        //if(!color.isEmpty())
        //    cor = color;
        //else
            cor = "#035290";
        painter.setBrush(cor);
        painter.drawRect(rect);

    }
    else
    {

        painter.drawPixmap(rect, *backgroundFront);
        painter.setOpacity(alpha);
        painter.drawPixmap(rect, *backgroundBack);
        QPainterPath path;
        QPainter painter1(this);
        painter1.setOpacity(0.25);
        painter1.setRenderHint(QPainter::Antialiasing);  // 反锯齿;
        painter1.setClipping(true);
        painter1.setPen(Qt::transparent);
        path.addRect(this->rect());
        path.setFillRule(Qt::WindingFill);
        painter1.setBrush(QColor("#000000"));
        painter1.setPen(Qt::transparent);
        painter1.drawPath(path);
    }
    qDebug() << __LINE__ << __FUNCTION__<< "===============2";

}

void FullBackgroundWidget::onRemoveUserBackground(const QString &strUserName)
{
    qDebug() << __LINE__ << __FUNCTION__;

    if (m_allBackgroundsMap.contains(strUserName))
        m_allBackgroundsMap.remove(strUserName);
}

QString FullBackgroundWidget::getUserBackgroundPath(const QString &strUserName)
{
    qDebug() << __LINE__ << __FUNCTION__;

    for (UserInfoPtr userInfo : m_modelLockDialog->usersInfo())
    {
        if (strUserName == userInfo->name())
        {
            qDebug() << __LINE__ << __FUNCTION__ << userInfo->name() << userInfo->backGround();

            return userInfo->backGround();
        }
    }
    return QString("");
}

void FullBackgroundWidget::addBackgroundData(const QString &bgPath)
{
    qDebug() << __LINE__ << __FUNCTION__;

    if (bgPath.isEmpty())
    {
        qDebug() << __LINE__ << __FUNCTION__ << bgPath << ":Path is Null";
        return;
    }
    QFile file(bgPath);
    if (!file.exists())
    {
        qDebug() << __LINE__ << __FUNCTION__ << "Add background file isn't exists";
        return;
    }
    int width = QApplication::primaryScreen()->geometry().width();
    int height = QApplication::primaryScreen()->geometry().height();

    QString resolution = QString("%1x%2").arg(width).arg(height);
    QPair<QString, QString> key(bgPath, resolution);
    QPixmap *pixmap = new QPixmap(scaleBlurPixmap(width,height, bgPath));

    m_allBackgroundsDataMap[key] = pixmap;
}

bool FullBackgroundWidget::existsBackgroundData(const QString &bgPath)
{
    qDebug() << __LINE__ << __FUNCTION__;

    int width = QApplication::primaryScreen()->geometry().width();
    int height = QApplication::primaryScreen()->geometry().height();

    QString resolution = QString("%1x%2").arg(width).arg(height);
    QPair<QString, QString> key(bgPath, resolution);
    return m_allBackgroundsDataMap.contains(key);
}

void FullBackgroundWidget::onAddUserBackground(const QString &strUserName)
{
    qDebug() << __LINE__ << __FUNCTION__;

    FullBackgroundWidget::m_loadingOneBackgroundFuture = QtConcurrent::run([=](){
        for (UserInfoPtr userInfo : m_modelLockDialog->usersInfo())
        {
            if (strUserName == userInfo->name())
            {
                if (!existsBackgroundData(userInfo->backGround()))
                    addBackgroundData(userInfo->backGround());

                break;
            }
        }
    });
    m_loadingOneBackgroundFuture.waitForFinished();
}

void FullBackgroundWidget::onUserBackgroundChanged(const QString &strUserName)
{

}

void FullBackgroundWidget::onCurrentUserBackground(const QString &strUserName)
{
    qWarning() << __LINE__ << __FUNCTION__ << "===============" << strUserName;
    //m_currentUserName = strUserName;
    QString userPath = getUserBackgroundPath(strUserName);
    int width = QApplication::primaryScreen()->geometry().width();
    int height = QApplication::primaryScreen()->geometry().height();
    QString resolution = QString("%1x%2").arg(width).arg(height);
    QPair<QString,QString> UserKey(userPath, resolution);

    if (!m_allBackgroundsDataMap.contains(UserKey))
    {
        onAddUserBackground(strUserName);
    }
    repaint();
}
