/*
 * Copyright (C) 2013, 2015 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.LayerTreeDetailsSidebarPanel = class LayerTreeDetailsSidebarPanel extends WI.DOMDetailsSidebarPanel
{
    constructor()
    {
        super("layer-tree", WI.UIString("Layers"));

        this._dataGridNodesByLayerId = new Map;

        this.element.classList.add("layer-tree");
    }

    // DetailsSidebarPanel Overrides.

    shown()
    {
        WI.layerTreeManager.addEventListener(WI.LayerTreeManager.Event.LayerTreeDidChange, this._layerTreeDidChange, this);

        console.assert(this.parentSidebar);

        super.shown();
    }

    hidden()
    {
        WI.layerTreeManager.removeEventListener(WI.LayerTreeManager.Event.LayerTreeDidChange, this._layerTreeDidChange, this);

        super.hidden();
    }

    // DOMDetailsSidebarPanel Overrides

    supportsDOMNode(nodeToInspect)
    {
        return WI.layerTreeManager.supported && nodeToInspect.nodeType() === Node.ELEMENT_NODE;
    }

    // Protected

    initialLayout()
    {
        super.initialLayout();

        this._buildLayerInfoSection();
        this._buildDataGridSection();
        this._buildBottomBar();
    }

    layout()
    {
        super.layout();

        if (!this.domNode || this.domNode.destroyed)
            return;

        WI.layerTreeManager.layersForNode(this.domNode, (layers) => {
            let layerForNode = layers[0] && layers[0].nodeId === this.domNode.id && !layers[0].isGeneratedContent ? layers[0] : null;
            let childLayers = layers.slice(layerForNode ? 1 : 0);
            this._unfilteredChildLayers = childLayers;
            this._updateDisplayWithLayers(layerForNode, childLayers);
        });
    }

    sizeDidChange()
    {
        super.sizeDidChange();

        // FIXME: <https://webkit.org/b/152269> Web Inspector: Convert DetailsSection classes to use View
        this._childLayersRow.sizeDidChange();
    }

    // Private

    _layerTreeDidChange(event)
    {
        this.needsLayout();
    }

    _buildLayerInfoSection()
    {
        var rows = this._layerInfoRows = {};
        var rowsArray = [];

        rowsArray.push(rows["Width"] = new WI.DetailsSectionSimpleRow(WI.UIString("Width")));
        rowsArray.push(rows["Height"] = new WI.DetailsSectionSimpleRow(WI.UIString("Height")));
        rowsArray.push(rows["Paints"] = new WI.DetailsSectionSimpleRow(WI.UIString("Paints")));
        rowsArray.push(rows["Memory"] = new WI.DetailsSectionSimpleRow(WI.UIString("Memory")));

        this._layerInfoGroup = new WI.DetailsSectionGroup(rowsArray);

        var emptyRow = new WI.DetailsSectionRow(WI.UIString("No Layer Available"));
        emptyRow.showEmptyMessage();
        this._noLayerInformationGroup = new WI.DetailsSectionGroup([emptyRow]);

        this._layerInfoSection = new WI.DetailsSection("layer-info", WI.UIString("Layer Info"), [this._noLayerInformationGroup]);

        this.contentView.element.appendChild(this._layerInfoSection.element);
    }

    _buildDataGridSection()
    {
        var columns = {name: {}, paintCount: {}, memory: {}};

        columns.name.title = WI.UIString("Node");
        columns.name.sortable = false;

        columns.paintCount.title = WI.UIString("Paints", "Paints @ Column title", "A count of how many times an element was painted (rendered)");
        columns.paintCount.sortable = true;
        columns.paintCount.aligned = "right";
        columns.paintCount.width = "70px";

        columns.memory.title = WI.UIString("Memory");
        columns.memory.sortable = true;
        columns.memory.aligned = "right";
        columns.memory.width = "70px";

        this._dataGrid = new WI.DataGrid(columns);
        this._dataGrid.inline = true;
        this._dataGrid.addEventListener(WI.DataGrid.Event.SortChanged, this._sortDataGrid, this);
        this._dataGrid.addEventListener(WI.DataGrid.Event.SelectedNodeChanged, this._selectedDataGridNodeChanged, this);

        this._dataGrid.sortColumnIdentifier = "memory";
        this._dataGrid.sortOrder = WI.DataGrid.SortOrder.Descending;
        this._dataGrid.createSettings("layer-tree-details-sidebar-panel");

        var element = this._dataGrid.element;
        element.addEventListener("focus", this._dataGridGainedFocus.bind(this), false);
        element.addEventListener("blur", this._dataGridLostFocus.bind(this), false);
        element.addEventListener("click", this._dataGridWasClicked.bind(this), false);

        this._childLayersRow = new WI.DetailsSectionDataGridRow(null, WI.UIString("No Child Layers"));
        var group = new WI.DetailsSectionGroup([this._childLayersRow]);
        var section = new WI.DetailsSection("layer-children", WI.UIString("Child Layers"), [group], null, true);

        this.contentView.element.appendChild(section.element);
    }

    _buildBottomBar()
    {
        var bottomBar = this.element.appendChild(document.createElement("div"));
        bottomBar.className = "bottom-bar";

        this._layersCountLabel = bottomBar.appendChild(document.createElement("div"));
        this._layersCountLabel.className = "layers-count-label";

        this._layersMemoryLabel = bottomBar.appendChild(document.createElement("div"));
        this._layersMemoryLabel.className = "layers-memory-label";
    }

    _sortDataGrid()
    {
        var sortColumnIdentifier = this._dataGrid.sortColumnIdentifier;

        function comparator(a, b)
        {
            var item1 = a.layer[sortColumnIdentifier] || 0;
            var item2 = b.layer[sortColumnIdentifier] || 0;
            return item1 - item2;
        }

        this._dataGrid.sortNodes(comparator);
        this._updatePopoverForSelectedNode();
    }

    _selectedDataGridNodeChanged()
    {
        if (this._dataGrid.selectedNode) {
            this._highlightSelectedNode();
            this._showPopoverForSelectedNode();
        } else {
            WI.domManager.hideDOMNodeHighlight();
            this._hidePopover();
        }
    }

    _dataGridGainedFocus(event)
    {
        this._highlightSelectedNode();
        this._showPopoverForSelectedNode();
    }

    _dataGridLostFocus(event)
    {
        WI.domManager.hideDOMNodeHighlight();
        this._hidePopover();
    }

    _dataGridWasClicked(event)
    {
        if (this._dataGrid.selectedNode && event.target.parentNode.classList.contains("filler"))
            this._dataGrid.selectedNode.deselect();
    }

    _highlightSelectedNode()
    {
        var dataGridNode = this._dataGrid.selectedNode;
        if (!dataGridNode)
            return;

        var layer = dataGridNode.layer;
        if (layer.isGeneratedContent || layer.isReflection || layer.isAnonymous)
            WI.domManager.highlightRect(layer.bounds, true);
        else {
            let domNode = WI.domManager.nodeForId(layer.nodeId);
            if (domNode)
                domNode.highlight();
            else
                WI.domManager.hideDOMNodeHighlight();
        }
    }

    _updateDisplayWithLayers(layerForNode, childLayers)
    {
        this._updateLayerInfoSection(layerForNode);
        this._updateDataGrid(layerForNode, childLayers);
        this._updateMetrics(layerForNode, childLayers);

        this._layerForNode = layerForNode;
        this._childLayers = childLayers;
    }

    _updateLayerInfoSection(layer)
    {
        this._layerInfoSection.groups = layer ? [this._layerInfoGroup] : [this._noLayerInformationGroup];

        if (!layer)
            return;

        this._layerInfoRows["Memory"].value = Number.bytesToString(layer.memory);
        this._layerInfoRows["Width"].value = layer.compositedBounds.width + "px";
        this._layerInfoRows["Height"].value = layer.compositedBounds.height + "px";
        this._layerInfoRows["Paints"].value = layer.paintCount + "";
    }

    _updateDataGrid(layerForNode, childLayers)
    {
        let dataGrid = this._dataGrid;
        let mutations = WI.layerTreeManager.layerTreeMutations(this._childLayers, childLayers);

        mutations.removals.forEach(function(layer) {
            let node = this._dataGridNodesByLayerId.get(layer.layerId);
            if (node) {
                dataGrid.removeChild(node);
                this._dataGridNodesByLayerId.delete(layer.layerId);
            }
        }, this);

        mutations.additions.forEach(function(layer) {
            let node = this._dataGridNodeForLayer(layer);
            if (node)
                dataGrid.appendChild(node);
        }, this);

        mutations.preserved.forEach(function(layer) {
            let node = this._dataGridNodesByLayerId.get(layer.layerId);
            if (node)
                node.layer = layer;
        }, this);

        this._sortDataGrid();

        this._childLayersRow.dataGrid = !isEmptyObject(childLayers) ? this._dataGrid : null;
    }

    _dataGridNodeForLayer(layer)
    {
        let node = new WI.LayerTreeDataGridNode(layer);
        this._dataGridNodesByLayerId.set(layer.layerId, node);

        return node;
    }

    _updateMetrics(layerForNode, childLayers)
    {
        var layerCount = 0;
        var totalMemory = 0;

        if (layerForNode) {
            layerCount++;
            totalMemory += layerForNode.memory || 0;
        }

        childLayers.forEach(function(layer) {
            layerCount++;
            totalMemory += layer.memory || 0;
        });

        this._layersCountLabel.textContent = WI.UIString("Layer Count: %d").format(layerCount);
        this._layersMemoryLabel.textContent = WI.UIString("Memory: %s").format(Number.bytesToString(totalMemory));
    }

    _showPopoverForSelectedNode()
    {
        var dataGridNode = this._dataGrid.selectedNode;
        if (!dataGridNode)
            return;

        this._contentForPopover(dataGridNode.layer, (content) => {
            if (dataGridNode === this._dataGrid.selectedNode)
                this._updatePopoverForSelectedNode(content);
        });
    }

    _updatePopoverForSelectedNode(content)
    {
        var dataGridNode = this._dataGrid.selectedNode;
        if (!dataGridNode)
            return;

        var popover = this._popover;
        if (!popover) {
            popover = this._popover = new WI.Popover;
            popover.windowResizeHandler = () => { this._updatePopoverForSelectedNode(); };
        }

        var targetFrame = WI.Rect.rectFromClientRect(dataGridNode.element.getBoundingClientRect());

        if (content)
            this._popover.presentNewContentWithFrame(content, targetFrame.pad(2), [WI.RectEdge.MIN_X]);
        else
            popover.present(targetFrame.pad(2), [WI.RectEdge.MIN_X]);
    }

    _hidePopover()
    {
        if (this._popover)
            this._popover.dismiss();
    }

    _contentForPopover(layer, callback)
    {
        var content = document.createElement("div");
        content.className = "layer-tree-popover";

        content.appendChild(document.createElement("p")).textContent = WI.UIString("Reasons for compositing:");

        var list = content.appendChild(document.createElement("ul"));

        WI.layerTreeManager.reasonsForCompositingLayer(layer, (compositingReasons) => {
            if (isEmptyObject(compositingReasons)) {
                callback(content);
                return;
            }

            this._populateListOfCompositingReasons(list, compositingReasons);

            callback(content);
        });

        return content;
    }

    _populateListOfCompositingReasons(list, compositingReasons)
    {
        function addReason(reason)
        {
            list.appendChild(document.createElement("li")).textContent = reason;
        }

        if (compositingReasons.transform3D)
            addReason(WI.UIString("Element has a 3D transform"));
        if (compositingReasons.video)
            addReason(WI.UIString("Element is <video>"));
        if (compositingReasons.canvas)
            addReason(WI.UIString("Element is <canvas>"));
        if (compositingReasons.plugin)
            addReason(WI.UIString("Element is a plug-in"));
        if (compositingReasons.iFrame)
            addReason(WI.UIString("Element is <iframe>"));
        if (compositingReasons.backfaceVisibilityHidden)
            addReason(WI.UIString("Element has \u201Cbackface-visibility: hidden\u201D style"));
        if (compositingReasons.clipsCompositingDescendants)
            addReason(WI.UIString("Element clips compositing descendants"));
        if (compositingReasons.animation)
            addReason(WI.UIString("Element is animated"));
        if (compositingReasons.filters)
            addReason(WI.UIString("Element has CSS filters applied"));
        if (compositingReasons.positionFixed)
            addReason(WI.UIString("Element has \u201Cposition: fixed\u201D style"));
        if (compositingReasons.positionSticky)
            addReason(WI.UIString("Element has \u201Cposition: sticky\u201D style"));
        if (compositingReasons.overflowScrollingTouch)
            addReason(WI.UIString("Element has \u201C-webkit-overflow-scrolling: touch\u201D style"));
        if (compositingReasons.stacking)
            addReason(WI.UIString("Element may overlap another compositing element"));
        if (compositingReasons.overlap)
            addReason(WI.UIString("Element overlaps other compositing element"));
        if (compositingReasons.negativeZIndexChildren)
            addReason(WI.UIString("Element has children with a negative z-index"));
        if (compositingReasons.transformWithCompositedDescendants)
            addReason(WI.UIString("Element has a 2D transform and composited descendants"));
        if (compositingReasons.opacityWithCompositedDescendants)
            addReason(WI.UIString("Element has opacity applied and composited descendants"));
        if (compositingReasons.maskWithCompositedDescendants)
            addReason(WI.UIString("Element is masked and has composited descendants"));
        if (compositingReasons.reflectionWithCompositedDescendants)
            addReason(WI.UIString("Element has a reflection and composited descendants"));
        if (compositingReasons.filterWithCompositedDescendants)
            addReason(WI.UIString("Element has CSS filters applied and composited descendants"));
        if (compositingReasons.blendingWithCompositedDescendants)
            addReason(WI.UIString("Element has CSS blending applied and composited descendants"));
        if (compositingReasons.isolatesCompositedBlendingDescendants)
            addReason(WI.UIString("Element is a stacking context and has composited descendants with CSS blending applied"));
        if (compositingReasons.perspective)
            addReason(WI.UIString("Element has perspective applied"));
        if (compositingReasons.preserve3D)
            addReason(WI.UIString("Element has \u201Ctransform-style: preserve-3d\u201D style"));
        if (compositingReasons.willChange)
            addReason(WI.UIString("Element has \u201Cwill-change\u201D style which includes opacity, transform, transform-style, perspective, filter or backdrop-filter"));
        if (compositingReasons.root)
            addReason(WI.UIString("Element is the root element"));
        if (compositingReasons.blending)
            addReason(WI.UIString("Element has \u201Cblend-mode\u201D style"));
    }
};
