/****************************************************************************
**
** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the plugins of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/

#if defined(WINVER) && WINVER < 0x0601
#  undef WINVER
#endif
#if !defined(WINVER)
#  define WINVER 0x0601 // required for NOTIFYICONDATA_V2_SIZE, ChangeWindowMessageFilterEx() (MinGW 5.3)
#endif

#if defined(NTDDI_VERSION) && NTDDI_VERSION < 0x06010000
#  undef NTDDI_VERSION
#endif
#if !defined(NTDDI_VERSION)
#  define NTDDI_VERSION 0x06010000 // required for Shell_NotifyIconGetRect (MinGW 5.3)
#endif

#include "qwindowssystemtrayicon.h"
#include "qwindowscontext.h"
#include "qwindowstheme.h"
#include "qwindowsmenu.h"
#include "qwindowsscreen.h"

#include <QtGui/qguiapplication.h>
#include <QtGui/qpixmap.h>
#include <QtCore/qdebug.h>
#include <QtCore/qrect.h>
#include <QtCore/qvector.h>
#include <QtCore/qsettings.h>
#include <qpa/qwindowsysteminterface.h>

#include <qt_windows.h>
#include <commctrl.h>
#include <shellapi.h>
#include <shlobj.h>
#include <windowsx.h>

QT_BEGIN_NAMESPACE

static const UINT q_uNOTIFYICONID = 0;

static uint MYWM_TASKBARCREATED = 0;
#define MYWM_NOTIFYICON (WM_APP+101)

Q_GUI_EXPORT HICON qt_pixmapToWinHICON(const QPixmap &);

// Copy QString data to a limited wchar_t array including \0.
static inline void qStringToLimitedWCharArray(QString in, wchar_t *target, int maxLength)
{
    const int length = qMin(maxLength - 1, in.size());
    if (length < in.size())
        in.truncate(length);
    in.toWCharArray(target);
    target[length] = wchar_t(0);
}

static inline void initNotifyIconData(NOTIFYICONDATA &tnd)
{
    memset(&tnd, 0, sizeof(NOTIFYICONDATA));
    tnd.cbSize = sizeof(NOTIFYICONDATA);
    tnd.uVersion = NOTIFYICON_VERSION_4;
}

static void setIconContents(NOTIFYICONDATA &tnd, const QString &tip, HICON hIcon)
{
    tnd.uFlags |= NIF_MESSAGE | NIF_ICON | NIF_TIP;
    tnd.uCallbackMessage = MYWM_NOTIFYICON;
    tnd.hIcon = hIcon;
    qStringToLimitedWCharArray(tip, tnd.szTip, sizeof(tnd.szTip) / sizeof(wchar_t));
}

static void setIconVisibility(NOTIFYICONDATA &tnd, bool v)
{
    tnd.uFlags |= NIF_STATE;
    tnd.dwStateMask = NIS_HIDDEN;
    tnd.dwState = v ? 0 : NIS_HIDDEN;
}

// Match the HWND of the dummy window to the instances
struct QWindowsHwndSystemTrayIconEntry
{
    HWND hwnd;
    QWindowsSystemTrayIcon *trayIcon;
};

using HwndTrayIconEntries = QVector<QWindowsHwndSystemTrayIconEntry>;

Q_GLOBAL_STATIC(HwndTrayIconEntries, hwndTrayIconEntries)

static int indexOfHwnd(HWND hwnd)
{
    const HwndTrayIconEntries *entries = hwndTrayIconEntries();
    for (int i = 0, size = entries->size(); i < size; ++i) {
        if (entries->at(i).hwnd == hwnd)
            return i;
    }
    return -1;
}

extern "C" LRESULT QT_WIN_CALLBACK qWindowsTrayIconWndProc(HWND hwnd, UINT message,
                                                           WPARAM wParam, LPARAM lParam)
{
    // QTBUG-79248: Trigger screen update if there are no other windows.
    if (message == WM_DPICHANGED && QGuiApplication::topLevelWindows().isEmpty())
        QWindowsContext::instance()->screenManager().handleScreenChanges();
    if (message == MYWM_TASKBARCREATED || message == MYWM_NOTIFYICON
        || message == WM_INITMENU || message == WM_INITMENUPOPUP
        || message == WM_CLOSE || message == WM_COMMAND) {
        const int index = indexOfHwnd(hwnd);
        if (index >= 0) {
            MSG msg;
            msg.hwnd = hwnd;         // re-create MSG structure
            msg.message = message;   // time and pt fields ignored
            msg.wParam = wParam;
            msg.lParam = lParam;
            msg.pt.x = GET_X_LPARAM(lParam);
            msg.pt.y = GET_Y_LPARAM(lParam);
            long result = 0;
            if (hwndTrayIconEntries()->at(index).trayIcon->winEvent(msg, &result))
                return result;
        }
    }
    return DefWindowProc(hwnd, message, wParam, lParam);
}

// Note: Message windows (HWND_MESSAGE) are not sufficient, they
// will not receive the "TaskbarCreated" message.
static inline HWND createTrayIconMessageWindow()
{
    QWindowsContext *ctx = QWindowsContext::instance();
    if (!ctx)
        return nullptr;
    // Register window class in the platform plugin.
    const QString className =
        ctx->registerWindowClass(QStringLiteral("QTrayIconMessageWindowClass"),
                                 qWindowsTrayIconWndProc);
    const wchar_t windowName[] = L"QTrayIconMessageWindow";
    return CreateWindowEx(0, reinterpret_cast<const wchar_t *>(className.utf16()),
                          windowName, WS_OVERLAPPED,
                          CW_USEDEFAULT, CW_USEDEFAULT,
                          CW_USEDEFAULT, CW_USEDEFAULT,
                          nullptr, nullptr,
                          static_cast<HINSTANCE>(GetModuleHandle(nullptr)), nullptr);
}

/*!
    \class QWindowsSystemTrayIcon
    \brief Windows native system tray icon

    \internal
    \ingroup qt-lighthouse-win
*/

