/*
* Copyright (C) 2019 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/&gt;.
*
*/

#include "singlemsg.h"

SingleMsg::SingleMsg(AppMsg* pParent, QString strIconPath, QString strAppName, QString strSummary, QDateTime dateTime, QString strBody, QString strUrl, QString strAction)
    : m_pParent(pParent),m_strIconPath(strIconPath),m_strAppName(strAppName),m_strSummary(strSummary),
      m_dateTime(dateTime),m_strBody(strBody),m_strUrl(strUrl),m_strAction(strAction),
      m_pSetJumpDelayTimer(new QTimer(this)),
      m_pAppVLaout(new QVBoxLayout()),
      m_pSingleWidget(new SingleWidget()),
      m_pAnimationBaseMapWidget(new QWidget(this)),
      m_pMainVLaout(new QVBoxLayout()),
      m_pIconWidget(new QWidget()),
      m_pIconHLayout(new QHBoxLayout()),
      m_pIconToolButton(new QLabel()),
      m_pAppNameLabel(new QLabel()),
      m_pTimeLabelWidget(new QWidget()),
      m_pStorageDeleteButtonWidget(new QWidget()),
      m_pTimeLabel(new QLabel()),
      m_pTimeLableHLayout(new QHBoxLayout()),
      m_pStorageDeleteButtonHLaout(new QHBoxLayout()),
      m_pContextWidget(new QWidget()),
      m_pVContextLayout(new QVBoxLayout()),
      m_pSummaryLabel(new QLabel()),
      m_pBodyLabel(new QLabel()),
      m_pShowLeftWidget(new QWidget()),
      m_pShowLeftItemLabel(new QLabel)

{
    /* 保存推送时间的绝对时间 */
    m_uNotifyTime = m_dateTime.toTime_t();

    /* 初始化gsetting */
    initGsetting();

    /* 初始化界面 */
    initUI();

    /* 初始化连接跳转动作 */
    initJumpConnect();

    /* 连接信号 */
    connect(this, SIGNAL(Sig_setAppFoldFlag(bool)), pParent, SLOT(setAppFoldFlag(bool)));
    connect(this, SIGNAL(Sig_onDeleSingleMsg(SingleMsg*)), pParent, SLOT(onDeleSingleMsg(SingleMsg*)));
    connect(this, SIGNAL(Sig_onDeleteAppMsg()), pParent, SLOT(onDeleteAppMsg()));
    connect(this, SIGNAL(Sig_notifyAppShowBaseMap()), pParent, SLOT(onShowBaseMap()));
    connect(this, SIGNAL(Sig_notifyAppHideBaseMap()), pParent, SLOT(onHideBaseMap()));
    return;
}

/**
 * @brief SingleMsg::initUI
 * 初始化界面
 */
void SingleMsg::initUI()
{
    /* 初始化界面属性 */
    initAttribute();

    /* 初始化布局 */
    initLayout();

    this->setFixedWidth(352);

}

