/*
 * Copyright (C) 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.
 */

WI.Frame = class Frame extends WI.Object
{
    constructor(id, name, securityOrigin, loaderIdentifier, mainResource)
    {
        super();

        console.assert(id);

        this._id = id;

        this._name = null;
        this._securityOrigin = null;

        this._resourceCollection = new WI.ResourceCollection;
        this._provisionalResourceCollection = new WI.ResourceCollection;
        this._extraScriptCollection = new WI.ScriptCollection;

        this._childFrameCollection = new WI.FrameCollection;
        this._childFrameIdentifierMap = new Map;

        this._parentFrame = null;
        this._isMainFrame = false;

        this._domContentReadyEventTimestamp = NaN;
        this._loadEventTimestamp = NaN;

        this._executionContextList = new WI.ExecutionContextList;

        this.initialize(name, securityOrigin, loaderIdentifier, mainResource);
    }

    // Public

    get resourceCollection() { return this._resourceCollection; }
    get extraScriptCollection() { return this._extraScriptCollection; }
    get childFrameCollection() { return this._childFrameCollection; }

    initialize(name, securityOrigin, loaderIdentifier, mainResource)
    {
        console.assert(loaderIdentifier);
        console.assert(mainResource);

        var oldName = this._name;
        var oldSecurityOrigin = this._securityOrigin;
        var oldMainResource = this._mainResource;

        this._name = name || null;
        this._securityOrigin = securityOrigin || null;
        this._loaderIdentifier = loaderIdentifier || null;

        this._mainResource = mainResource;
        this._mainResource._parentFrame = this;

        if (oldMainResource && this._mainResource !== oldMainResource)
            this._disassociateWithResource(oldMainResource);

        this.removeAllResources();
        this.removeAllChildFrames();
        this.clearExecutionContexts();
        this.clearProvisionalLoad();

        if (this._mainResource !== oldMainResource)
            this._dispatchMainResourceDidChangeEvent(oldMainResource);

        if (this._securityOrigin !== oldSecurityOrigin)
            this.dispatchEventToListeners(WI.Frame.Event.SecurityOriginDidChange, {oldSecurityOrigin});

        if (this._name !== oldName)
            this.dispatchEventToListeners(WI.Frame.Event.NameDidChange, {oldName});
    }

    startProvisionalLoad(provisionalMainResource)
    {
        console.assert(provisionalMainResource);

        this._provisionalMainResource = provisionalMainResource;
        this._provisionalMainResource._parentFrame = this;

        this._provisionalLoaderIdentifier = provisionalMainResource.loaderIdentifier;

        this._provisionalResourceCollection.clear();

        this.dispatchEventToListeners(WI.Frame.Event.ProvisionalLoadStarted);
    }

    commitProvisionalLoad(securityOrigin)
    {
        console.assert(this._provisionalMainResource);
        console.assert(this._provisionalLoaderIdentifier);
        if (!this._provisionalLoaderIdentifier)
            return;

        var oldSecurityOrigin = this._securityOrigin;
        var oldMainResource = this._mainResource;

        this._securityOrigin = securityOrigin || null;
        this._loaderIdentifier = this._provisionalLoaderIdentifier;
        this._mainResource = this._provisionalMainResource;

        this._domContentReadyEventTimestamp = NaN;
        this._loadEventTimestamp = NaN;

        if (oldMainResource && this._mainResource !== oldMainResource)
            this._disassociateWithResource(oldMainResource);

        this.removeAllResources();

        this._resourceCollection = this._provisionalResourceCollection;
        this._provisionalResourceCollection = new WI.ResourceCollection;
        this._extraScriptCollection.clear();

        this.clearExecutionContexts(true);
        this.clearProvisionalLoad(true);
        this.removeAllChildFrames();

        this.dispatchEventToListeners(WI.Frame.Event.ProvisionalLoadCommitted);

        if (this._mainResource !== oldMainResource)
            this._dispatchMainResourceDidChangeEvent(oldMainResource);

        if (this._securityOrigin !== oldSecurityOrigin)
            this.dispatchEventToListeners(WI.Frame.Event.SecurityOriginDidChange, {oldSecurityOrigin});
    }

    clearProvisionalLoad(skipProvisionalLoadClearedEvent)
    {
        if (!this._provisionalLoaderIdentifier)
            return;

        this._provisionalLoaderIdentifier = null;
        this._provisionalMainResource = null;
        this._provisionalResourceCollection.clear();

        if (!skipProvisionalLoadClearedEvent)
            this.dispatchEventToListeners(WI.Frame.Event.ProvisionalLoadCleared);
    }

    get id()
    {
        return this._id;
    }

    get loaderIdentifier()
    {
        return this._loaderIdentifier;
    }

    get provisionalLoaderIdentifier()
    {
        return this._provisionalLoaderIdentifier;
    }

    get name()
    {
        return this._name;
    }

    get securityOrigin()
    {
        return this._securityOrigin;
    }

    get url()
    {
        return this._mainResource.url;
    }

    get urlComponents()
    {
        return this._mainResource.urlComponents;
    }

    get domTree()
    {
        if (!this._domTree)
            this._domTree = new WI.DOMTree(this);
        return this._domTree;
    }

    get pageExecutionContext()
    {
        return this._executionContextList.pageExecutionContext;
    }

    get executionContextList()
    {
        return this._executionContextList;
    }

    clearExecutionContexts(committingProvisionalLoad)
    {
        if (this._executionContextList.contexts.length) {
            let contexts = this._executionContextList.contexts.slice();
            this._executionContextList.clear();
            this.dispatchEventToListeners(WI.Frame.Event.ExecutionContextsCleared, {committingProvisionalLoad: !!committingProvisionalLoad, contexts});
        }
    }

    addExecutionContext(context)
    {
        var changedPageContext = this._executionContextList.add(context);

        if (changedPageContext)
            this.dispatchEventToListeners(WI.Frame.Event.PageExecutionContextChanged);
    }

    get mainResource()
    {
        return this._mainResource;
    }

    get provisionalMainResource()
    {
        return this._provisionalMainResource;
    }

    get parentFrame()
    {
        return this._parentFrame;
    }

    get domContentReadyEventTimestamp()
    {
        return this._domContentReadyEventTimestamp;
    }

    get loadEventTimestamp()
    {
        return this._loadEventTimestamp;
    }

    isMainFrame()
    {
        return this._isMainFrame;
    }

    markAsMainFrame()
    {
        this._isMainFrame = true;
    }

    unmarkAsMainFrame()
    {
        this._isMainFrame = false;
    }

    markDOMContentReadyEvent(timestamp)
    {
        console.assert(isNaN(this._domContentReadyEventTimestamp));

        this._domContentReadyEventTimestamp = timestamp || NaN;
    }

    markLoadEvent(timestamp)
    {
        console.assert(isNaN(this._loadEventTimestamp));

        this._loadEventTimestamp = timestamp || NaN;
    }

    isDetached()
    {
        var frame = this;
        while (frame) {
            if (frame.isMainFrame())
                return false;
            frame = frame.parentFrame;
        }

        return true;
    }

    childFrameForIdentifier(frameId)
    {
        return this._childFrameIdentifierMap.get(frameId) || null;
    }

    addChildFrame(frame)
    {
        console.assert(frame instanceof WI.Frame);
        if (!(frame instanceof WI.Frame))
            return;

        if (frame._parentFrame === this)
            return;

        if (frame._parentFrame)
            frame._parentFrame.removeChildFrame(frame);

        this._childFrameCollection.add(frame);
        this._childFrameIdentifierMap.set(frame._id, frame);

        frame._parentFrame = this;

        this.dispatchEventToListeners(WI.Frame.Event.ChildFrameWasAdded, {childFrame: frame});
    }

    removeChildFrame(frameOrFrameId)
    {
        console.assert(frameOrFrameId);

        let childFrameId = frameOrFrameId;
        if (childFrameId instanceof WI.Frame)
            childFrameId = frameOrFrameId._id;

        // Fetch the frame by id even if we were passed a WI.Frame.
        // We do this incase the WI.Frame is a new object that isn't
        // in _childFrameCollection, but the id is a valid child frame.
        let childFrame = this.childFrameForIdentifier(childFrameId);
        console.assert(childFrame instanceof WI.Frame);
        if (!(childFrame instanceof WI.Frame))
            return;

        console.assert(childFrame.parentFrame === this);

        this._childFrameCollection.remove(childFrame);
        this._childFrameIdentifierMap.delete(childFrame._id);

        childFrame._detachFromParentFrame();

        this.dispatchEventToListeners(WI.Frame.Event.ChildFrameWasRemoved, {childFrame});
    }

    removeAllChildFrames()
    {
        this._detachFromParentFrame();

        for (let childFrame of this._childFrameCollection)
            childFrame.removeAllChildFrames();

        this._childFrameCollection.clear();
        this._childFrameIdentifierMap.clear();

        this.dispatchEventToListeners(WI.Frame.Event.AllChildFramesRemoved);
    }

    resourceForURL(url, recursivelySearchChildFrames)
    {
        var resource = this._resourceCollection.resourceForURL(url);
        if (resource)
            return resource;

        // Check the main resources of the child frames for the requested URL.
        for (let childFrame of this._childFrameCollection) {
            resource = childFrame.mainResource;
            if (resource.url === url)
                return resource;
        }

        if (!recursivelySearchChildFrames)
            return null;

        // Recursively search resources of child frames.
        for (let childFrame of this._childFrameCollection) {
            resource = childFrame.resourceForURL(url, true);
            if (resource)
                return resource;
        }

        return null;
    }

    resourceCollectionForType(type)
    {
        return this._resourceCollection.resourceCollectionForType(type);
    }

    addResource(resource)
    {
        console.assert(resource instanceof WI.Resource);
        if (!(resource instanceof WI.Resource))
            return;

        if (resource.parentFrame === this)
            return;

        if (resource.parentFrame)
            resource.parentFrame.remove(resource);

        this._associateWithResource(resource);

        if (this._isProvisionalResource(resource)) {
            this._provisionalResourceCollection.add(resource);
            this.dispatchEventToListeners(WI.Frame.Event.ProvisionalResourceWasAdded, {resource});
        } else {
            this._resourceCollection.add(resource);
            this.dispatchEventToListeners(WI.Frame.Event.ResourceWasAdded, {resource});
        }
    }

    removeResource(resource)
    {
        // This does not remove provisional resources.

        this._resourceCollection.remove(resource);

        this._disassociateWithResource(resource);

        this.dispatchEventToListeners(WI.Frame.Event.ResourceWasRemoved, {resource});
    }

    removeAllResources()
    {
        // This does not remove provisional resources, use clearProvisionalLoad for that.

        if (!this._resourceCollection.size)
            return;

        for (let resource of this._resourceCollection)
            this._disassociateWithResource(resource);

        this._resourceCollection.clear();

        this.dispatchEventToListeners(WI.Frame.Event.AllResourcesRemoved);
    }

    addExtraScript(script)
    {
        this._extraScriptCollection.add(script);

        this.dispatchEventToListeners(WI.Frame.Event.ExtraScriptAdded, {script});
    }

    saveIdentityToCookie(cookie)
    {
        cookie[WI.Frame.MainResourceURLCookieKey] = this.mainResource.url.hash;
        cookie[WI.Frame.IsMainFrameCookieKey] = this._isMainFrame;
    }

    // Private

    _detachFromParentFrame()
    {
        if (this._domTree) {
            this._domTree.disconnect();
            this._domTree = null;
        }

        this._parentFrame = null;
    }

    _isProvisionalResource(resource)
    {
        return resource.loaderIdentifier && this._provisionalLoaderIdentifier && resource.loaderIdentifier === this._provisionalLoaderIdentifier;
    }

    _associateWithResource(resource)
    {
        console.assert(!resource._parentFrame);
        if (resource._parentFrame)
            return;

        resource._parentFrame = this;
    }

    _disassociateWithResource(resource)
    {
        console.assert(resource.parentFrame === this);
        if (resource.parentFrame !== this)
            return;

        resource._parentFrame = null;
    }

    _dispatchMainResourceDidChangeEvent(oldMainResource)
    {
        this.dispatchEventToListeners(WI.Frame.Event.MainResourceDidChange, {oldMainResource});
    }
};

