/*
 * Copyright (C) 2011 Google 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:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * 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.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
 * OWNER OR 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.
 */

WebInspector.DOMBreakpointsSidebarPane = function()
{
    WebInspector.NativeBreakpointsSidebarPane.call(this, WebInspector.UIString("DOM Breakpoints"));

    this._breakpointElements = {};

    this._breakpointTypes = {
        SubtreeModified: 0,
        AttributeModified: 1,
        NodeRemoved: 2
    };
    this._breakpointTypeLabels = [
        WebInspector.UIString("Subtree Modified"),
        WebInspector.UIString("Attribute Modified"),
        WebInspector.UIString("Node Removed")
    ];
    this._contextMenuLabels = [
        WebInspector.UIString("Break on Subtree Modifications"),
        WebInspector.UIString("Break on Attributes Modifications"),
        WebInspector.UIString("Break on Node Removal")
    ];
}

WebInspector.DOMBreakpointsSidebarPane.prototype = {
    setInspectedURL: function(url)
    {
        this._reset();
        this._inspectedURL = url.removeURLFragment();
    },

    populateNodeContextMenu: function(node, contextMenu)
    {
        var nodeBreakpoints = {};
        for (var id in this._breakpointElements) {
            var element = this._breakpointElements[id];
            if (element._node === node)
                nodeBreakpoints[element._type] = true;
        }

        function toggleBreakpoint(type)
        {
            if (!nodeBreakpoints[type])
                this._setBreakpoint(node, type, true);
            else
                this._removeBreakpoint(node, type);
            this._saveBreakpoints();
        }

        for (var type = 0; type < 3; ++type) {
            var label = this._contextMenuLabels[type];
            contextMenu.appendCheckboxItem(label, toggleBreakpoint.bind(this, type), nodeBreakpoints[type]);
        }
    },

    createBreakpointHitStatusMessage: function(eventData, callback)
    {
        if (eventData.type === this._breakpointTypes.SubtreeModified) {
            var targetNodeObject = WebInspector.RemoteObject.fromPayload(eventData.targetNode);
            function didPushNodeToFrontend(targetNodeId)
            {
                if (targetNodeId)
                    targetNodeObject.release();
                this._doCreateBreakpointHitStatusMessage(eventData, targetNodeId, callback);
            }
            targetNodeObject.pushNodeToFrontend(didPushNodeToFrontend.bind(this));
        } else
            this._doCreateBreakpointHitStatusMessage(eventData, null, callback);
    },

    _doCreateBreakpointHitStatusMessage: function (eventData, targetNodeId, callback)
    {
        var message;
        var typeLabel = this._breakpointTypeLabels[eventData.type];
        var linkifiedNode = WebInspector.panels.elements.linkifyNodeById(eventData.nodeId);
        var substitutions = [typeLabel, linkifiedNode];
        var targetNode = "";
        if (targetNodeId)
            targetNode = WebInspector.panels.elements.linkifyNodeById(targetNodeId);

        if (eventData.type === this._breakpointTypes.SubtreeModified) {
            if (eventData.insertion) {
                if (targetNodeId !== eventData.nodeId) {
                    message = "Paused on a \"%s\" breakpoint set on %s, because a new child was added to its descendant %s.";
                    substitutions.push(targetNode);
                } else
                    message = "Paused on a \"%s\" breakpoint set on %s, because a new child was added to that node.";
            } else {
                message = "Paused on a \"%s\" breakpoint set on %s, because its descendant %s was removed.";
                substitutions.push(targetNode);
            }
        } else
            message = "Paused on a \"%s\" breakpoint set on %s.";

        var element = document.createElement("span");
        var formatters = {
            s: function(substitution)
            {
                return substitution;
            }
        };
        function append(a, b)
        {
            if (typeof b === "string")
                b = document.createTextNode(b);
            element.appendChild(b);
        }
        WebInspector.formatLocalized(message, substitutions, formatters, "", append);

        callback(element);
    },

    nodeRemoved: function(node)
    {
        this._removeBreakpointsForNode(node);
        if (!node.children)
            return;
        for (var i = 0; i < node.children.length; ++i)
            this._removeBreakpointsForNode(node.children[i]);
        this._saveBreakpoints();
    },

    _removeBreakpointsForNode: function(node)
    {
        for (var id in this._breakpointElements) {
            var element = this._breakpointElements[id];
            if (element._node === node)
                this._removeBreakpoint(element._node, element._type);
        }
    },

    _setBreakpoint: function(node, type, enabled)
    {
        var breakpointId = this._createBreakpointId(node.id, type);
        if (breakpointId in this._breakpointElements)
            return;

        var element = document.createElement("li");
        element._node = node;
        element._type = type;
        element.addEventListener("contextmenu", this._contextMenu.bind(this, node, type), true);

        var checkboxElement = document.createElement("input");
        checkboxElement.className = "checkbox-elem";
        checkboxElement.type = "checkbox";
        checkboxElement.checked = enabled;
        checkboxElement.addEventListener("click", this._checkboxClicked.bind(this, node, type), false);
        element._checkboxElement = checkboxElement;
        element.appendChild(checkboxElement);

        var labelElement = document.createElement("span");
        element.appendChild(labelElement);

        var linkifiedNode = WebInspector.panels.elements.linkifyNodeById(node.id);
        linkifiedNode.addStyleClass("monospace");
        labelElement.appendChild(linkifiedNode);

        var description = document.createElement("div");
        description.className = "source-text";
        description.textContent = this._breakpointTypeLabels[type];
        labelElement.appendChild(description);

        var currentElement = this.listElement.firstChild;
        while (currentElement) {
            if (currentElement._type && currentElement._type < element._type)
                break;
            currentElement = currentElement.nextSibling;
        }
        this._addListElement(element, currentElement);
        this._breakpointElements[breakpointId] = element;
        if (enabled)
            BrowserDebuggerAgent.setDOMBreakpoint(node.id, type);
    },

    _removeBreakpoint: function(node, type)
    {
        var breakpointId = this._createBreakpointId(node.id, type);
        var element = this._breakpointElements[breakpointId];
        if (!element)
            return;

        this._removeListElement(element);
        delete this._breakpointElements[breakpointId];
        if (element._checkboxElement.checked)
            BrowserDebuggerAgent.removeDOMBreakpoint(node.id, type);
    },

    _contextMenu: function(node, type, event)
    {
        var contextMenu = new WebInspector.ContextMenu();
        function removeBreakpoint()
        {
            this._removeBreakpoint(node, type);
            this._saveBreakpoints();
        }
        contextMenu.appendItem(WebInspector.UIString("Remove Breakpoint"), removeBreakpoint.bind(this));
        contextMenu.show(event);
    },

    _checkboxClicked: function(node, type, event)
    {
        if (event.target.checked)
            BrowserDebuggerAgent.setDOMBreakpoint(node.id, type);
        else
            BrowserDebuggerAgent.removeDOMBreakpoint(node.id, type);
        this._saveBreakpoints();
    },

    highlightBreakpoint: function(eventData)
    {
        var breakpointId = this._createBreakpointId(eventData.nodeId, eventData.type);
        var element = this._breakpointElements[breakpointId];
        if (!element)
            return;
        this.expanded = true;
        element.addStyleClass("breakpoint-hit");
        this._highlightedElement = element;
    },

    clearBreakpointHighlight: function()
    {
        if (this._highlightedElement) {
            this._highlightedElement.removeStyleClass("breakpoint-hit");
            delete this._highlightedElement;
        }
    },

    _createBreakpointId: function(nodeId, type)
    {
        return nodeId + ":" + type;
    },

    _saveBreakpoints: function()
    {
        var breakpoints = [];
        var storedBreakpoints = WebInspector.settings.domBreakpoints;
        for (var i = 0; i < storedBreakpoints.length; ++i) {
            var breakpoint = storedBreakpoints[i];
            if (breakpoint.url !== this._inspectedURL)
                breakpoints.push(breakpoint);
        }
        for (var id in this._breakpointElements) {
            var element = this._breakpointElements[id];
            breakpoints.push({ url: this._inspectedURL, path: element._node.path(), type: element._type, enabled: element._checkboxElement.checked });
        }
        WebInspector.settings.domBreakpoints = breakpoints;
    },

    restoreBreakpoints: function()
    {
        var pathToBreakpoints = {};

        function didPushNodeByPathToFrontend(path, nodeId)
        {
            var node = WebInspector.domAgent.nodeForId(nodeId);
            if (!node)
                return;

            var breakpoints = pathToBreakpoints[path];
            for (var i = 0; i < breakpoints.length; ++i)
                this._setBreakpoint(node, breakpoints[i].type, breakpoints[i].enabled);
        }

        var breakpoints = WebInspector.settings.domBreakpoints;
        for (var i = 0; i < breakpoints.length; ++i) {
            var breakpoint = breakpoints[i];
            if (breakpoint.url !== this._inspectedURL)
                continue;
            var path = breakpoint.path;
            if (!pathToBreakpoints[path]) {
                pathToBreakpoints[path] = [];
                WebInspector.domAgent.pushNodeByPathToFrontend(path, didPushNodeByPathToFrontend.bind(this, path));
            }
            pathToBreakpoints[path].push(breakpoint);
        }
    }
}

WebInspector.DOMBreakpointsSidebarPane.prototype.__proto__ = WebInspector.NativeBreakpointsSidebarPane.prototype;