void SingleMsg::initAttribute()
{
    m_pSingleWidget->setObjectName("SingleNotification");

    /* 图标和时间行的水平布局部件 */
    m_pIconWidget->setAttribute(Qt::WA_TranslucentBackground);

    /* 设置通知消息中的Icon */
    m_pIconToolButton->setFixedSize(24, 24);
    m_pIconToolButton->setAttribute(Qt::WA_TranslucentBackground);

    QPixmap pixmap;
    if (m_strIconPath.contains("file://")) {
        int length = m_strIconPath.length();
        m_strIconPath = m_strIconPath.mid(7, length);
    }

    const qreal pixelRatio = qApp->primaryScreen()->devicePixelRatio();

    pixmap = QIcon::fromTheme(m_strIconPath).pixmap(QSize(24, 24));


    if (pixmap.isNull()) {
        QString iconUrl;
        const QUrl url(m_strIconPath);
        iconUrl = url.isLocalFile() ? url.toLocalFile() : url.url();

        if (m_strIconPath.contains("file://")) {
            int length = m_strIconPath.length();
            m_strIconPath = m_strIconPath.mid(7, length);
        }
        const QIcon &icon = QIcon::fromTheme(m_strIconPath, QIcon::fromTheme("application-x-desktop"));
        pixmap = icon.pixmap(width() * pixelRatio, height() * pixelRatio);
    } else {
        pixmap = pixmap.scaled(m_pIconToolButton->width() * pixelRatio, m_pIconToolButton->height() * pixelRatio,
                               Qt::KeepAspectRatioByExpanding,
                               Qt::SmoothTransformation);

        pixmap.setDevicePixelRatio(pixelRatio);

    }

    m_pIconToolButton->setPixmap(pixmap);


    /* 消息通知中的消息标题 */
    m_pAppNameLabel->setObjectName("AppName");
    m_pAppNameLabel->setAttribute(Qt::WA_TranslucentBackground);

    QFont font14;
    font14.setPixelSize(14);
    m_pAppNameLabel->setFont(font14);

    setLabelAlphaF(m_pAppNameLabel,0.45); //设置透明度
    QFontMetrics fontMetrics1(m_pAppNameLabel->font());
    QString formatAppName = fontMetrics1.elidedText(m_strAppName, Qt::ElideRight, m_pAppNameLabel->width()); //增加省略机制
    m_pAppNameLabel->setText(formatAppName);

    /* 消息时间载体 */
    m_pTimeLabelWidget->setFixedSize(146, 20);
    m_pTimeLabelWidget->setAttribute(Qt::WA_TranslucentBackground);

    /* 消息删除按钮载体 */
    m_pStorageDeleteButtonWidget->setFixedSize(146, 20);
    m_pStorageDeleteButtonWidget->setAttribute(Qt::WA_TranslucentBackground);
    m_pStorageDeleteButtonWidget->hide();

    /* 设置通知消息中的通知时间 */
    m_pTimeLabel->setObjectName("pushtime");
    m_pTimeLabel->setText(tr("now"));
    m_pTimeLabel->setAttribute(Qt::WA_TranslucentBackground);
    setLabelAlphaF(m_pTimeLabel,0.45);

    /* 单独删除按钮 */
    QString strIcon = ":/images/exit.svg";
    QString strHoverIcon = ":/images/exit-hover.svg";
    QString strPressIcon = ":/images/exit-press.svg";

    QSize deleteNormalIconSize(24, 24);
    QSize deletePressedIconSize(18, 18);

    m_pSingleDeleteButton = new ButtonWidget(strIcon, strHoverIcon, strPressIcon,deleteNormalIconSize,deletePressedIconSize);
    connect(m_pSingleDeleteButton, SIGNAL(Sig_clicked()), this, SLOT(onDele()));

    /* 内容部件,将主题正文以及剩余条数显示装入内容部件 */
    m_pContextWidget->setAttribute(Qt::WA_TranslucentBackground);

    /* 通知消息主题 */
    m_pSummaryLabel->setFixedWidth(314);
    m_pSummaryLabel->setAttribute(Qt::WA_TranslucentBackground);

    QFont font16;
    font16.setPixelSize(16);
    m_pSummaryLabel->setFont(font16);

    /* 处理主题省略模式文字信息 */
    QString formatSummary;
    formatSummary.append("<p style='line-height:26px'>").append(m_strSummary).append("</p>");
    QFontMetrics fontMetrics(m_pSummaryLabel->font());
    int nFontSize = fontMetrics.width(formatSummary);
    QString strformatSummary = formatSummary;
    if(nFontSize > (m_pSummaryLabel->width() + 239)){
        strformatSummary = fontMetrics.elidedText(formatSummary, Qt::ElideRight, m_pSummaryLabel->width() + 210);
    }

    m_pSummaryLabel->setText(strformatSummary);

    /* 通知消息中的正文 */
    m_pBodyLabel->setFixedWidth(315);
    m_pBodyLabel->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
    m_pBodyLabel->adjustSize();
    m_pBodyLabel->setAttribute(Qt::WA_TranslucentBackground);

    /* 设置通知消息中的正文QLabel，行高24px,采用自动换行模式 */
    if(false == m_strBody.isEmpty()){
        QString strLineHeight24Body;
        strLineHeight24Body.append("<p style='line-height:24px'>").append(m_strBody).append("</p>");

        QFontMetrics fontMetrics(m_pBodyLabel->font());
        int fontSize = fontMetrics.width(strLineHeight24Body);
        QString formatBody = strLineHeight24Body;

        m_pBodyLabel->setWordWrap(false);
        if(fontSize > (m_pBodyLabel->width() + 209)){
            formatBody = fontMetrics.elidedText(strLineHeight24Body, Qt::ElideRight, m_pBodyLabel->width() + 180);
        }
        m_pBodyLabel->setText(formatBody);
        setLabelAlphaF(m_pBodyLabel,0.65);
    }

    /* 显示该应用未展开部件 */
    m_pShowLeftWidget->setAttribute(Qt::WA_TranslucentBackground);

    /* 应用未展开条数Label */
    m_pShowLeftItemLabel->setObjectName("ShowLeftItem");
    m_pShowLeftItemLabel->setVisible(false);
    setLabelAlphaF(m_pShowLeftItemLabel,0.65);

}