WI.Frame.Event = {
    NameDidChange: "frame-name-did-change",
    SecurityOriginDidChange: "frame-security-origin-did-change",
    MainResourceDidChange: "frame-main-resource-did-change",
    ProvisionalLoadStarted: "frame-provisional-load-started",
    ProvisionalLoadCommitted: "frame-provisional-load-committed",
    ProvisionalLoadCleared: "frame-provisional-load-cleared",
    ProvisionalResourceWasAdded: "frame-provisional-resource-was-added",
    ResourceWasAdded: "frame-resource-was-added",
    ResourceWasRemoved: "frame-resource-was-removed",
    AllResourcesRemoved: "frame-all-resources-removed",
    ExtraScriptAdded: "frame-extra-script-added",
    ChildFrameWasAdded: "frame-child-frame-was-added",
    ChildFrameWasRemoved: "frame-child-frame-was-removed",
    AllChildFramesRemoved: "frame-all-child-frames-removed",
    PageExecutionContextChanged: "frame-page-execution-context-changed",
    ExecutionContextsCleared: "frame-execution-contexts-cleared"
};

WI.Frame.TypeIdentifier = "Frame";
WI.Frame.MainResourceURLCookieKey = "frame-main-resource-url";
WI.Frame.IsMainFrameCookieKey = "frame-is-main-frame";
