/*
 * Copyright (C) 2022 Apple Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 * THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "config.h"
#include "TestNotificationProvider.h"

#include <WebKit/WKArray.h>
#include <WebKit/WKContext.h>
#include <WebKit/WKMutableDictionary.h>
#include <WebKit/WKNotification.h>
#include <WebKit/WKNotificationManager.h>
#include <WebKit/WKNumber.h>
#include <WebKit/WKPage.h>
#include <WebKit/WKSecurityOriginRef.h>
#include <WebKit/WKString.h>
#include <wtf/text/WTFString.h>

namespace TestWebKitAPI {

static void showWebNotification(WKPageRef page, WKNotificationRef notification, const void* clientInfo)
{
    static_cast<TestNotificationProvider*>(const_cast<void*>(clientInfo))->showWebNotification(page, notification);
}

static void closeWebNotification(WKNotificationRef notification, const void* clientInfo)
{
    static_cast<TestNotificationProvider*>(const_cast<void*>(clientInfo))->closeWebNotification(notification);
}

static WKDictionaryRef notificationPermissions(const void* clientInfo)
{
    return static_cast<TestNotificationProvider*>(const_cast<void*>(clientInfo))->notificationPermissions();
}

TestNotificationProvider::TestNotificationProvider(Vector<WKNotificationManagerRef>&& managers)
    : m_managers(WTFMove(managers))
{
    m_provider = {
        WKNotificationProviderBase { 0, this },
        &TestWebKitAPI::showWebNotification,
        &TestWebKitAPI::closeWebNotification,
        0, // didDestroyNotification
        0, // addNotificationManager
        0, // removeNotificationManager
        &TestWebKitAPI::notificationPermissions,
        0, // clearNotifications
    };

    for (auto& manager : m_managers)
        WKNotificationManagerSetProvider(manager, &m_provider.base);
}

TestNotificationProvider::~TestNotificationProvider()
{
    for (auto& manager : m_managers)
        WKNotificationManagerSetProvider(manager, nullptr);
}

WKDictionaryRef TestNotificationProvider::notificationPermissions() const
{
    auto permissions = WKMutableDictionaryCreate();

    for (auto& [origin, allowed] : m_permissions) {
        auto wkOriginString = adoptWK(WKStringCreateWithUTF8CString(origin.utf8().data()));
        auto wkAllowed = adoptWK(WKBooleanCreate(allowed));
        WKDictionarySetItem(permissions, wkOriginString.get(), wkAllowed.get());
    }

    return permissions;
}

void TestNotificationProvider::setPermission(const String& origin, bool allowed)
{
    m_permissions.set(origin, allowed);

    auto wkOriginString = adoptWK(WKStringCreateWithUTF8CString(origin.utf8().data()));
    auto wkOrigin = adoptWK(WKSecurityOriginCreateFromString(wkOriginString.get()));

    for (auto& manager : m_managers)
        WKNotificationManagerProviderDidUpdateNotificationPolicy(manager, wkOrigin.get(), allowed);
}

void TestNotificationProvider::resetPermission(const String& origin)
{
    m_permissions.remove(origin);

    auto wkOriginString = adoptWK(WKStringCreateWithUTF8CString(origin.utf8().data()));
    auto wkOrigin = adoptWK(WKSecurityOriginCreateFromString(wkOriginString.get()));
    auto wkOriginTypeRef = static_cast<WKTypeRef>(wkOrigin.get());
    auto wkOriginArray = adoptWK(WKArrayCreate(&wkOriginTypeRef, 1));

    for (auto& manager : m_managers)
        WKNotificationManagerProviderDidRemoveNotificationPolicies(manager, wkOriginArray.get());
}

static WKNotificationManagerRef notificationManagerForPage(WKPageRef page)
{
    if (page)
        return WKContextGetNotificationManager(WKPageGetContext(page));

    return WKNotificationManagerGetSharedServiceWorkerNotificationManager();
}

void TestNotificationProvider::showWebNotification(WKPageRef page, WKNotificationRef notification)
{
    m_hasReceivedShowNotification = true;

    auto notificationManager = notificationManagerForPage(page);
    uint64_t identifier = WKNotificationGetID(notification);
    WKNotificationManagerProviderDidShowNotification(notificationManager, identifier);

    WKRetain(notificationManager);
    m_pendingNotification = std::make_pair(notificationManager, identifier);

    m_lastNotificationDataStoreIdentifier = adoptWK(WKNotificationCopyDataStoreIdentifier(notification));
}

void TestNotificationProvider::closeWebNotification(WKNotificationRef notification)
{
    ASSERT(!m_hasReceivedCloseNotification);
    m_hasReceivedCloseNotification = true;
}

void TestNotificationProvider::resetHasReceivedNotification()
{
    m_hasReceivedShowNotification = false;
    m_hasReceivedCloseNotification = false;
}

bool TestNotificationProvider::simulateNotificationClick()
{
    if (!m_pendingNotification.first)
        return false;

    callOnMainThread([pair = std::exchange(m_pendingNotification, { })] {
        WKNotificationManagerProviderDidClickNotification(pair.first, pair.second);
        WKRelease(pair.first);
    });

    return true;
}

bool TestNotificationProvider::simulateNotificationClose()
{
    if (!m_pendingNotification.first)
        return false;

    callOnMainThread([pair = std::exchange(m_pendingNotification, { })] {
        auto id = adoptWK(WKUInt64Create(pair.second));
        auto idRef = static_cast<WKTypeRef>(id.get());
        auto wkArray = adoptWK(WKArrayCreate(&idRef, 1));

        WKNotificationManagerProviderDidCloseNotifications(pair.first, wkArray.get());
        WKRelease(pair.first);
    });

    return true;
}

} // namespace TestWebKitAPI