QWindowsSystemTrayIcon::QWindowsSystemTrayIcon()
{
}

QWindowsSystemTrayIcon::~QWindowsSystemTrayIcon()
{
    qCDebug(lcQpaTrayIcon) << __FUNCTION__ << this;
    ensureCleanup();
}

void QWindowsSystemTrayIcon::init()
{
    qCDebug(lcQpaTrayIcon) << __FUNCTION__ << this;
    m_visible = true;
    if (!setIconVisible(m_visible))
        ensureInstalled();
}

void QWindowsSystemTrayIcon::cleanup()
{
    qCDebug(lcQpaTrayIcon) << __FUNCTION__ << this;
    m_visible = false;
    ensureCleanup();
}

void QWindowsSystemTrayIcon::updateIcon(const QIcon &icon)
{
    qCDebug(lcQpaTrayIcon) << __FUNCTION__ << '(' << icon << ')' << this;
    if (icon.cacheKey() == m_icon.cacheKey())
        return;
    const HICON hIconToDestroy = createIcon(icon);
    if (ensureInstalled())
        sendTrayMessage(NIM_MODIFY);
    if (hIconToDestroy)
        DestroyIcon(hIconToDestroy);
}

void QWindowsSystemTrayIcon::updateToolTip(const QString &tooltip)
{
    qCDebug(lcQpaTrayIcon) << __FUNCTION__ << '(' << tooltip << ')' << this;
    if (m_toolTip == tooltip)
        return;
    m_toolTip = tooltip;
    if (isInstalled())
        sendTrayMessage(NIM_MODIFY);
}

QRect QWindowsSystemTrayIcon::geometry() const
{
    NOTIFYICONIDENTIFIER nid;
    memset(&nid, 0, sizeof(nid));
    nid.cbSize = sizeof(nid);
    nid.hWnd = m_hwnd;
    nid.uID = q_uNOTIFYICONID;
    RECT rect;
    const QRect result = SUCCEEDED(Shell_NotifyIconGetRect(&nid, &rect))
        ? QRect(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top)
        : QRect();
    qCDebug(lcQpaTrayIcon) << __FUNCTION__ << this << "returns" << result;
    return result;
}