void SingleMsg::initLayout()
{
    //为了设置SingleMsg的6px圆角的样式,在里面套了一个QWidget
    m_pAppVLaout->setContentsMargins(0, 0, 0, 0);
    m_pAppVLaout->setSpacing(0);

    /* 单条消息总体垂直布局器 */
    m_pMainVLaout->setContentsMargins(0, 0, 0, 0);
    m_pMainVLaout->setSpacing(0);

    /* 图标和时间行的水平布局器 */
    m_pIconHLayout->setContentsMargins(10, 11, 0, 0);
    m_pIconHLayout->setSpacing(0);

    /* 设置标签布局 */
    m_pTimeLableHLayout->addWidget(m_pTimeLabel, 0, Qt::AlignRight);
    m_pTimeLableHLayout->addItem(new QSpacerItem(26, 10 , QSizePolicy::Fixed, QSizePolicy::Fixed));
    m_pTimeLableHLayout->setContentsMargins(0, 0, 0, 0);
    m_pTimeLableHLayout->setSpacing(0);
    m_pTimeLabelWidget->setLayout(m_pTimeLableHLayout);

    /* 收纳和删除按钮布局 */
    m_pStorageDeleteButtonHLaout->addItem(new QSpacerItem(1, 10, QSizePolicy::Expanding, QSizePolicy::Fixed));
    m_pStorageDeleteButtonHLaout->addSpacerItem(new QSpacerItem(8, 10, QSizePolicy::Fixed, QSizePolicy::Fixed));
    m_pStorageDeleteButtonHLaout->addWidget(m_pSingleDeleteButton, 0, Qt::AlignRight);
    m_pStorageDeleteButtonHLaout->addItem(new QSpacerItem(15, 10, QSizePolicy::Fixed, QSizePolicy::Fixed));
    m_pStorageDeleteButtonHLaout->setContentsMargins(0, 0, 0, 0);
    m_pStorageDeleteButtonHLaout->setSpacing(0);
    m_pStorageDeleteButtonWidget->setLayout(m_pStorageDeleteButtonHLaout);

    /* 设置通知消息中的弹簧，水平任意伸缩使应用名和时间分开 */
    QSpacerItem* pHExpandSpacer = new QSpacerItem(400, 10, QSizePolicy::Expanding, QSizePolicy::Fixed);

    /* 图标和时间行的水平布局 */
    m_pIconHLayout->addWidget(m_pIconToolButton, 0, Qt::AlignLeft);
    m_pIconHLayout->addItem(new QSpacerItem(6, 10, QSizePolicy::Fixed, QSizePolicy::Fixed));
    m_pIconHLayout->addWidget(m_pAppNameLabel, 0, Qt::AlignLeft|Qt::AlignVCenter);
    m_pIconHLayout->addItem(pHExpandSpacer);
    m_pIconHLayout->addWidget(m_pTimeLabelWidget);
    m_pIconHLayout->addWidget(m_pStorageDeleteButtonWidget,0, Qt::AlignRight);
    m_pIconWidget->setLayout(m_pIconHLayout);

    /* 内容部件的垂直布局器 */
    m_pVContextLayout->setContentsMargins(40, 0, 26, 0);
    m_pVContextLayout->setSpacing(0);

    QVBoxLayout* pVShowLeftLayout = new QVBoxLayout();
    pVShowLeftLayout->setContentsMargins(0,6,0,14);
    pVShowLeftLayout->addWidget(m_pShowLeftItemLabel, 0, Qt::AlignLeft);
    m_pShowLeftWidget->setLayout(pVShowLeftLayout);

    m_pVContextLayout->addWidget(m_pSummaryLabel, 0, Qt::AlignLeft);
    m_pVContextLayout->addWidget(m_pBodyLabel, 0, Qt::AlignLeft);
    m_pVContextLayout->addWidget(m_pShowLeftWidget, 0, Qt::AlignLeft);
    m_pContextWidget->setLayout(m_pVContextLayout);

    m_pMainVLaout->addWidget(m_pIconWidget, 0);
    m_pMainVLaout->addWidget(m_pContextWidget);

    m_pSingleWidget->setLayout(m_pMainVLaout);
    m_pAppVLaout->addWidget(m_pSingleWidget);

    this->setLayout(m_pAppVLaout);
    this->update();
}

void SingleMsg::initJumpConnect()
{
    /* 跳转动作 */
    m_pSetJumpDelayTimer->setSingleShot(true);      //延迟30毫秒，等待删除完成后跳转
    connect(m_pSetJumpDelayTimer, &QTimer::timeout, this, [=](){
        if(!m_strUrl.isEmpty()){
            QString cmd = QString("xdg-open ") + m_strUrl;
            qInfo()<<"Jump Url:"<<cmd;
            system(cmd.toStdString().c_str());
            emit Sig_onDeleSingleMsg(this);
        } else if(!m_strAction.isEmpty()){
            qInfo()<<"Jump Action:"<<m_strAction;
            QProcess *process = new QProcess();
            process->start(m_strAction);
            emit Sig_onDeleSingleMsg(this);
        } else {
            emit Sig_onDeleSingleMsg(this);
        }
    });

    connect(this,&SingleMsg::Sig_jumpAction,this,[=](){
        m_pSetJumpDelayTimer->start(30);
    });
}

/**
 * @brief SingleMsg::updatePushTime
 * 更新消息通知时间
 */
