/*
 * Copyright (C) 2012 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 "WebNotificationProvider.h"

#include <WebKit/WKMutableArray.h>
#include <WebKit/WKNotification.h>
#include <WebKit/WKNotificationManager.h>
#include <WebKit/WKNumber.h>
#include <WebKit/WKSecurityOriginRef.h>
#include <wtf/Assertions.h>

namespace WTR {

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

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

static void addNotificationManager(WKNotificationManagerRef manager, const void* clientInfo)
{
    static_cast<WebNotificationProvider*>(const_cast<void*>(clientInfo))->addNotificationManager(manager);
}

static void removeNotificationManager(WKNotificationManagerRef manager, const void* clientInfo)
{
    static_cast<WebNotificationProvider*>(const_cast<void*>(clientInfo))->removeNotificationManager(manager);
}

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

WebNotificationProvider::WebNotificationProvider()
{
}

WebNotificationProvider::~WebNotificationProvider()
{
    for (auto& manager : m_ownedNotifications)
        WKNotificationManagerSetProvider(manager.key.get(), nullptr);
}

WKNotificationProviderV0 WebNotificationProvider::provider()
{
    WKNotificationProviderV0 notificationProvider = {
        { 0, this },
        WTR::showWebNotification,
        WTR::closeWebNotification,
        0, // didDestroyNotification
        WTR::addNotificationManager,
        WTR::removeNotificationManager,
        WTR::notificationPermissions,
        0, // clearNotifications
    };
    return notificationProvider;
}

void WebNotificationProvider::showWebNotification(WKPageRef page, WKNotificationRef notification)
{
    auto context = WKPageGetContext(page);
    auto notificationManager = WKContextGetNotificationManager(context);
    uint64_t id = WKNotificationGetID(notification);

    ASSERT(m_ownedNotifications.contains(notificationManager));
    auto addResult = m_ownedNotifications.find(notificationManager)->value.add(id);
    ASSERT_UNUSED(addResult, addResult.isNewEntry);
    auto addResult2 = m_owningManager.set(id, notificationManager);
    ASSERT_UNUSED(addResult2, addResult2.isNewEntry);
    auto addResult3 = m_localToGlobalNotificationIDMap.add(std::make_pair(page, WKNotificationManagerGetLocalIDForTesting(notificationManager, notification)), id);
    ASSERT_UNUSED(addResult3, addResult3.isNewEntry);

    WKNotificationManagerProviderDidShowNotification(notificationManager, id);
}

static void removeGlobalIDFromIDMap(HashMap<std::pair<WKPageRef, uint64_t>, uint64_t>& map, uint64_t id)
{
    for (auto iter = map.begin(); iter != map.end(); ++iter) {
        if (iter->value == id) {
            map.remove(iter);
            return;
        }
    }
    ASSERT_NOT_REACHED();
}

void WebNotificationProvider::closeWebNotification(WKNotificationRef notification)
{
    uint64_t id = WKNotificationGetID(notification);
    ASSERT(m_owningManager.contains(id));
    auto notificationManager = m_owningManager.get(id);

    ASSERT(m_ownedNotifications.contains(notificationManager));
    bool success = m_ownedNotifications.find(notificationManager)->value.remove(id);
    ASSERT_UNUSED(success, success);
    m_owningManager.remove(id);

    removeGlobalIDFromIDMap(m_localToGlobalNotificationIDMap, id);

    auto wkID = adoptWK(WKUInt64Create(id));
    auto array = adoptWK(WKMutableArrayCreate());
    WKArrayAppendItem(array.get(), wkID.get());
    WKNotificationManagerProviderDidCloseNotifications(notificationManager, array.get());
}

void WebNotificationProvider::addNotificationManager(WKNotificationManagerRef manager)
{
    m_ownedNotifications.add(manager, HashSet<uint64_t>());
}

void WebNotificationProvider::removeNotificationManager(WKNotificationManagerRef manager)
{
    auto iterator = m_ownedNotifications.find(manager);
    ASSERT(iterator != m_ownedNotifications.end());
    auto toRemove = iterator->value;
    WKRetainPtr<WKNotificationManagerRef> guard(manager);
    m_ownedNotifications.remove(iterator);
    auto array = adoptWK(WKMutableArrayCreate());
    for (uint64_t notificationID : toRemove) {
        bool success = m_owningManager.remove(notificationID);
        ASSERT_UNUSED(success, success);
        removeGlobalIDFromIDMap(m_localToGlobalNotificationIDMap, notificationID);
        WKArrayAppendItem(array.get(), adoptWK(WKUInt64Create(notificationID)).get());
    }
    WKNotificationManagerProviderDidCloseNotifications(manager, array.get());
}

WKDictionaryRef WebNotificationProvider::notificationPermissions()
{
    // Initial permissions are always empty.
    return WKMutableDictionaryCreate();
}

void WebNotificationProvider::simulateWebNotificationClick(WKPageRef page, uint64_t notificationID)
{
    ASSERT(m_localToGlobalNotificationIDMap.contains(std::make_pair(page, notificationID)));
    auto globalID = m_localToGlobalNotificationIDMap.get(std::make_pair(page, notificationID));
    ASSERT(m_owningManager.contains(globalID));
    WKNotificationManagerProviderDidClickNotification(m_owningManager.get(globalID), globalID);
}

void WebNotificationProvider::reset()
{
    for (auto& notificationPair : m_ownedNotifications) {
        if (notificationPair.value.isEmpty())
            continue;
        auto array = adoptWK(WKMutableArrayCreate());
        for (uint64_t notificationID : notificationPair.value)
            WKArrayAppendItem(array.get(), adoptWK(WKUInt64Create(notificationID)).get());

        notificationPair.value.clear();
        WKNotificationManagerProviderDidCloseNotifications(notificationPair.key.get(), array.get());
    }
    m_owningManager.clear();
    m_localToGlobalNotificationIDMap.clear();
}

} // namespace WTR