void QWindowsSystemTrayIcon::showMessage(const QString &title, const QString &messageIn,
                                         const QIcon &icon,
                                         QPlatformSystemTrayIcon::MessageIcon iconType,
                                         int msecsIn)
{
    qCDebug(lcQpaTrayIcon) << __FUNCTION__ << '(' << title << messageIn << icon
        << iconType << msecsIn  << ')' << this;
    if (!supportsMessages())
        return;
    // For empty messages, ensures that they show when only title is set
    QString message = messageIn;
    if (message.isEmpty() && !title.isEmpty())
        message.append(QLatin1Char(' '));

    NOTIFYICONDATA tnd;
    initNotifyIconData(tnd);
    qStringToLimitedWCharArray(message, tnd.szInfo, 256);
    qStringToLimitedWCharArray(title, tnd.szInfoTitle, 64);

    tnd.uID = q_uNOTIFYICONID;
    tnd.dwInfoFlags = NIIF_USER;

    QSize size(GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON));
    const QSize largeIcon(GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON));
    const QSize more = icon.actualSize(largeIcon);
    if (more.height() > (largeIcon.height() * 3/4) || more.width() > (largeIcon.width() * 3/4)) {
        tnd.dwInfoFlags |= NIIF_LARGE_ICON;
        size = largeIcon;
    }
    QPixmap pm = icon.pixmap(size);
    if (pm.isNull()) {
        tnd.dwInfoFlags = NIIF_INFO;
    } else {
        if (pm.size() != size) {
            qWarning("QSystemTrayIcon::showMessage: Wrong icon size (%dx%d), please add standard one: %dx%d",
                      pm.size().width(), pm.size().height(), size.width(), size.height());
            pm = pm.scaled(size, Qt::IgnoreAspectRatio);
        }
        tnd.hBalloonIcon = qt_pixmapToWinHICON(pm);
    }
    tnd.hWnd = m_hwnd;
    tnd.uTimeout = msecsIn <= 0 ?  UINT(10000) : UINT(msecsIn); // 10s default
    tnd.uFlags = NIF_INFO | NIF_SHOWTIP;

    Shell_NotifyIcon(NIM_MODIFY, &tnd);
}

bool QWindowsSystemTrayIcon::supportsMessages() const
{
    // The key does typically not exist on Windows 10, default to true.
    return QWindowsContext::readAdvancedExplorerSettings(L"EnableBalloonTips", 1) != 0;
}

QPlatformMenu *QWindowsSystemTrayIcon::createMenu() const
{
    if (QWindowsTheme::useNativeMenus() && m_menu.isNull())
        m_menu = new QWindowsPopupMenu;
    qCDebug(lcQpaTrayIcon) << __FUNCTION__ << this << "returns" << m_menu.data();
    return m_menu.data();
}

// Delay-install until an Icon exists
bool QWindowsSystemTrayIcon::ensureInstalled()
{
    if (isInstalled())
        return true;
    if (m_hIcon == nullptr)
        return false;
    m_hwnd = createTrayIconMessageWindow();
    if (Q_UNLIKELY(m_hwnd == nullptr))
        return false;
    // For restoring the tray icon after explorer crashes
    if (!MYWM_TASKBARCREATED)
        MYWM_TASKBARCREATED = RegisterWindowMessage(L"TaskbarCreated");
    // Allow the WM_TASKBARCREATED message through the UIPI filter
    ChangeWindowMessageFilterEx(m_hwnd, MYWM_TASKBARCREATED, MSGFLT_ALLOW, nullptr);
    qCDebug(lcQpaTrayIcon) << __FUNCTION__ << this << "MYWM_TASKBARCREATED=" << MYWM_TASKBARCREATED;

    QWindowsHwndSystemTrayIconEntry entry{m_hwnd, this};
    hwndTrayIconEntries()->append(entry);
    sendTrayMessage(NIM_ADD);
    return true;
}

void QWindowsSystemTrayIcon::ensureCleanup()
{
    if (isInstalled()) {
        const int index = indexOfHwnd(m_hwnd);
        if (index >= 0)
            hwndTrayIconEntries()->removeAt(index);
        sendTrayMessage(NIM_DELETE);
        DestroyWindow(m_hwnd);
        m_hwnd = nullptr;
    }
    if (m_hIcon != nullptr)
        DestroyIcon(m_hIcon);
    m_hIcon = nullptr;
    m_menu = nullptr; // externally owned
    m_toolTip.clear();
}

bool QWindowsSystemTrayIcon::setIconVisible(bool visible)
{
    if (!isInstalled())
        return false;
    NOTIFYICONDATA tnd;
    initNotifyIconData(tnd);
    tnd.uID = q_uNOTIFYICONID;
    tnd.hWnd = m_hwnd;
    setIconVisibility(tnd, visible);
    return Shell_NotifyIcon(NIM_MODIFY, &tnd) == TRUE;
}