void SingleMsg::updatePushTime()
{
    QDateTime currentDateTime(QDateTime::currentDateTime());

    if(currentDateTime.toTime_t() < (m_uNotifyTime + 60)){
        return;
    }

    QString strPushDate;
    if (m_dateTime.date() == currentDateTime.date()) {
        if(true == m_bTimeFormat){
            strPushDate = m_dateTime.toString("hh:mm");                     //24小时制
        } else {
            strPushDate = m_dateTime.toString("AP h:mm");                   //12小时制
        }
        m_pTimeLabel->setText(strPushDate);
        return;
    }

    if (1 == (currentDateTime.date().toJulianDay() - m_dateTime.date().toJulianDay())) {
        strPushDate = tr("Yesterday ");
        if (true == m_bTimeFormat) {
            strPushDate = strPushDate + m_dateTime.toString("hh:mm");       //24小时制
        } else {
            strPushDate = strPushDate + m_dateTime.toString("AP h:mm");     //12小时制
        }
        m_pTimeLabel->setText(strPushDate);

        return;
    }

    if ((currentDateTime.date().toJulianDay() - m_dateTime.date().toJulianDay()) < 7) {
        /* 一周以内 */
        if(true == m_bTimeFormat){
            strPushDate = m_dateTime.toString("ddd hh:mm");                 //24小时制
        } else {
            strPushDate =  m_dateTime.toString("ddd AP h:mm");              //12小时制
        }
        m_pTimeLabel->setText(strPushDate);

    } else {
        /* 一周以外 */
        if (ControlCenterPanelGsetting::getInstance()->getDateSystem() == DATE_FORMAT) {
            strPushDate = m_dateTime.toString("yyyy/MM/dd");
        } else {
            strPushDate = m_dateTime.toString("yyyy-MM-dd");
        }
        m_pTimeLabel->setText(strPushDate);
    }

    return;
}

/**
 * @brief SingleMsg::setBodyLabelWordWrap
 * 设置正文显示状态，省略显示或全部展示
 * @param bFlag
 * 状态值：TRUE 展开状态  FALSE 折叠状态
 */
void SingleMsg::setBodyLabelWordWrap(bool bFlag)
{
    if(true == m_strBody.isEmpty()){
        return;
    }

    m_pBodyLabel->setWordWrap(bFlag);
    QFontMetrics fontMetrics(m_pBodyLabel->font());
    QString strLineHeight24Body;
    strLineHeight24Body.append("<p style='line-height:24px'>").append(m_strBody).append("</p>");
    int fontSize = fontMetrics.width(strLineHeight24Body);
    QString formatBody = strLineHeight24Body;

    if(true == bFlag){
        /* 如果展开,就超过四行末尾显示省略号 */
        formatBody = fontMetrics.elidedText(strLineHeight24Body, Qt::ElideRight, m_pBodyLabel->width() * 4 + 152);

    } else {
        /* 如果不展开,就超过一行末尾显示省略号 */
        if (fontSize > (m_pBodyLabel->width() + 209)) {
            formatBody = fontMetrics.elidedText(strLineHeight24Body, Qt::ElideRight, m_pBodyLabel->width() + 180);
        }
    }
    m_pBodyLabel->setText(formatBody);

    return;
}

/**
 * @brief SingleMsg::setLeftItem
 * 将应用的总的剩余条数设置剩余标签显示内容,根据具体情况显示,该函数只有顶部消息才执行
 * @param nShowLeftCount
 * 消息数量
 */
void SingleMsg::setLeftItem(int nShowLeftCount)
{
    m_nShowLeftCount = nShowLeftCount;
    QString strShowLeft = tr("In addition ") + QString::number(nShowLeftCount) + tr(" notification");
    m_pShowLeftItemLabel->setText(strShowLeft);
    m_pShowLeftItemLabel->setAttribute(Qt::WA_TranslucentBackground);

    /* 当剩余条数大于0, 且是折叠状态则显示剩余标签 */
    if ((true == m_bFold) && (m_nShowLeftCount > 0)) {
        /* 假如折叠，剩余条目显示将可见，则SingleMsg的内容均无空隙 */
        m_pAppVLaout->setContentsMargins(0,0,0,0);
        m_pShowLeftItemLabel->setVisible(true);
    } else {
        /* 假如展开，剩余条目显示不可见，则SingleMsg的内容空白恢复正常，即底部多出6个px的空隙 */
        m_pAppVLaout->setContentsMargins(0,0,0,6);
        m_pShowLeftItemLabel->setVisible(false);
    }
}

/**
 * @brief SingleMsg::setShowLeftItemFlag
 * 设置应用未展开条数状态，隐藏或显示
 * @param bFlag
 * 状态值： TRUE 显示  FALSE 隐藏
 */
void SingleMsg::setShowLeftItemFlag(bool bFlag)
{
    m_pShowLeftItemLabel->setVisible(bFlag);
}

/**
 * @brief SingleMsg::setSingleMsgContentsMargins
 * 折叠时设置 m_pAppVLaout 布局间隙
 * @param left
 * @param top
 * @param right
 * @param bottom
 */
