/*
 * Copyright (C) 2017 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.RecordingActionTreeElement = class RecordingActionTreeElement extends WI.GeneralTreeElement
{
    constructor(representedObject, index, recordingType)
    {
        console.assert(representedObject instanceof WI.RecordingAction);

        let {titleFragment, copyText} = WI.RecordingActionTreeElement._generateDOM(representedObject, recordingType);
        let classNames = WI.RecordingActionTreeElement._getClassNames(representedObject);

        const subtitle = null;
        super(classNames, titleFragment, subtitle, representedObject);

        this._index = index;
        this._copyText = copyText;

        if (this.representedObject.valid)
            this.representedObject.addEventListener(WI.RecordingAction.Event.ValidityChanged, this._handleValidityChanged, this);
    }

    // Static

    static _generateDOM(recordingAction, recordingType)
    {
        let parameterCount = recordingAction.parameters.length;

        function createParameterElement(parameter, swizzleType, index) {
            let parameterElement = document.createElement("span");
            parameterElement.classList.add("parameter");

            switch (swizzleType) {
            case WI.Recording.Swizzle.Number:
                var constantNameForParameter = WI.RecordingAction.constantNameForParameter(recordingType, recordingAction.name, parameter, index, parameterCount);
                if (constantNameForParameter) {
                    parameterElement.classList.add("constant");
                    parameterElement.textContent = "context." + constantNameForParameter;
                } else
                    parameterElement.textContent = parameter.maxDecimals(2);
                break;

            case WI.Recording.Swizzle.Boolean:
                parameterElement.textContent = parameter;
                break;

            case WI.Recording.Swizzle.String:
                parameterElement.textContent = JSON.stringify(parameter);
                break;

            case WI.Recording.Swizzle.Array:
                parameterElement.classList.add("swizzled");
                parameterElement.textContent = JSON.stringify(parameter);
                break;

            case WI.Recording.Swizzle.TypedArray:
            case WI.Recording.Swizzle.Image:
            case WI.Recording.Swizzle.ImageBitmap:
            case WI.Recording.Swizzle.ImageData:
            case WI.Recording.Swizzle.DOMMatrix:
            case WI.Recording.Swizzle.Path2D:
            case WI.Recording.Swizzle.CanvasGradient:
            case WI.Recording.Swizzle.CanvasPattern:
            case WI.Recording.Swizzle.WebGLBuffer:
            case WI.Recording.Swizzle.WebGLFramebuffer:
            case WI.Recording.Swizzle.WebGLRenderbuffer:
            case WI.Recording.Swizzle.WebGLTexture:
            case WI.Recording.Swizzle.WebGLShader:
            case WI.Recording.Swizzle.WebGLProgram:
            case WI.Recording.Swizzle.WebGLUniformLocation:
            case WI.Recording.Swizzle.WebGLQuery:
            case WI.Recording.Swizzle.WebGLSampler:
            case WI.Recording.Swizzle.WebGLSync:
            case WI.Recording.Swizzle.WebGLTransformFeedback:
            case WI.Recording.Swizzle.WebGLVertexArrayObject:
                parameterElement.classList.add("swizzled");
                parameterElement.textContent = WI.Recording.displayNameForSwizzleType(swizzleType);
                break;
            }

            if (!parameterElement.textContent) {
                parameterElement.classList.add("invalid");
                parameterElement.textContent = swizzleType === WI.Recording.Swizzle.None ? parameter : WI.Recording.displayNameForSwizzleType(swizzleType);
            }

            return parameterElement;
        }

        let titleFragment = document.createDocumentFragment();
        let copyText = recordingAction.name;

        let contextReplacer = recordingAction.contextReplacer;
        if (contextReplacer) {
            copyText = contextReplacer + "." + copyText;

            let contextReplacerContainer = titleFragment.appendChild(document.createElement("span"));
            contextReplacerContainer.classList.add("context-replacer");
            contextReplacerContainer.textContent = contextReplacer;
        }

        let nameContainer = titleFragment.appendChild(document.createElement("span"));
        nameContainer.classList.add("name");
        nameContainer.textContent = recordingAction.name;

        if (!parameterCount)
            return {titleFragment, copyText};

        let parametersContainer = titleFragment.appendChild(document.createElement("span"));
        parametersContainer.classList.add("parameters");

        if (recordingAction.isFunction)
            copyText += "(";
        else
            copyText += " = ";

        for (let i = 0; i < parameterCount; ++i) {
            let parameter = recordingAction.parameters[i];
            let swizzleType = recordingAction.swizzleTypes[i];
            let parameterElement = createParameterElement(parameter, swizzleType, i);
            parametersContainer.appendChild(parameterElement);

            if (i)
                copyText += ", ";

            copyText += parameterElement.textContent;
        }

        if (recordingAction.isFunction)
            copyText += ")";

        let colorParameters = recordingAction.getColorParameters();
        if (colorParameters.length) {
            let swatch = WI.RecordingActionTreeElement._createSwatchForColorParameters(colorParameters);
            if (swatch) {
                let insertionIndex = recordingAction.parameters.indexOf(colorParameters[0]);
                parametersContainer.insertBefore(swatch.element, parametersContainer.children[insertionIndex]);
            }
        }

        let imageParameters = recordingAction.getImageParameters();
        let isImage = imageParameters[0] instanceof HTMLImageElement;
        let isImageBitmap = imageParameters[0] instanceof ImageBitmap;
        let isImageData = imageParameters[0] instanceof ImageData;
        let isCanvasGradient = imageParameters[0] instanceof CanvasGradient;
        let isCanvasPattern = imageParameters[0] instanceof CanvasPattern;
        if (imageParameters.length && (isImage || isImageBitmap || isImageData || isCanvasGradient || isCanvasPattern)) {
            let image = imageParameters[0];

            if (isImageBitmap)
                image = WI.ImageUtilities.imageFromImageBitmap(image);
            else if (isImageData)
                image = WI.ImageUtilities.imageFromImageData(image);
            else if (isCanvasGradient)
                image = WI.ImageUtilities.imageFromCanvasGradient(image, 100, 100);
            else if (isCanvasPattern)
                image = image.__image;

            if (image) {
                let swatch = new WI.InlineSwatch(WI.InlineSwatch.Type.Image, image);
                let insertionIndex = recordingAction.parameters.indexOf(imageParameters[0]);
                let parameterElement = parametersContainer.children[insertionIndex];
                parametersContainer.insertBefore(swatch.element, parameterElement);
            }
        }

        return {titleFragment, copyText};
    }

    static _createSwatchForColorParameters(parameters)
    {
        let rgb = [];
        let color = null;

        switch (parameters.length) {
        case 1:
        case 2:
            if (typeof parameters[0] === "string")
                color = WI.Color.fromString(parameters[0].trim());
            else if (!isNaN(parameters[0]))
                rgb = WI.Color.normalized2rgb(parameters[0], parameters[0], parameters[0]);
            break;

        case 4:
            rgb = WI.Color.normalized2rgb(parameters[0], parameters[1], parameters[2]);
            break;

        case 5:
            rgb = WI.Color.cmyk2rgb(...parameters);
            break;

        default:
            console.error("Unexpected number of color parameters.");
            return null;
        }

        if (!color) {
            if (rgb.length !== 3)
                return null;

            let alpha = parameters.length === 1 ? 1 : parameters.lastValue;
            color = new WI.Color(WI.Color.Format.RGBA, [...rgb, alpha]);
            if (!color)
                return null;
        }

        const readOnly = true;
        return new WI.InlineSwatch(WI.InlineSwatch.Type.Color, color, readOnly);
    }

    static _getClassNames(recordingAction)
    {
        let classNames = ["recording-action"];

        if (recordingAction instanceof WI.RecordingInitialStateAction) {
            classNames.push("initial-state");
            return classNames;
        }

        if (!recordingAction.isFunction)
            classNames.push("attribute");

        let actionClassName = WI.RecordingActionTreeElement._classNameForAction(recordingAction);
        if (actionClassName.length)
            classNames.push(actionClassName);

        if (recordingAction.isVisual)
            classNames.push("visual");

        if (!recordingAction.valid)
            classNames.push("invalid");

        return classNames;
    }

    static _classNameForAction(recordingAction)
    {
        if (recordingAction.contextReplacer)
            return "has-context-replacer";

        switch (recordingAction.name) {
        case "arc":
        case "arcTo":
            return "arc";

        case "globalAlpha":
        case "globalCompositeOperation":
        case "setAlpha":
        case "setGlobalAlpha":
        case "setCompositeOperation":
        case "setGlobalCompositeOperation":
            return "composite";

        case "bezierCurveTo":
        case "quadraticCurveTo":
            return "curve";

        case "clearRect":
        case "fill":
        case "fillRect":
        case "fillText":
            return "fill";

        case "createImageData":
        case "drawFocusIfNeeded":
        case "drawImage":
        case "drawImageFromRect":
        case "filter":
        case "getImageData":
        case "imageSmoothingEnabled":
        case "imageSmoothingQuality":
        case "putImageData":
        case "transferFromImageBitmap":
        case "webkitImageSmoothingEnabled":
            return "image";

        case "getLineDash":
        case "lineCap":
        case "lineDashOffset":
        case "lineJoin":
        case "lineWidth":
        case "miterLimit":
        case "setLineCap":
        case "setLineDash":
        case "setLineJoin":
        case "setLineWidth":
        case "setMiterLimit":
        case "webkitLineDash":
        case "webkitLineDashOffset":
            return "line-style";

        case "closePath":
        case "lineTo":
            return "line-to";

        case "beginPath":
        case "moveTo":
            return "move-to";

        case "isPointInPath":
            return "point-in-path";

        case "isPointInStroke":
            return "point-in-stroke";

        case "clearShadow":
        case "setShadow":
        case "shadowBlur":
        case "shadowColor":
        case "shadowOffsetX":
        case "shadowOffsetY":
            return "shadow";

        case "createLinearGradient":
        case "createPattern":
        case "createRadialGradient":
        case "fillStyle":
        case "setFillColor":
        case "setStrokeColor":
        case "strokeStyle":
            return "style";

        case "stroke":
        case "strokeRect":
        case "strokeText":
            return "stroke";

        case "direction":
        case "font":
        case "measureText":
        case "textAlign":
        case "textBaseline":
            return "text";

        case "getTransform":
        case "resetTransform":
        case "rotate":
        case "scale":
        case "setTransform":
        case "transform":
        case "translate":
            return "transform";

        case "clip":
        case "ellipse":
        case "rect":
        case "restore":
        case "save":
            return recordingAction.name;
        }

        return "name-unknown";
    }

    // Public

    get index() { return this._index; }

    get filterableData()
    {
        let text = [];

        function getText(stringOrElement) {
            if (typeof stringOrElement === "string")
                text.push(stringOrElement);
            else if (stringOrElement instanceof Node)
                text.push(stringOrElement.textContent);
        }

        getText(this._mainTitleElement || this._mainTitle);
        getText(this._subtitleElement || this._subtitle);

        return {text};
    }

    // Protected

    customTitleTooltip()
    {
        return this._copyText;
    }

    onattach()
    {
        super.onattach();

        this.element.dataset.index = this._index.toLocaleString();

        if (this.representedObject.valid && this.representedObject.warning) {
            this.addClassName("warning");
            this.status = WI.ImageUtilities.useSVGSymbol("Images/Warning.svg", "warning", this.representedObject.warning);
        }
    }

    populateContextMenu(contextMenu, event)
    {
        contextMenu.appendItem(WI.UIString("Copy Action"), () => {
            InspectorFrontendHost.copyText("context." + this._copyText + ";");
        });

        contextMenu.appendSeparator();

        let sourceCodeLocation = null;
        for (let callFrame of this.representedObject.trace) {
            if (callFrame.sourceCodeLocation) {
                sourceCodeLocation = callFrame.sourceCodeLocation;
                break;
            }
        }

        if (sourceCodeLocation) {
            contextMenu.appendItem(WI.UIString("Reveal in Sources Tab"), () => {
                WI.showSourceCodeLocation(sourceCodeLocation, {
                    ignoreNetworkTab: true,
                    ignoreSearchTab: true,
                });
            });

            contextMenu.appendSeparator();
        }

        super.populateContextMenu(contextMenu, event);
    }

    // Private

    _handleValidityChanged(event)
    {
        this.addClassName("invalid");

        this.representedObject.removeEventListener(null, null, this);
    }
};