bool QWindowsSystemTrayIcon::sendTrayMessage(DWORD msg)
{
    NOTIFYICONDATA tnd;
    initNotifyIconData(tnd);
    tnd.uID = q_uNOTIFYICONID;
    tnd.hWnd = m_hwnd;
    tnd.uFlags = NIF_SHOWTIP;
    if (msg != NIM_DELETE && !m_visible)
        setIconVisibility(tnd, m_visible);
    if (msg == NIM_ADD || msg == NIM_MODIFY)
        setIconContents(tnd, m_toolTip, m_hIcon);
    if (!Shell_NotifyIcon(msg, &tnd))
        return false;
    return msg != NIM_ADD || Shell_NotifyIcon(NIM_SETVERSION, &tnd);
}

// Return the old icon to be freed after modifying the tray icon.
HICON QWindowsSystemTrayIcon::createIcon(const QIcon &icon)
{
    const HICON oldIcon = m_hIcon;
    m_hIcon = nullptr;
    if (icon.isNull())
        return oldIcon;
    const QSize requestedSize = QSize(GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON));
    const QSize size = icon.actualSize(requestedSize);
    const QPixmap pm = icon.pixmap(size);
    if (!pm.isNull())
        m_hIcon = qt_pixmapToWinHICON(pm);
    return oldIcon;
}

bool QWindowsSystemTrayIcon::winEvent(const MSG &message, long *result)
{
    *result = 0;
    switch (message.message) {
    case MYWM_NOTIFYICON: {
        Q_ASSERT(q_uNOTIFYICONID == HIWORD(message.lParam));
        const int trayMessage = LOWORD(message.lParam);
        switch (trayMessage) {
        case NIN_SELECT:
        case NIN_KEYSELECT:
            if (m_ignoreNextMouseRelease)
                m_ignoreNextMouseRelease = false;
            else
                emit activated(Trigger);
            break;
        case WM_LBUTTONDBLCLK:
            m_ignoreNextMouseRelease = true; // Since DBLCLICK Generates a second mouse
            emit activated(DoubleClick);     // release we must ignore it
            break;
        case WM_CONTEXTMENU: {
            // QTBUG-67966: Coordinates may be out of any screen in PROCESS_DPI_UNAWARE mode
            // since hi-res coordinates are delivered in this case (Windows issue).
            // Default to primary screen with check to prevent a crash.
            const QPoint globalPos = QPoint(GET_X_LPARAM(message.wParam), GET_Y_LPARAM(message.wParam));
            const auto &screenManager = QWindowsContext::instance()->screenManager();
            const QPlatformScreen *screen = screenManager.screenAtDp(globalPos);
            if (!screen)
                screen = screenManager.screens().value(0);
            if (screen) {
                emit contextMenuRequested(globalPos, screen);
                emit activated(Context);
                if (m_menu)
                    m_menu->trackPopupMenu(message.hwnd, globalPos.x(), globalPos.y());
            }
        }
            break;
        case NIN_BALLOONUSERCLICK:
            emit messageClicked();
            break;
        case WM_MBUTTONUP:
            emit activated(MiddleClick);
            break;
        default:
            break;
        }
    }
        break;
    case WM_INITMENU:
    case WM_INITMENUPOPUP:
        QWindowsPopupMenu::notifyAboutToShow(reinterpret_cast<HMENU>(message.wParam));
        break;
    case WM_CLOSE:
        QWindowSystemInterface::handleApplicationTermination<QWindowSystemInterface::SynchronousDelivery>();
        break;
    case WM_COMMAND:
        QWindowsPopupMenu::notifyTriggered(LOWORD(message.wParam));
        break;
    default:
        if (message.message == MYWM_TASKBARCREATED) // self-registered message id (tray crashed)
            sendTrayMessage(NIM_ADD);
        break;
    }
    return false;
}

#ifndef QT_NO_DEBUG_STREAM

void QWindowsSystemTrayIcon::formatDebug(QDebug &d) const
{
    d << static_cast<const void *>(this) << ", \"" << m_toolTip
        << "\", hwnd=" << m_hwnd << ", m_hIcon=" << m_hIcon << ", menu="
        << m_menu.data();
}

QDebug operator<<(QDebug d, const QWindowsSystemTrayIcon *t)
{
    QDebugStateSaver saver(d);
    d.nospace();
    d.noquote();
    d << "QWindowsSystemTrayIcon(";
    if (t)
        t->formatDebug(d);
    else
        d << '0';
    d << ')';
    return d;
}
#endif // !QT_NO_DEBUG_STREAM

QT_END_NAMESPACE