void SingleMsg::setSingleMsgContentsMargins(int left, int top, int right, int bottom)
{
    m_pAppVLaout->setContentsMargins(left, top, right, bottom);
}

/**
 * @brief SingleMsg::enterEvent
 * 进入事件 完成：展示刪除按鈕，隐藏时间标签，更新图标间隙.
 * @param event
 */
void SingleMsg::enterEvent(QEvent *event)
{
    Q_UNUSED(event);
    m_pStorageDeleteButtonWidget->show();
    m_pTimeLabelWidget->hide();
    m_pIconHLayout->setContentsMargins(10, 11, 0, 0);

    return;
}

/**
 * @brief SingleMsg::leaveEvent
 * 离开事件 完成：展示时间标签，隐藏删除按钮，更新图标间隙.
 * @param event
 */
void SingleMsg::leaveEvent(QEvent *event)
{
    Q_UNUSED(event);
    m_pTimeLabelWidget->show();
    m_pStorageDeleteButtonWidget->hide();
    m_pIconHLayout->setContentsMargins(10, 11, 0, 0);
    return;
}

/**
 * @brief SingleMsg::mousePressEvent
 * 点击事件 完成：
 * 过滤鼠标左键，执行展开操作或跳转操作，展开时更新折叠按钮，反之隐藏
 * @param event
 */
void SingleMsg::mousePressEvent(QMouseEvent *event)
{
    if (event->buttons() == Qt::LeftButton) {
        if (m_pParent->getFoldFlag()) {
            /* 折叠状态 */
            if (true == m_bMain) {
                if (m_pParent->getSingleMsgCount()<=1) {
                    if (m_bFold) {
                        /* 折叠状态下展开单条消息 */
                        setBodyLabelWordWrap(true);
                        setFoldFlag(false);
                        m_pParent->setFoldFlag(false);
                    } else {
                        /* 已经展开的消息执行跳转 */
                        jumpFlag = true;
                        jumpAction();

                        //点击消息通知,收集数据
                        pointDataStruct pointData;
                        pointData.module = MESSAGEBAR + m_strAppName;
                        pointData.function = CLICK_MESSAGEBAR_BODY;
                        pointData.otherFunction.append(m_strBody);
                        DataProcess::getInstance()->sendData(pointData);

                    }
                } else {
                    /* 展开整个app消息 */
                    if (m_bFold) {
                        setFoldFlag(false);
                        m_pShowLeftItemLabel->setVisible(false);
                        emit Sig_setAppFoldFlag(m_bFold);
                    }
                }
            }
        } else {
            /* 执行跳转动作 */
            jumpFlag = true;
            jumpAction();

            //点击消息通知,收集数据
            pointDataStruct pointData;
            pointData.module = MESSAGEBAR + m_strAppName;
            pointData.function = CLICK_MESSAGEBAR_BODY;
            pointData.otherFunction.append(m_strBody);
            DataProcess::getInstance()->sendData(pointData);

        }
        this->update();
    }

    return;
}

/**
 * @brief SingleMsg::jumpAction
 * 执行跳转动作
 */
void SingleMsg::jumpAction()
{
    /* 关闭该条通知 */
    onDele();

    return;
}

/**
 * @brief SingleMsg::mainMsgSetShowOrFold
 * 设置通知展开或折叠
 */
void SingleMsg::mainMsgSetShowOrFold(bool bFlag)
{
    if(true == m_bMain){
        /* 当消息为主窗口时,由主消息设置折叠 */
        setFoldFlag(true);
        setBodyLabelWordWrap(false);

        if (m_nShowLeftCount > 0) {
            /* 当剩余条数大于0, 且是折叠状态则显示剩余标签 */
            m_pAppVLaout->setContentsMargins(0,0,0,0);
            m_pShowLeftItemLabel->setVisible(true);
        }
        emit Sig_setAppFoldFlag(true);
    }
}

/**
 * @brief SingleMsg::startAnimationUnfold
 * 开启多消息展开时动画
 */
void SingleMsg::startAnimationUnfold()
{
    int width = this->width();
    int height = this->height();

    if(true == m_strBody.isEmpty()){
        height = 87;
    } else {
        height = 111;
    }

    m_pAppVLaout->removeWidget(m_pSingleWidget);
    m_pAnimationBaseMapWidget->setFixedSize(width, 0);
    m_pAnimationBaseMapWidget->setVisible(true);
    m_pAppVLaout->addWidget(m_pAnimationBaseMapWidget, 0, Qt::AlignHCenter);
    this->setVisible(true);

    //设置show动画
    QPropertyAnimation* pAnimation = new QPropertyAnimation(m_pSingleWidget, "geometry");
    pAnimation->setDuration(50);
    connect(pAnimation, &QPropertyAnimation::valueChanged, this, &SingleMsg::updateUnfoldMove);
    connect(pAnimation, SIGNAL(finished()), this, SLOT(onUnfoldFinish()));

    pAnimation->setStartValue(QRect(0, 0, width, height));
    pAnimation->setEndValue(QRect(0, height, width, height));
    pAnimation->start(QAbstractAnimation::DeleteWhenStopped);
}

