/*
 * Copyright (C) 2012 Adobe Systems Incorporated. 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 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 HOLDER 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.
 */

/**
 * @constructor
 * @extends {WebInspector.View}
 * @param {WebInspector.NamedFlow} flow
 */
WebInspector.CSSNamedFlowView = function(flow)
{
    WebInspector.View.call(this);
    this.element.addStyleClass("css-named-flow");
    this.element.addStyleClass("outline-disclosure");

    this._treeOutline = new TreeOutline(this.element.createChild("ol"), true);

    this._contentTreeItem = new TreeElement(WebInspector.UIString("content"), null, true);
    this._treeOutline.appendChild(this._contentTreeItem);

    this._regionsTreeItem = new TreeElement(WebInspector.UIString("region chain"), null, true);
    this._regionsTreeItem.expand();
    this._treeOutline.appendChild(this._regionsTreeItem);

    this._flow = flow;

    var content = flow.content;
    for (var i = 0; i < content.length; ++i)
        this._insertContentNode(content[i]);

    var regions = flow.regions;
    for (var i = 0; i < regions.length; ++i)
        this._insertRegion(regions[i]);
}

WebInspector.CSSNamedFlowView.OversetTypeMessageMap = {
    empty: "empty",
    fit: "fit",
    overset: "overset"
}

