/*
 * Copyright (C) 2011, 2013 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 "WebNotificationManagerProxy.h"

#include "ImmutableArray.h"
#include "ImmutableDictionary.h"
#include "WebContext.h"
#include "WebNotification.h"
#include "WebNotificationManagerMessages.h"
#include "WebNotificationManagerProxyMessages.h"
#include "WebPageProxy.h"
#include "WebSecurityOrigin.h"

using namespace WTF;
using namespace WebCore;

namespace WebKit {

const char* WebNotificationManagerProxy::supplementName()
{
    return "WebNotificationManagerProxy";
}

PassRefPtr<WebNotificationManagerProxy> WebNotificationManagerProxy::create(WebContext* context)
{
    return adoptRef(new WebNotificationManagerProxy(context));
}

WebNotificationManagerProxy::WebNotificationManagerProxy(WebContext* context)
    : WebContextSupplement(context)
{
    WebContextSupplement::context()->addMessageReceiver(Messages::WebNotificationManagerProxy::messageReceiverName(), this);
}

void WebNotificationManagerProxy::initializeProvider(const WKNotificationProvider *provider)
{
    m_provider.initialize(provider);
    m_provider.addNotificationManager(this);
}

// WebContextSupplement

void WebNotificationManagerProxy::contextDestroyed()
{
    m_provider.removeNotificationManager(this);
}

void WebNotificationManagerProxy::refWebContextSupplement()
{
    APIObject::ref();
}

void WebNotificationManagerProxy::derefWebContextSupplement()
{
    APIObject::deref();
}

// CoreIPC::MessageReceiver

void WebNotificationManagerProxy::populateCopyOfNotificationPermissions(HashMap<String, bool>& permissions)
{
    RefPtr<ImmutableDictionary> knownPermissions = m_provider.notificationPermissions();

    if (!knownPermissions)
        return;

    permissions.clear();
    RefPtr<ImmutableArray> knownOrigins = knownPermissions->keys();
    for (size_t i = 0; i < knownOrigins->size(); ++i) {
        WebString* origin = knownOrigins->at<WebString>(i);
        permissions.set(origin->string(), knownPermissions->get<WebBoolean>(origin->string())->value());
    }
}

void WebNotificationManagerProxy::show(WebPageProxy* page, const String& title, const String& body, const String& iconURL, const String& tag, const String& lang, const String& dir, const String& originString, uint64_t notificationID)
{
    if (!isNotificationIDValid(notificationID))
        return;
    
    RefPtr<WebNotification> notification = WebNotification::create(title, body, iconURL, tag, lang, dir, originString, notificationID);
    m_notifications.set(notificationID, notification);
    m_provider.show(page, notification.get());
}

void WebNotificationManagerProxy::cancel(uint64_t notificationID)
{
    if (!isNotificationIDValid(notificationID))
        return;

    RefPtr<WebNotification> notification = m_notifications.get(notificationID);
    if (!notification)
        return;

    m_provider.cancel(notification.get());
}
    
void WebNotificationManagerProxy::didDestroyNotification(uint64_t notificationID)
{
    if (!isNotificationIDValid(notificationID))
        return;

    RefPtr<WebNotification> notification = m_notifications.take(notificationID);
    if (!notification)
        return;

    m_provider.didDestroyNotification(notification.get());
}

void WebNotificationManagerProxy::clearNotifications(const Vector<uint64_t>& notificationIDs)
{
    m_provider.clearNotifications(notificationIDs);
    size_t count = notificationIDs.size();
    for (size_t i = 0; i < count; ++i)
        m_notifications.remove(notificationIDs[i]);
}

void WebNotificationManagerProxy::providerDidShowNotification(uint64_t notificationID)
{
    if (!context())
        return;
    
    context()->sendToAllProcesses(Messages::WebNotificationManager::DidShowNotification(notificationID));
}

void WebNotificationManagerProxy::providerDidClickNotification(uint64_t notificationID)
{
    if (!context())
        return;
    
    context()->sendToAllProcesses(Messages::WebNotificationManager::DidClickNotification(notificationID));
}


void WebNotificationManagerProxy::providerDidCloseNotifications(ImmutableArray* notificationIDs)
{
    if (!context())
        return;
    
    size_t size = notificationIDs->size();
    
    Vector<uint64_t> vectorNotificationIDs;
    vectorNotificationIDs.reserveInitialCapacity(size);
    
    for (size_t i = 0; i < size; ++i) {
        uint64_t notificationID = notificationIDs->at<WebUInt64>(i)->value();
        vectorNotificationIDs.append(notificationID);
    }
    
    if (vectorNotificationIDs.size())
        context()->sendToAllProcesses(Messages::WebNotificationManager::DidCloseNotifications(vectorNotificationIDs));
}

void WebNotificationManagerProxy::providerDidUpdateNotificationPolicy(const WebSecurityOrigin* origin, bool allowed)
{
    if (!context())
        return;

    context()->sendToAllProcesses(Messages::WebNotificationManager::DidUpdateNotificationDecision(origin->toString(), allowed));
}

void WebNotificationManagerProxy::providerDidRemoveNotificationPolicies(ImmutableArray* origins)
{
    if (!context())
        return;

    size_t size = origins->size();
    if (!size)
        return;
    
    Vector<String> originStrings;
    originStrings.reserveInitialCapacity(size);
    
    for (size_t i = 0; i < size; ++i)
        originStrings.append(origins->at<WebSecurityOrigin>(i)->toString());
    
    context()->sendToAllProcesses(Messages::WebNotificationManager::DidRemoveNotificationDecisions(originStrings));
}

} // namespace WebKit