/**
 * @brief SingleMsg::startAnimationFold
 * 开启多消息折叠时动画
 */
void SingleMsg::startAnimationFold()
{
    int width = this->width();
    int height = this->height();

    m_pAnimationBaseMapWidget->setFixedSize(380, (height - 6));
    m_pAnimationBaseMapWidget->setVisible(true);
    m_pAppVLaout->removeWidget(m_pSingleWidget);
    m_pAppVLaout->addWidget(m_pAnimationBaseMapWidget, 0, Qt::AlignHCenter);

    //设置show动画
    QPropertyAnimation* pAnimation = new QPropertyAnimation(m_pSingleWidget, "geometry");
    pAnimation->setDuration(50);
    connect(pAnimation, &QPropertyAnimation::valueChanged, this, &SingleMsg::updateFoldMove);
    connect(pAnimation, SIGNAL(finished()), this, SLOT(onFoldFinish()));

    pAnimation->setStartValue(QRect(0, 0, width, height));
    pAnimation->setEndValue(QRect(0, height, width, height));
    pAnimation->start(QAbstractAnimation::DeleteWhenStopped);
}

/**
 * @brief SingleMsg::startAnimationDeleLeftMove
 * 开启删除左移动画
 */
void SingleMsg::startAnimationDeleLeftMove()
{
    int nWidth = this->width();
    int nHeight = this->height();
    nHeight = nHeight - 6;                  //减去底部6px的空白区域，得出动画框体偏移高度

    m_pAppVLaout->removeWidget(m_pSingleWidget);
    m_pAnimationBaseMapWidget->setFixedSize(nWidth, nHeight);
    m_pAnimationBaseMapWidget->setVisible(true);
    m_pAppVLaout->addWidget(m_pAnimationBaseMapWidget, 0, Qt::AlignHCenter);

    //设置show动画
    QPropertyAnimation* pAnimation = new QPropertyAnimation(m_pSingleWidget, "geometry");
    pAnimation->setDuration(150);
    connect(pAnimation, &QPropertyAnimation::valueChanged, this, &SingleMsg::updateDeleLeftMove);
    connect(pAnimation, SIGNAL(finished()), this, SLOT(onDeleLeftMoveFinish()));

    pAnimation->setStartValue(QRect(0, 0, nWidth, nHeight));
    pAnimation->setEndValue(QRect(0 - nWidth, 0, nWidth, nHeight));
    pAnimation->start(QAbstractAnimation::DeleteWhenStopped);

}

/**
 * @brief SingleMsg::startAnimationDeleUpperMove
 * 开启删除上移动画
 */
void SingleMsg::startAnimationDeleUpperMove()
{
    int width = this->width();
    int height = this->height();

    //设置show动画
    QPropertyAnimation* pAnimation = new QPropertyAnimation(m_pAnimationBaseMapWidget, "geometry");
    pAnimation->setDuration(150);
    connect(pAnimation, &QPropertyAnimation::valueChanged, this, &SingleMsg::updateDeleUpperMove);
    connect(pAnimation, SIGNAL(finished()), this, SLOT(onDeleUpperMoveFinish()));

    pAnimation->setStartValue(QRect(0, 0, width, height));
    pAnimation->setEndValue(QRect(0, 0 - height, width, height));
    pAnimation->start(QAbstractAnimation::DeleteWhenStopped);
}

/**
 * @brief SingleMsg::initGsetting
 * 初始化 主题、控制面板 gsetting
 */
void SingleMsg::initGsetting()
{
    /* 创建主题 gsetting 信号连接 */
    connect(StyleGsetting::getInstance(),&StyleGsetting::Sig_styleGsettingChanged,[=](QString key){
        setLabelAlphaF(m_pAppNameLabel,0.45);
        setLabelAlphaF(m_pTimeLabel,0.45);
        setLabelAlphaF(m_pBodyLabel,0.65);
        setLabelAlphaF(m_pShowLeftItemLabel,0.65);
    });

    //更新小时设置状态
    if (ControlCenterPanelGsetting::getInstance()->getHourSystem() == TIME_FORMAT) {
        m_bTimeFormat = TWELVE_HOUR_SYSTEM;
    } else {
        m_bTimeFormat = TWENTY_FOUR_HOUR_SYSTEM;
    }

    /* 控制面板 - 12/24 小时制  gsetting 初始化 */
    connect(ControlCenterPanelGsetting::getInstance(), \
            &ControlCenterPanelGsetting::Sig_appNotifySettingChanged, [=](QString key){
        if (key == CONTROL_CENTER_PANEL_HOUR_KEY) {
            if (ControlCenterPanelGsetting::getInstance()->getHourSystem() == TIME_FORMAT) {
                m_bTimeFormat = TWELVE_HOUR_SYSTEM;
            } else {
                m_bTimeFormat = TWENTY_FOUR_HOUR_SYSTEM;
            }
            updatePushTime();//更新时间
        }
    });

    return;
}

