/*
 * 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.Layers3DContentView = class Layers3DContentView extends WI.ContentView
{
    constructor()
    {
        super();

        this.element.classList.add("layers-3d");

        this._compositingBordersButtonNavigationItem = new WI.ActivateButtonNavigationItem("layer-borders", WI.UIString("Show compositing borders"), WI.UIString("Hide compositing borders"), "Images/LayerBorders.svg", 13, 13);
        this._compositingBordersButtonNavigationItem.addEventListener(WI.ButtonNavigationItem.Event.Clicked, this._handleCompositingBordersButtonClicked, this);
        this._compositingBordersButtonNavigationItem.enabled = WI.LayerTreeManager.supportsVisibleCompositingBorders();
        this._compositingBordersButtonNavigationItem.visibilityPriority = WI.NavigationItem.VisibilityPriority.Low;

        this._paintFlashingButtonNavigationItem = new WI.ActivateButtonNavigationItem("paint-flashing", WI.UIString("Enable paint flashing"), WI.UIString("Disable paint flashing"), "Images/Paint.svg", 16, 16);
        this._paintFlashingButtonNavigationItem.addEventListener(WI.ButtonNavigationItem.Event.Clicked, this._handlePaingFlashingButtonClicked, this);
        this._paintFlashingButtonNavigationItem.enabled = WI.LayerTreeManager.supportsShowingPaintRects();
        this._paintFlashingButtonNavigationItem.visibilityPriority = WI.NavigationItem.VisibilityPriority.Low;

        this._layers = [];
        this._layerGroupsById = new Map;
        this._selectedLayerGroup = null;
        this._candidateSelection = null;
        this._nodeToSelect = null;

        this._renderer = null;
        this._camera = null;
        this._controls = null;
        this._scene = null;
        this._boundingBox = null;
        this._raycaster = null;
        this._animationFrameRequestId = null;
        this._documentNode = null;

        this._layerInfoElement = null;
        this._compositedDimensionsElement = null;
        this._visibleDimensionsElement = null;
        this._reasonsListElement = null;
    }

    // Public

    get navigationItems()
    {
        return [this._compositingBordersButtonNavigationItem, this._paintFlashingButtonNavigationItem];
    }

    get supplementalRepresentedObjects()
    {
        return this._layers;
    }

    selectLayerById(layerId)
    {
        let layerGroup = this._layerGroupsById.get(layerId);
        this._updateLayerGroupSelection(layerGroup);
        this._updateLayerInfoElement();
        this._centerOnSelection();
    }

    selectLayerForNode(node)
    {
        if (!this._layers.length) {
            this._nodeToSelect = node;
            return;
        }

        this._nodeToSelect = null;

        let layer = null;
        while (node && !layer) {
            layer = this._layers.find((layer) => layer.nodeId === node.id);
            if (!layer)
                node = node.parentNode;
        }

        console.assert(layer, "There should always be a top level (document) layer");
        if (!layer)
            return;

        this.selectLayerById(layer.layerId);

        this.dispatchEventToListeners(WI.Layers3DContentView.Event.SelectedLayerChanged, {layerId: layer.layerId});
    }

    // Protected

    attached()
    {
        super.attached();

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

        if (this.didInitialLayout)
            this._animate();

        WI.layerTreeManager.updateCompositingBordersVisibleFromPageIfNeeded();

        WI.layerTreeManager.addEventListener(WI.LayerTreeManager.Event.CompositingBordersVisibleChanged, this._handleCompositingBordersVisibleChanged, this);
        this._handleCompositingBordersVisibleChanged();

        WI.layerTreeManager.addEventListener(WI.LayerTreeManager.Event.ShowPaintRectsChanged, this._handleShowPaintRectsChanged, this);
        this._handleShowPaintRectsChanged();
    }

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

        this._stopAnimation();

        WI.layerTreeManager.removeEventListener(WI.LayerTreeManager.Event.ShowPaintRectsChanged, this._handleShowPaintRectsChanged, this);
        WI.layerTreeManager.removeEventListener(WI.LayerTreeManager.Event.CompositingBordersVisibleChanged, this._handleCompositingBordersVisibleChanged, this);

        super.detached();
    }

    initialLayout()
    {
        super.initialLayout();

        this._renderer = new THREE.WebGLRenderer({antialias: true});
        this._renderer.setSize(this.element.offsetWidth, this.element.offsetHeight);

        let updateBackground = () => {
            this._renderer.setClearColor(window.getComputedStyle(this.element).getPropertyValue("--background-color-content").trim());
        };
        window.matchMedia("(prefers-color-scheme: dark)").addListener(updateBackground);
        updateBackground();

        this._camera = new THREE.PerspectiveCamera(45, this.element.offsetWidth / this.element.offsetHeight, 1, 100_000);

        this._controls = new THREE.OrbitControls(this._camera, this._renderer.domElement);
        this._controls.enableDamping = true;
        this._controls.panSpeed = 0.5;
        this._controls.enableKeys = false;
        this._controls.zoomSpeed = 0.5;
        this._controls.minDistance = 1000;
        this._controls.rotateSpeed = 0.5;
        this._controls.minAzimuthAngle = -Math.PI / 2;
        this._controls.maxAzimuthAngle = Math.PI / 2;
        this._controls.screenSpacePanning = true;
        this._renderer.domElement.addEventListener("contextmenu", (event) => { event.stopPropagation(); });

        this._scene = new THREE.Scene;
        this._boundingBox = new THREE.Box3;

        this._raycaster = new THREE.Raycaster;
        this._renderer.domElement.addEventListener("mousedown", this._canvasMouseDown.bind(this));
        this._renderer.domElement.addEventListener("mouseup", this._canvasMouseUp.bind(this));

        this.element.appendChild(this._renderer.domElement);

        this._animate();
    }

    layout()
    {
        if (this.layoutReason === WI.View.LayoutReason.Resize)
            return;

        WI.domManager.requestDocument((node) => {
            let documentWasUpdated = this._updateDocument(node);

            WI.layerTreeManager.layersForNode(node, (layers) => {
                this._updateLayers(layers);

                if (documentWasUpdated)
                    this._resetCamera();

                if (this._nodeToSelect)
                    this.selectLayerForNode(this._nodeToSelect);
            });
        });
    }

    sizeDidChange()
    {
        super.sizeDidChange();

        this._stopAnimation();
        this._camera.aspect = this.element.offsetWidth / this.element.offsetHeight;
        this._camera.updateProjectionMatrix();
        this._renderer.setSize(this.element.offsetWidth, this.element.offsetHeight);
        this._animate();
    }

    // Private

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

    _animate()
    {
        this._controls.update();
        this._restrictPan();
        this._renderer.render(this._scene, this._camera);
        this._animationFrameRequestId = requestAnimationFrame(() => { this._animate(); });
    }

    _stopAnimation()
    {
        cancelAnimationFrame(this._animationFrameRequestId);
        this._animationFrameRequestId = null;
    }

    _updateDocument(documentNode)
    {
        if (documentNode === this._documentNode)
            return false;

        this._scene.children.length = 0;
        this._layerGroupsById.clear();
        this._layers.length = 0;

        this._documentNode = documentNode;

        return true;
    }

    _updateLayers(newLayers)
    {
        // FIXME: This should be made into the basic usage of the manager, if not the agent itself.
        //        At that point, we can remove this duplication from the visualization and sidebar.
        let {removals, additions} = WI.layerTreeManager.layerTreeMutations(this._layers, newLayers);

        for (let layer of removals) {
            let layerGroup = this._layerGroupsById.get(layer.layerId);
            this._scene.remove(layerGroup);
            this._layerGroupsById.delete(layer.layerId);
        }

        if (this._selectedLayerGroup && !this._layerGroupsById.get(this._selectedLayerGroup.userData.layer.layerId))
            this.selectedLayerGroup = null;

        for (let layer of additions) {
            let layerGroup = this._createLayerGroup(layer);
            this._layerGroupsById.set(layer.layerId, layerGroup);
            this._scene.add(layerGroup);
        }

        // FIXME: Update the backend to provide a literal "layer tree" so we can decide z-indices less naively.
        const zInterval = 25;
        newLayers.forEach((layer, index) => {
            let layerGroup = this._layerGroupsById.get(layer.layerId);
            layerGroup.position.set(0, 0, index * zInterval);
        });

        this._boundingBox.setFromObject(this._scene);
        this._controls.maxDistance = this._boundingBox.max.z + WI.Layers3DContentView._zPadding;

        this._layers = newLayers;
        this.dispatchEventToListeners(WI.ContentView.Event.SelectionPathComponentsDidChange);
    }

    _createLayerGroup(layer) {
        let layerGroup = new THREE.Group;
        layerGroup.userData.layer = layer;
        layerGroup.add(this._createLayerMesh(layer.bounds), this._createLayerMesh(layer.compositedBounds, true));
        return layerGroup;
    }

    _createLayerMesh({x, y, width, height}, isOutline = false)
    {
        let geometry = new THREE.Geometry;
        geometry.vertices.push(
            new THREE.Vector3(x, -y, 0),
            new THREE.Vector3(x, -y - height, 0),
            new THREE.Vector3(x + width, -y - height, 0),
            new THREE.Vector3(x + width, -y, 0),
        );

        if (isOutline) {
            let material = new THREE.LineBasicMaterial({color: WI.Layers3DContentView._layerColor.stroke});
            return new THREE.LineLoop(geometry, material);
        }

        geometry.faces.push(new THREE.Face3(0, 1, 3), new THREE.Face3(1, 2, 3));

        let material = new THREE.MeshBasicMaterial({
            color: WI.Layers3DContentView._layerColor.fill,
            transparent: true,
            opacity: 0.4,
            side: THREE.DoubleSide,
            depthWrite: false,
        });

        return new THREE.Mesh(geometry, material);
    }

    _canvasMouseDown(event)
    {
        let x = (event.offsetX / event.target.offsetWidth) * 2 - 1;
        let y = -(event.offsetY / event.target.offsetHeight) * 2 + 1;
        this._raycaster.setFromCamera(new THREE.Vector2(x, y), this._camera);

        const recursive = true;
        let intersects = this._raycaster.intersectObjects(this._scene.children, recursive);
        let layerGroup = intersects.length ? intersects[0].object.parent : null;
        this._candidateSelection = {layerGroup};

        let canvasMouseMove = (event) => {
            this._candidateSelection = null;
            this._renderer.domElement.removeEventListener("mousemove", canvasMouseMove);
        };

        this._renderer.domElement.addEventListener("mousemove", canvasMouseMove);
    }

    _canvasMouseUp(event)
    {
        if (!this._candidateSelection)
            return;

        let selection = this._candidateSelection.layerGroup;
        if (selection && selection === this._selectedLayerGroup) {
            if (!event.metaKey)
                return;

            selection = null;
        }

        this._updateLayerGroupSelection(selection);
        this._updateLayerInfoElement();

        let layerId = selection ? selection.userData.layer.layerId : null;
        this.dispatchEventToListeners(WI.Layers3DContentView.Event.SelectedLayerChanged, {layerId});
    }

    _updateLayerGroupSelection(layerGroup)
    {
        let setColor = ({fill, stroke}) => {
            let [plane, outline] = this._selectedLayerGroup.children;
            plane.material.color.set(fill);
            outline.material.color.set(stroke);
        };

        if (this._selectedLayerGroup)
            setColor(WI.Layers3DContentView._layerColor);

        this._selectedLayerGroup = layerGroup;

        if (this._selectedLayerGroup)
            setColor(WI.Layers3DContentView._selectedLayerColor);
    }

    _centerOnSelection()
    {
        if (!this._selectedLayerGroup)
            return;

        let {x, y, width, height} = this._selectedLayerGroup.userData.layer.bounds;
        this._controls.target.set(x + (width / 2), -y - (height / 2), 0);
        this._camera.position.set(x + (width / 2), -y - (height / 2), this._selectedLayerGroup.position.z + WI.Layers3DContentView._zPadding / 2);
    }

    _resetCamera()
    {
        let {x, y, width, height} = this._layers[0].bounds;
        this._controls.target.set(x + (width / 2), -y - (height / 2), 0);
        this._camera.position.set(x + (width / 2), -y - (height / 2), this._controls.maxDistance - WI.Layers3DContentView._zPadding / 2);
    }

    _restrictPan()
    {
        let delta = new THREE.Vector3;
        this._boundingBox.clampPoint(this._controls.target, delta).setZ(0).sub(this._controls.target);
        this._controls.target.add(delta);
        this._camera.position.add(delta);
    }

    _handleCompositingBordersVisibleChanged(event)
    {
        this._compositingBordersButtonNavigationItem.activated = WI.layerTreeManager.compositingBordersVisible;
    }

    _handleCompositingBordersButtonClicked(event)
    {
        WI.layerTreeManager.compositingBordersVisible = !WI.layerTreeManager.compositingBordersVisible;
    }

    _handleShowPaintRectsChanged(event)
    {
        this._paintFlashingButtonNavigationItem.activated = WI.layerTreeManager.showPaintRects;
    }

    _handlePaingFlashingButtonClicked(event)
    {
        WI.layerTreeManager.showPaintRects = !WI.layerTreeManager.showPaintRects;
    }

    _buildLayerInfoElement()
    {
        this._layerInfoElement = this._element.appendChild(document.createElement("div"));
        this._layerInfoElement.classList.add("layer-info", "hidden");

        let content = this._layerInfoElement.appendChild(document.createElement("div"));
        content.className = "content";

        let dimensionsTitle = content.appendChild(document.createElement("div"));
        dimensionsTitle.textContent = WI.UIString("Dimensions");
        let dimensionsTable = content.appendChild(document.createElement("table"));

        let compositedRow = dimensionsTable.appendChild(document.createElement("tr"));
        let compositedLabel = compositedRow.appendChild(document.createElement("td"));
        compositedLabel.textContent = WI.UIString("Composited");
        this._compositedDimensionsElement = compositedRow.appendChild(document.createElement("td"));

        let visibleRow = dimensionsTable.appendChild(document.createElement("tr"));
        let visibleLabel = visibleRow.appendChild(document.createElement("td"));
        visibleLabel.textContent = WI.UIString("Visible");
        this._visibleDimensionsElement = visibleRow.appendChild(document.createElement("td"));

        let reasonsTitle = content.appendChild(document.createElement("div"));
        reasonsTitle.textContent = WI.UIString("Reasons for compositing");
        this._reasonsListElement = content.appendChild(document.createElement("ul"));
    }

    _updateLayerInfoElement()
    {
        if (!this._layerInfoElement)
            this._buildLayerInfoElement();

        if (!this._selectedLayerGroup) {
            this._layerInfoElement.classList.add("hidden");
            return;
        }

        let layer = this._selectedLayerGroup.userData.layer;
        this._compositedDimensionsElement.textContent = `${layer.compositedBounds.width}px ${multiplicationSign} ${layer.compositedBounds.height}px`;
        this._visibleDimensionsElement.textContent = `${layer.bounds.width}px ${multiplicationSign} ${layer.bounds.height}px`;

        WI.layerTreeManager.reasonsForCompositingLayer(layer, (compositingReasons) => {
            this._updateReasonsList(compositingReasons);
            this._layerInfoElement.classList.remove("hidden");
        });
    }

    _updateReasonsList(compositingReasons)
    {
        this._reasonsListElement.removeChildren();

        let addReason = (reason) => {
            let item = this._reasonsListElement.appendChild(document.createElement("li"));
            item.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.model)
            addReason(WI.UIString("Element is <model>"));
        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"));
    }
};

WI.Layers3DContentView._zPadding = 3000;

WI.Layers3DContentView._layerColor = {
    fill: "hsl(76, 49%, 75%)",
    stroke: "hsl(79, 45%, 50%)"
};

WI.Layers3DContentView._selectedLayerColor = {
    fill: "hsl(208, 66%, 79%)",
    stroke: "hsl(202, 57%, 68%)"
};

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