/*
 * 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 node = this._dataGrid.dataGridNodeFromNode(event.target);
        if (node === this._hoveredDataGridNode)
            return;

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

        this._hoveredDataGridNode = node;

        if (node.layer.isGeneratedContent || node.layer.isReflection || node.layer.isAnonymous) {
            const usePageCoordinates = true;
            WI.domManager.highlightRect(node.layer.bounds, usePageCoordinates);
        } else
            WI.domManager.highlightDOMNode(node.layer.nodeId);
    }

    _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"
};