/**
 * @brief SingleMsg::onDele
 * 通知中心消息删除
 */
void SingleMsg::onDele()
{
    NotificationGsetting::getInstance()->setState(false);

    if((true == m_bMain) && (true == m_bFold) && (m_nShowLeftCount > 0)){
        m_pAppVLaout->setContentsMargins(0,0,0,6);
        emit Sig_notifyAppHideBaseMap();
    }

    /* 设置一个单次定时器,只为延迟2毫秒执行删除 */
    QTimer *m_pSetDeleDelayTimer = new QTimer();
    m_pSetDeleDelayTimer->setSingleShot(true);
    connect(m_pSetDeleDelayTimer, SIGNAL(timeout()), this, SLOT(startAnimationDeleLeftMove()));
    m_pSetDeleDelayTimer->start(2);

    //点击删除~~~，收集数据
    pointDataStruct pointData;
    pointData.module = MESSAGEBAR + m_strAppName;
    pointData.function = DELETE;
    pointData.otherFunction.append(m_strBody);
    DataProcess::getInstance()->sendData(pointData);

    return;
}

/**
 * @brief SingleMsg::updateUnfoldMove
 * 更新展开的移动数据
 * @param value
 */
void SingleMsg::updateUnfoldMove(const QVariant &value)
{
    QRect Rect = value.value<QRect>();
    int x1, y1, x2, y2;
    Rect.getRect(&x1, &y1, &x2, &y2);

    //首先将填充控件的高度不断增加直至6
    if(y1 <= 6){
        m_pAppVLaout->setContentsMargins(0, 0, 0, y1);

    } else {
        m_pAppVLaout->setContentsMargins(0, 0, 0, 6);               //当填充控件增加直至6以后
        m_pSingleWidget->setGeometry(0, (y1 - y2), x2, (y2 - 6));   //(y2 - 6)即为m_pSingleWidget的本来高度
        m_pAnimationBaseMapWidget->setFixedSize(x2, (y1 - 6));
    }

    return;
}

/**
 * @brief SingleMsg::updateFoldMove
 * 更新折叠的移动数据
 * @param value
 */
void SingleMsg::updateFoldMove(const QVariant &value)
{
    QRect Rect = value.value<QRect>();
    int x1, y1, x2, y2;
    Rect.getRect(&x1, &y1, &x2, &y2);

    //m_pSingleWidget的本来高度
    int nHeight = y2 - 6;

    //首先将m_pSingleWidget慢慢消失
    if(y1 <= nHeight) {
        m_pSingleWidget->setGeometry(0, (0 - y1), x2, nHeight);
        m_pAnimationBaseMapWidget->setFixedSize(x2, (nHeight - y1));
    } else {
        m_pSingleWidget->setGeometry(0, (0 - nHeight), x2, nHeight);    //当m_pSingleWidget消失后，开始将底部6个px的空白消失
        m_pAnimationBaseMapWidget->setFixedSize(x2, 0);
        m_pAppVLaout->setContentsMargins(0, 0, 0, (6 - (y1 - nHeight)));
    }

    return;
}

/**
 * @brief SingleMsg::onUnfoldFinish
 * 处理展开完成时的函数
 */
void SingleMsg::onUnfoldFinish()
{
    m_pAppVLaout->removeWidget(m_pAnimationBaseMapWidget);
    m_pAnimationBaseMapWidget->setVisible(false);
    m_pAppVLaout->addWidget(m_pSingleWidget);
}

/**
 * @brief SingleMsg::onFoldFinish
 * 处理折叠完成时的函数
 */
void SingleMsg::onFoldFinish()
{
    this->setVisible(false);
    m_pAppVLaout->removeWidget(m_pAnimationBaseMapWidget);
    m_pAnimationBaseMapWidget->setVisible(false);
    m_pAppVLaout->addWidget(m_pSingleWidget);

    setFoldFlag(true);
    setBodyLabelWordWrap(false);

    emit Sig_notifyAppShowBaseMap();
}

/**
 * @brief SingleMsg::updateDeleLeftMove
 * 更新删除左移时的移动数据
 * @param value
 */
void SingleMsg::updateDeleLeftMove(const QVariant &value)
{
    QRect Rect = value.value<QRect>();
    int x1, y1, x2, y2;
    Rect.getRect(&x1, &y1, &x2, &y2);
    m_pSingleWidget->setGeometry(x1, 0, x2, y2);
}

/**
 * @brief SingleMsg::onDeleLeftMoveFinish
 * 处理删除左移完成时的函数
 */
void SingleMsg::onDeleLeftMoveFinish()
{
    startAnimationDeleUpperMove();
}

