/*
 * Copyright (C) 2013, 2015 Apple Inc. All rights reserved.
 * Copyright (C) 2017 Sony Interactive Entertainment Inc.
 *
 * 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.LayerDetailsSidebarPanel = class LayerDetailsSidebarPanel extends WI.DetailsSidebarPanel
{
    constructor()
    {
        super("layer", WI.UIString("All Layers"));

        this.element.classList.add("layer");

        this._layers = [];
        this._layerIdToSelect = null;

        this._dataGrid = null;
        this._hoveredDataGridNode = null;
        this._dataGridNodesByLayerId = new Map;

        this._bottomBar = null;
        this._layersCountLabel = null;
        this._layersMemoryLabel = null;
    }

    // Public

    inspect(objects)
    {
        if (!(objects instanceof Array))
            objects = [objects];

        let layers = objects.filter((object) => object instanceof WI.Layer);
        this._updateLayers(layers);

        return !!layers.length;
    }

    selectNodeByLayerId(layerId)
    {
        this._layerIdToSelect = null;

        let node = this._dataGridNodesByLayerId.get(layerId);
        if (node === this._dataGrid.selectedNode)
            return;

        const suppressEvent = true;
        if (node)
            node.revealAndSelect(suppressEvent);
        else if (this._dataGrid.selectedNode)
            this._dataGrid.selectedNode.deselect(suppressEvent);
        else
            this._layerIdToSelect = layerId;
    }

    // Private

    _buildDataGrid()
    {
        const columns = {
            name: {
                title: WI.UIString("Node"),
                sortable: false,
            },
            paintCount: {
                title: WI.UIString("Paints"),
                sortable: true,
                aligned: "right",
                width: "70px",
            },
            memory: {
                title: WI.UIString("Memory"),
                sortable: true,
                aligned: "right",
                width: "70px",
            }
        };

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

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

        this._dataGrid.element.addEventListener("mousemove", this._dataGridMouseMove.bind(this));
        this._dataGrid.element.addEventListener("mouseleave", this._dataGridMouseLeave.bind(this));

        // FIXME: We can't use virtualized rows until DataGrid is able to scroll them programmatically.
        //        See TreeElement#reveal -> TreeOutline#updateVirtualizedElements for an analogy.
        this._dataGrid.inline = true;
        this._dataGrid.element.classList.remove("inline");

        this.contentView.addSubview(this._dataGrid);
    }

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

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

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

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

        function comparator(a, b) {
            let itemA = a.layer[sortColumnIdentifier] || 0;
            let itemB = b.layer[sortColumnIdentifier] || 0;
            return itemA - itemB;
        }

        this._dataGrid.sortNodes(comparator);
    }

    _dataGridSelectedNodeChanged()
    {
        let layerId = this._dataGrid.selectedNode ? this._dataGrid.selectedNode.layer.layerId : null;
        this.dispatchEventToListeners(WI.LayerDetailsSidebarPanel.Event.SelectedLayerChanged, {layerId});
    }

    _dataGridMouseMove(event)
    {
        let dataGridNode = this._dataGrid.dataGridNodeFromNode(event.target);
        if (dataGridNode === this._hoveredDataGridNode)
            return;

        if (!dataGridNode) {
            this._hideDOMNodeHighlight();
            return;
        }

        this._hoveredDataGridNode = dataGridNode;

        let layer = dataGridNode.layer;

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

    _dataGridMouseLeave(event)
    {
        this._hideDOMNodeHighlight();
    }

    _hideDOMNodeHighlight()
    {
        WI.domManager.hideDOMNodeHighlight();
        this._hoveredDataGridNode = null;
    }

    _updateLayers(newLayers)
    {
        this._updateDataGrid(newLayers);
        this._updateBottomBar(newLayers);

        this._layers = newLayers;
    }

    _updateDataGrid(newLayers)
    {
        if (!this._dataGrid)
            this._buildDataGrid();

        let {removals, additions, preserved} = WI.layerTreeManager.layerTreeMutations(this._layers, newLayers);

        removals.forEach((layer) => {
            let node = this._dataGridNodesByLayerId.get(layer.layerId);
            this._dataGrid.removeChild(node);
            this._dataGridNodesByLayerId.delete(layer.layerId);
        });

        additions.forEach((layer) => {
            let node = new WI.LayerTreeDataGridNode(layer);
            this._dataGridNodesByLayerId.set(layer.layerId, node);
            this._dataGrid.appendChild(node);
        });

        preserved.forEach((layer) => {
            let node = this._dataGridNodesByLayerId.get(layer.layerId);
            node.layer = layer;
        });

        this._sortDataGrid();

        if (this._layerIdToSelect)
            this.selectNodeByLayerId(this._layerIdToSelect);
    }

    _updateBottomBar(newLayers)
    {
        if (!this._bottomBar)
            this._buildBottomBar();

        this._layersCountLabel.textContent = WI.UIString("Layer Count: %d").format(newLayers.length);

        let totalMemory = newLayers.reduce((total, layer) => total + (layer.memory || 0), 0);
        this._layersMemoryLabel.textContent = WI.UIString("Memory: %s").format(Number.bytesToString(totalMemory));
    }
};

WI.LayerDetailsSidebarPanel.Event = {
    SelectedLayerChanged: "selected-layer-changed"
};