WebInspector.CSSNamedFlowView.prototype = {
    /**
     * @param {WebInspector.DOMNode=} rootDOMNode
     * @return {?WebInspector.ElementsTreeOutline}
     */
    _createFlowTreeOutline: function(rootDOMNode)
    {
        if (!rootDOMNode)
            return null;

        var treeOutline = new WebInspector.ElementsTreeOutline(false, false);
        treeOutline.element.addStyleClass("named-flow-element");
        treeOutline.setVisible(true);
        treeOutline.rootDOMNode = rootDOMNode;
        treeOutline.wireToDomAgent();
        WebInspector.domAgent.removeEventListener(WebInspector.DOMAgent.Events.DocumentUpdated, treeOutline._elementsTreeUpdater._documentUpdated, treeOutline._elementsTreeUpdater);

        return treeOutline;
    },

    /**
     * @param {DOMAgent.NodeId} contentNodeId
     * @param {number=} index
     */
    _insertContentNode: function(contentNodeId, index)
    {
        var treeOutline = this._createFlowTreeOutline(WebInspector.domAgent.nodeForId(contentNodeId));
        var treeItem = new TreeElement(treeOutline.element, treeOutline);

        if (index === undefined) {
            this._contentTreeItem.appendChild(treeItem);
            return;
        }

        this._contentTreeItem.insertChild(treeItem, index);
    },

    /**
     * @param {CSSAgent.Region} region
     * @param {number=} index
     */
    _insertRegion: function(region, index)
    {
        var treeOutline = this._createFlowTreeOutline(WebInspector.domAgent.nodeForId(region.nodeId));
        treeOutline.element.addStyleClass("region-" + region.regionOverset);

        var treeItem = new TreeElement(treeOutline.element, treeOutline);
        var oversetText = WebInspector.UIString(WebInspector.CSSNamedFlowView.OversetTypeMessageMap[region.regionOverset]);
        treeItem.tooltip = WebInspector.UIString("Region is %s.", oversetText);

        if (index === undefined) {
            this._regionsTreeItem.appendChild(treeItem);
            return;
        }

        this._regionsTreeItem.insertChild(treeItem, index);
    },

    get flow()
    {
        return this._flow;
    },

    set flow(newFlow)
    {
        this._update(newFlow);
    },

    /**
     * @param {TreeElement} regionTreeItem
     * @param {string} newRegionOverset
     * @param {string} oldRegionOverset
     */
    _updateRegionOverset: function(regionTreeItem, newRegionOverset, oldRegionOverset)
    {
        var element = regionTreeItem.representedObject.element;
        element.removeStyleClass("region-" + oldRegionOverset);
        element.addStyleClass("region-" + newRegionOverset);

        var oversetText = WebInspector.UIString(WebInspector.CSSNamedFlowView.OversetTypeMessageMap[newRegionOverset]);
        regionTreeItem.tooltip = WebInspector.UIString("Region is %s." , oversetText);
    },

    /**
     * @param {Array.<DOMAgent.NodeId>} oldContent
     * @param {Array.<DOMAgent.NodeId>} newContent
     */
    _mergeContentNodes: function(oldContent, newContent)
    {
        var nodeIdSet = {};
        for (var i = 0; i < newContent.length; ++i)
            nodeIdSet[newContent[i]] = true;

        var oldContentIndex = 0;
        var newContentIndex = 0;
        var contentTreeChildIndex = 0;

        while(oldContentIndex < oldContent.length || newContentIndex < newContent.length) {
            if (oldContentIndex === oldContent.length) {
                this._insertContentNode(newContent[newContentIndex]);
                ++newContentIndex;
                continue;
            }

            if (newContentIndex === newContent.length) {
                this._contentTreeItem.removeChildAtIndex(contentTreeChildIndex);
                ++oldContentIndex;
                continue;
            }

            if (oldContent[oldContentIndex] === newContent[newContentIndex]) {
                ++oldContentIndex;
                ++newContentIndex;
                ++contentTreeChildIndex;
                continue;
            }

            if (nodeIdSet[oldContent[oldContentIndex]]) {
                this._insertContentNode(newContent[newContentIndex], contentTreeChildIndex);
                ++newContentIndex;
                ++contentTreeChildIndex;
                continue;
            }

            this._contentTreeItem.removeChildAtIndex(contentTreeChildIndex);
            ++oldContentIndex;
        }
    },

    /**
     * @param {Array.<CSSAgent.Region>} oldRegions
     * @param {Array.<CSSAgent.Region>} newRegions
     */
    _mergeRegions: function(oldRegions, newRegions)
    {
        var nodeIdSet = {};
        for (var i = 0; i < newRegions.length; ++i)
            nodeIdSet[newRegions[i].nodeId] = true;

        var oldRegionsIndex = 0;
        var newRegionsIndex = 0;
        var regionsTreeChildIndex = 0;

        while(oldRegionsIndex < oldRegions.length || newRegionsIndex < newRegions.length) {
            if (oldRegionsIndex === oldRegions.length) {
                this._insertRegion(newRegions[newRegionsIndex]);
                ++newRegionsIndex;
                continue;
            }

            if (newRegionsIndex === newRegions.length) {
                this._regionsTreeItem.removeChildAtIndex(regionsTreeChildIndex);
                ++oldRegionsIndex;
                continue;
            }

            if (oldRegions[oldRegionsIndex].nodeId === newRegions[newRegionsIndex].nodeId) {
                if (oldRegions[oldRegionsIndex].regionOverset !== newRegions[newRegionsIndex].regionOverset)
                    this._updateRegionOverset(this._regionsTreeItem.children[regionsTreeChildIndex], newRegions[newRegionsIndex].regionOverset, oldRegions[oldRegionsIndex].regionOverset);
                ++oldRegionsIndex;
                ++newRegionsIndex;
                ++regionsTreeChildIndex;
                continue;
            }

            if (nodeIdSet[oldRegions[oldRegionsIndex].nodeId]) {
                this._insertRegion(newRegions[newRegionsIndex], regionsTreeChildIndex);
                ++newRegionsIndex;
                ++regionsTreeChildIndex;
                continue;
            }

            this._regionsTreeItem.removeChildAtIndex(regionsTreeChildIndex);
            ++oldRegionsIndex;
        }
    },

    /**
     * @param {WebInspector.NamedFlow} newFlow
     */
    _update: function(newFlow)
    {
        this._mergeContentNodes(this._flow.content, newFlow.content);
        this._mergeRegions(this._flow.regions, newFlow.regions);

        this._flow = newFlow;
    },

    __proto__: WebInspector.View.prototype
}