/**
 * @brief SingleMsg::updateDeleUpperMove
 * //更新删除上移时的移动数据
 * @param value
 */
void SingleMsg::updateDeleUpperMove(const QVariant &value)
{
    QRect Rect = value.value<QRect>();
    int x1, y1, x2, y2;
    Rect.getRect(&x1, &y1, &x2, &y2);

   // y2-6表示填充控件的高度，y1为负数，首先将填充控件的高度不断减少直至0
    if ((y2 - 6 + y1) >= 0) {
        m_pAnimationBaseMapWidget->setFixedSize(x2, (y2 - 6 + y1));
    } else {
        m_pAnimationBaseMapWidget->setVisible(false);           //当填充控件减至0以后，就需要减少底部6个px的空白
        m_pAppVLaout->setContentsMargins(0,0,0,(y2 + y1));
    }
}

/**
 * @brief SingleMsg::onDeleUpperMoveFinish
 * 处理删除上移完成时的函数
 */
void SingleMsg::onDeleUpperMoveFinish()
{
    if((true == m_bMain) && (true == m_bFold) && (m_nShowLeftCount > 0)) {
        /* 点击的是折叠状态下的主消息的删除按钮 */
        emit Sig_onDeleteAppMsg();
    } else if ((true == m_bMain) && (m_nShowLeftCount == 0) && jumpFlag) {
        /* 仅有一条消息时点击消息体 */
        emit Sig_jumpAction();
    } else {
        if (jumpFlag) {
            emit Sig_jumpAction();
        } else {
            emit Sig_onDeleSingleMsg(this);
        }
    }
}

/**
 * @brief SingleMsg::setLabelAlphaF
 * 设置文本透明度
 * @param this_label 要设置的标签
 * @param alpha 要设置的透明度
 */
void SingleMsg::setLabelAlphaF(QLabel *this_label, qreal alpha)
{
    QPalette palette = this_label->palette();
    QStyleOption opt;
    opt.init(this_label);
    QColor color = opt.palette.color(QPalette::Text);
    color.setAlphaF(alpha);
    palette.setBrush(QPalette::WindowText, color);
    this_label->setPalette(palette);
}


SingleWidget::SingleWidget()
{
    status = NORMAL;
}

/**
 * @brief SingleWidget::paintEvent
 * 绘画事件 完成消息的样式绘制
 * @param e
 */
void SingleWidget::paintEvent(QPaintEvent *e)
{
    QPainter p(this);
    QRect rect = this->rect();
    rect.setWidth(rect.width() - 1);
    rect.setHeight(rect.height() - 1);
    p.setRenderHint(QPainter::Antialiasing);

    QPainterPath rectPath;
    rectPath.addRoundedRect(this->rect().adjusted(0, 0, 0, 0), 6, 6);

    QPixmap pixmap(this->rect().size());
    pixmap.fill(Qt::transparent);
    QPainter pixmapPainter(&pixmap);
    pixmapPainter.setRenderHint(QPainter::Antialiasing);
    pixmapPainter.setPen(Qt::transparent);
    pixmapPainter.setBrush(Qt::black);
    pixmapPainter.drawPath(rectPath);
    pixmapPainter.end();

    QImage img = pixmap.toImage();
    qt_blurImage(img, 2, false, false);

    pixmap = QPixmap::fromImage(img);
    QPainter pixmapPainter2(&pixmap);
    pixmapPainter2.setRenderHint(QPainter::Antialiasing);
    pixmapPainter2.setCompositionMode(QPainter::CompositionMode_Clear);
    pixmapPainter2.setPen(Qt::transparent);
    pixmapPainter2.setBrush(QColor(255, 255, 255, 20));
    pixmapPainter2.drawPath(rectPath);

    p.drawPixmap(this->rect(), pixmap, pixmap.rect());
    p.save();
    QColor color = qApp->palette().color(QPalette::Base);
    color.setAlphaF(1);
    p.fillPath(rectPath, color);
    p.restore();

    QWidget::paintEvent(e);
}

/**
 * @brief SingleWidget::enterEvent
 * 进入状态，更新 status : HOVER
 * @param event
 */
void SingleWidget::enterEvent(QEvent *event)
{
    Q_UNUSED(event);
    status = HOVER;
    QWidget::enterEvent(event);
}

/**
 * @brief SingleWidget::leaveEvent
 * 离开状态，更新 status : NORMAL
 * @param event
 */
void SingleWidget::leaveEvent(QEvent *event)
{
    Q_UNUSED(event);
    status = NORMAL;
    QWidget::leaveEvent(event);
}

/**
 * @brief SingleWidget::mousePressEvent
 * 点击事件，更新 status : PRESS
 * @param event
 */
void SingleWidget::mousePressEvent(QMouseEvent *event)
{
    Q_UNUSED(event);
    status = PRESS;
    QWidget::mousePressEvent(event);
}


