/*
 * Copyright (C) 2013 Apple Inc. All rights reserved.
 * Copyright (C) 2013 Samsung Electronics. 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.
 */

// FIXME: DOMStorageManager lacks advanced multi-target support. (DOMStorage per-target)

WI.DOMStorageManager = class DOMStorageManager extends WI.Object
{
    constructor()
    {
        super();

        this._enabled = false;
        this._reset();
    }

    // Agent

    get domains() { return ["DOMStorage"]; }

    activateExtraDomain(domain)
    {
        console.assert(domain === "DOMStorage");

        for (let target of WI.targets)
            this.initializeTarget(target);
    }

    // Target

    initializeTarget(target)
    {
        if (!this._enabled)
            return;

        if (target.hasDomain("DOMStorage"))
            target.DOMStorageAgent.enable();
    }

    // Public

    get domStorageObjects() { return this._domStorageObjects; }

    get cookieStorageObjects()
    {
        var cookieStorageObjects = [];
        for (var host in this._cookieStorageObjects)
            cookieStorageObjects.push(this._cookieStorageObjects[host]);
        return cookieStorageObjects;
    }

    enable()
    {
        console.assert(!this._enabled);

        this._enabled = true;

        this._reset();

        for (let target of WI.targets)
            this.initializeTarget(target);

        WI.Frame.addEventListener(WI.Frame.Event.MainResourceDidChange, this._mainResourceDidChange, this);
        WI.Frame.addEventListener(WI.Frame.Event.SecurityOriginDidChange, this._securityOriginDidChange, this);
    }

    disable()
    {
        console.assert(this._enabled);

        this._enabled = false;

        for (let target of WI.targets) {
            if (target.hasDomain("DOMStorage"))
                target.DOMStorageAgent.disable();
        }

        WI.Frame.removeEventListener(null, null, this);

        this._reset();
    }

    // DOMStorageObserver

    itemsCleared(storageId)
    {
        console.assert(this._enabled);

        let domStorage = this._domStorageForIdentifier(storageId);
        if (domStorage)
            domStorage.itemsCleared(storageId);
    }

    itemRemoved(storageId, key)
    {
        console.assert(this._enabled);

        let domStorage = this._domStorageForIdentifier(storageId);
        if (domStorage)
            domStorage.itemRemoved(key);
    }

    itemAdded(storageId, key, value)
    {
        console.assert(this._enabled);

        let domStorage = this._domStorageForIdentifier(storageId);
        if (domStorage)
            domStorage.itemAdded(key, value);
    }

    itemUpdated(storageId, key, oldValue, newValue)
    {
        console.assert(this._enabled);

        let domStorage = this._domStorageForIdentifier(storageId);
        if (domStorage)
            domStorage.itemUpdated(key, oldValue, newValue);
    }

    // InspectorObserver

    inspectDOMStorage(id)
    {
        console.assert(this._enabled);

        var domStorage = this._domStorageForIdentifier(id);
        console.assert(domStorage);
        if (!domStorage)
            return;
        this.dispatchEventToListeners(WI.DOMStorageManager.Event.DOMStorageObjectWasInspected, {domStorage});
    }

    // Private

    _reset()
    {
        this._domStorageObjects = [];
        this._cookieStorageObjects = {};

        this.dispatchEventToListeners(DOMStorageManager.Event.Cleared);

        let mainFrame = WI.networkManager.mainFrame;
        if (mainFrame) {
            this._addDOMStorageIfNeeded(mainFrame);
            this._addCookieStorageIfNeeded(mainFrame);
        }
    }

    _domStorageForIdentifier(id)
    {
        for (var storageObject of this._domStorageObjects) {
            // The id is an object, so we need to compare the properties using Object.shallowEqual.
            if (Object.shallowEqual(storageObject.id, id))
                return storageObject;
        }

        return null;
    }

    _addDOMStorageIfNeeded(frame)
    {
        if (!this._enabled)
            return;

        if (!InspectorBackend.hasDomain("DOMStorage"))
            return;

        // Don't show storage if we don't have a security origin (about:blank).
        if (!frame.securityOrigin || frame.securityOrigin === "://")
            return;

        // FIXME: Consider passing the other parts of the origin along.

        let addDOMStorage = (isLocalStorage) => {
            let identifier = {securityOrigin: frame.securityOrigin, isLocalStorage};
            if (this._domStorageForIdentifier(identifier))
                return;

            let domStorage = new WI.DOMStorageObject(identifier, frame.mainResource.urlComponents.host, identifier.isLocalStorage);
            this._domStorageObjects.push(domStorage);
            this.dispatchEventToListeners(DOMStorageManager.Event.DOMStorageObjectWasAdded, {domStorage});
        };
        addDOMStorage(true);
        addDOMStorage(false);
    }

    _addCookieStorageIfNeeded(frame)
    {
        if (!this._enabled)
            return;

        if (!InspectorBackend.hasCommand("Page.getCookies"))
            return;

        // Add the host of the frame that changed the main resource to the list of hosts there could be cookies for.
        let host = parseURL(frame.url).host;
        if (!host)
            return;

        if (this._cookieStorageObjects[host])
            return;

        this._cookieStorageObjects[host] = new WI.CookieStorageObject(host);
        this.dispatchEventToListeners(WI.DOMStorageManager.Event.CookieStorageObjectWasAdded, {cookieStorage: this._cookieStorageObjects[host]});
    }

    _mainResourceDidChange(event)
    {
        console.assert(event.target instanceof WI.Frame);

        if (event.target.isMainFrame()) {
            this._reset();
            return;
        }

        this._addCookieStorageIfNeeded(event.target);
    }

    _securityOriginDidChange(event)
    {
        console.assert(event.target instanceof WI.Frame);

        this._addDOMStorageIfNeeded(event.target);
    }
};

WI.DOMStorageManager.Event = {
    CookieStorageObjectWasAdded: "dom-storage-manager-cookie-storage-object-was-added",
    DOMStorageObjectWasAdded: "dom-storage-manager-dom-storage-object-was-added",
    DOMStorageObjectWasInspected: "dom-storage-manager-dom-storage-object-was-inspected",
    Cleared: "dom-storage-manager-cleared",
};
