/*
 * Copyright (C) IBM Corp. 2009  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 IBM Corp. 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.WatchExpressionsSidebarPane = function()
{
    WebInspector.SidebarPane.call(this, WebInspector.UIString("Watch Expressions"));
    WebInspector.settings.addEventListener("loaded", this._settingsLoaded, this);
}

WebInspector.WatchExpressionsSidebarPane.prototype = {
    _settingsLoaded: function()
    {
        this.bodyElement.removeChildren();

        this.expanded = WebInspector.settings.watchExpressions.length > 0;
        this.section = new WebInspector.WatchExpressionsSection();
        this.bodyElement.appendChild(this.section.element);

        var addElement = document.createElement("button");
        addElement.setAttribute("type", "button");
        addElement.textContent = WebInspector.UIString("Add");
        addElement.addEventListener("click", this.section.addExpression.bind(this.section), false);

        var refreshElement = document.createElement("button");
        refreshElement.setAttribute("type", "button");
        refreshElement.textContent = WebInspector.UIString("Refresh");
        refreshElement.addEventListener("click", this.section.update.bind(this.section), false);

        var centerElement = document.createElement("div");
        centerElement.addStyleClass("watch-expressions-buttons-container");
        centerElement.appendChild(addElement);
        centerElement.appendChild(refreshElement);
        this.bodyElement.appendChild(centerElement);

        this.onexpand = this.refreshExpressions.bind(this);
    },

    refreshExpressions: function()
    {
        if (this.section)
            this.section.update();
    }
}

WebInspector.WatchExpressionsSidebarPane.prototype.__proto__ = WebInspector.SidebarPane.prototype;

WebInspector.WatchExpressionsSection = function()
{
    this._watchObjectGroupId = "watch-group";

    WebInspector.ObjectPropertiesSection.call(this);

    this.watchExpressions = WebInspector.settings.watchExpressions;

    this.headerElement.className = "hidden";
    this.editable = true;
    this.expanded = true;
    this.propertiesElement.addStyleClass("watch-expressions");
}

WebInspector.WatchExpressionsSection.NewWatchExpression = "\xA0";

WebInspector.WatchExpressionsSection.prototype = {
    update: function()
    {
        function appendResult(expression, watchIndex, result, exception)
        {
            if (exception) {
                // Exception results are not wrappers, but text messages.
                result = WebInspector.ObjectProxy.wrapPrimitiveValue(result);
            } else if (result.type === "string") {
                // Evaluation result is intentionally not abbreviated. However, we'd like to distinguish between null and "null"
                result.description = "\"" + result.description + "\"";
            }

            var property = new WebInspector.ObjectPropertyProxy(expression, result);
            property.watchIndex = watchIndex;
            property.isException = exception;

            // For newly added, empty expressions, set description to "",
            // since otherwise you get DOMWindow
            if (property.name === WebInspector.WatchExpressionsSection.NewWatchExpression) 
                property.value.description = "";

            // To clarify what's going on here: 
            // In the outer function, we calculate the number of properties
            // that we're going to be updating, and set that in the
            // propertyCount variable.  
            // In this function, we test to see when we are processing the 
            // last property, and then call the superclass's updateProperties() 
            // method to get all the properties refreshed at once.
            properties.push(property);
            
            if (properties.length == propertyCount) {
                this.updateProperties(properties, WebInspector.WatchExpressionTreeElement, WebInspector.WatchExpressionsSection.CompareProperties);

                // check to see if we just added a new watch expression,
                // which will always be the last property
                if (this._newExpressionAdded) {
                    delete this._newExpressionAdded;

                    treeElement = this.findAddedTreeElement();
                    if (treeElement)
                        treeElement.startEditing();
                }
            }
        }

        // TODO: pass exact injected script id.
        InspectorBackend.releaseWrapperObjectGroup(0, this._watchObjectGroupId)
        var properties = [];

        // Count the properties, so we known when to call this.updateProperties()
        // in appendResult()
        var propertyCount = 0;
        for (var i = 0; i < this.watchExpressions.length; ++i) {
            if (!this.watchExpressions[i]) 
                continue;
            ++propertyCount;
        }

        // Now process all the expressions, since we have the actual count,
        // which is checked in the appendResult inner function.
        for (var i = 0; i < this.watchExpressions.length; ++i) {
            var expression = this.watchExpressions[i];
            if (!expression)
                continue;

            WebInspector.console.evalInInspectedWindow("(" + expression + ")", this._watchObjectGroupId, appendResult.bind(this, expression, i));
        }

        // note this is setting the expansion of the tree, not the section;
        // with no expressions, and expanded tree, we get some extra vertical
        // white space
        // FIXME: should change to use header buttons instead of the buttons
        // at the bottom of the section, then we can add a "No Watch Expressions
        // element when there are no watch expressions, and this issue should
        // go away.
        this.expanded = (propertyCount != 0);
    },

    addExpression: function()
    {
        this._newExpressionAdded = true;
        this.watchExpressions.push(WebInspector.WatchExpressionsSection.NewWatchExpression);
        this.update();
    },

    updateExpression: function(element, value)
    {
        this.watchExpressions[element.property.watchIndex] = value;
        this.saveExpressions();
        this.update();
    },

    findAddedTreeElement: function()
    {
        var children = this.propertiesTreeOutline.children;
        for (var i = 0; i < children.length; ++i)
            if (children[i].property.name === WebInspector.WatchExpressionsSection.NewWatchExpression)
                return children[i];
    },

    saveExpressions: function()
    {
        var toSave = [];
        for (var i = 0; i < this.watchExpressions.length; i++)
            if (this.watchExpressions[i])
                toSave.push(this.watchExpressions[i]);

        WebInspector.settings.watchExpressions = toSave;
        return toSave.length;
    }
}

WebInspector.WatchExpressionsSection.prototype.__proto__ = WebInspector.ObjectPropertiesSection.prototype;

WebInspector.WatchExpressionsSection.CompareProperties = function(propertyA, propertyB) 
{
    if (propertyA.watchIndex == propertyB.watchIndex)
        return 0;
    else if (propertyA.watchIndex < propertyB.watchIndex)
        return -1;
    else
        return 1;
}

WebInspector.WatchExpressionTreeElement = function(property)
{
    WebInspector.ObjectPropertyTreeElement.call(this, property);
}

WebInspector.WatchExpressionTreeElement.prototype = {
    update: function()
    {
        WebInspector.ObjectPropertyTreeElement.prototype.update.call(this);

        if (this.property.isException)
            this.valueElement.addStyleClass("watch-expressions-error-level");

        var deleteButton = document.createElement("input");
        deleteButton.type = "button";
        deleteButton.title = WebInspector.UIString("Delete watch expression.");
        deleteButton.addStyleClass("enabled-button");
        deleteButton.addStyleClass("delete-button");
        deleteButton.addEventListener("click", this._deleteButtonClicked.bind(this), false);

        this.listItemElement.insertBefore(deleteButton, this.listItemElement.firstChild);
    },

    _deleteButtonClicked: function()
    {
        this.treeOutline.section.updateExpression(this, null);
    },

    startEditing: function()
    {
        if (WebInspector.isBeingEdited(this.nameElement) || !this.treeOutline.section.editable)
            return;

        this.nameElement.textContent = this.property.name.trim();

        var context = { expanded: this.expanded };

        // collapse temporarily, if required
        this.hasChildren = false;

        this.listItemElement.addStyleClass("editing-sub-part");

        WebInspector.startEditing(this.nameElement, this.editingCommitted.bind(this), this.editingCancelled.bind(this), context);
    },

    editingCancelled: function(element, context)
    {
        if (!this.nameElement.textContent)
            this.treeOutline.section.updateExpression(this, null);
            
        this.update();
        this.editingEnded(context);
    },

    applyExpression: function(expression, updateInterface)
    {
        expression = expression.trim();

        if (!expression)
            expression = null;

        this.property.name = expression;
        this.treeOutline.section.updateExpression(this, expression);
    }
}

WebInspector.WatchExpressionTreeElement.prototype.__proto__ = WebInspector.ObjectPropertyTreeElement.prototype;
