/*
 * 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.ShaderProgramContentView = class ShaderProgramContentView extends WI.ContentView
{
    constructor(shaderProgram)
    {
        console.assert(shaderProgram instanceof WI.ShaderProgram);

        super(shaderProgram);

        let isWebGPU = this.representedObject.canvas.contextType === WI.Canvas.ContextType.WebGPU;

        this._refreshButtonNavigationItem = new WI.ButtonNavigationItem("refresh", WI.UIString("Refresh"), "Images/ReloadFull.svg", 13, 13);
        this._refreshButtonNavigationItem.visibilityPriority = WI.NavigationItem.VisibilityPriority.Low;
        this._refreshButtonNavigationItem.addEventListener(WI.ButtonNavigationItem.Event.Clicked, this._refreshContent, this);

        let contentDidChangeDebouncer = new Debouncer((event) => {
            this._contentDidChange(event);
        });

        this.element.classList.add("shader-program", this.representedObject.programType);

        let createEditor = (shaderType) => {
            let container = this.element.appendChild(document.createElement("div"));

            let header = container.appendChild(document.createElement("header"));

            let shaderTypeContainer = header.appendChild(document.createElement("div"));
            shaderTypeContainer.classList.add("shader-type");

            let textEditor = new WI.TextEditor;
            textEditor.readOnly = false;
            textEditor.addEventListener(WI.TextEditor.Event.Focused, this._editorFocused, this);
            textEditor.addEventListener(WI.TextEditor.Event.NumberOfSearchResultsDidChange, this._numberOfSearchResultsDidChange, this);
            textEditor.addEventListener(WI.TextEditor.Event.ContentDidChange, (event) => {
                contentDidChangeDebouncer.delayForTime(250, event);
            }, this);

            switch (shaderType) {
            case WI.ShaderProgram.ShaderType.Compute:
                shaderTypeContainer.textContent = WI.UIString("Compute Shader");
                textEditor.mimeType = isWebGPU ? "x-pipeline/x-compute" : "x-shader/x-compute";
                break;

            case WI.ShaderProgram.ShaderType.Fragment:
                shaderTypeContainer.textContent = WI.UIString("Fragment Shader");
                textEditor.mimeType = isWebGPU ? "x-pipeline/x-fragment" : "x-shader/x-fragment";
                break;

            case WI.ShaderProgram.ShaderType.Vertex:
                shaderTypeContainer.textContent = WI.UIString("Vertex Shader");
                textEditor.mimeType = isWebGPU ? "x-pipeline/x-vertex" : "x-shader/x-vertex";
                break;
            }

            this.addSubview(textEditor);
            container.appendChild(textEditor.element);
            container.classList.add("shader", shaderType);

            return {container, textEditor};
        };

        switch (this.representedObject.programType) {
        case WI.ShaderProgram.ProgramType.Compute: {
            let computeEditor = createEditor(WI.ShaderProgram.ShaderType.Compute);
            this._computeContainer = computeEditor.container;
            this._computeEditor = computeEditor.textEditor;

            this._lastActiveEditor = this._computeEditor;
            break;
        }

        case WI.ShaderProgram.ProgramType.Render: {
            let vertexEditor = createEditor(WI.ShaderProgram.ShaderType.Vertex);
            this._vertexContainer = vertexEditor.container;
            this._vertexEditor = vertexEditor.textEditor;

            let fragmentEditor = createEditor(WI.ShaderProgram.ShaderType.Fragment);
            this._fragmentContainer = fragmentEditor.container;
            this._fragmentEditor = fragmentEditor.textEditor;

            this._lastActiveEditor = this._vertexEditor;
            break;
        }
        }
    }

    // Public

    get navigationItems()
    {
        return [this._refreshButtonNavigationItem];
    }

    // Protected

    shown()
    {
        super.shown();

        switch (this.representedObject.programType) {
        case WI.ShaderProgram.ProgramType.Compute:
            this._computeEditor.shown();
            break;

        case WI.ShaderProgram.ProgramType.Render:
            this._vertexEditor.shown();
            this._fragmentEditor.shown();
            break;
        }

        this._refreshContent();
    }

    hidden()
    {
        switch (this.representedObject.programType) {
        case WI.ShaderProgram.ProgramType.Compute:
            this._computeEditor.hidden();
            break;

        case WI.ShaderProgram.ProgramType.Render:
            this._vertexEditor.hidden();
            this._fragmentEditor.hidden();
            break;
        }

        super.hidden();
    }

    get supportsSave()
    {
        return true;
    }

    get saveData()
    {
        let filename = "";
        switch (this._lastActiveEditor) {
        case this._computeEditor:
            filename = WI.UIString("Compute");
            break;
        case this._fragmentEditor:
            filename = WI.UIString("Fragment");
            break;
        case this._vertexEditor:
            filename = WI.UIString("Vertex");
            break;
        }
        console.assert(filename);

        let extension = "";
        switch (this.representedObject.canvas.contextType) {
        case WI.Canvas.ContextType.WebGL:
        case WI.Canvas.ContextType.WebGL2:
            extension = WI.unlocalizedString(".glsl");
            break;
        case WI.Canvas.ContextType.WebGPU:
            extension = WI.unlocalizedString(".wsl");
            break;
        }
        console.assert(extension);

        return {
            url: WI.FileUtilities.inspectorURLForFilename(filename + extension),
            content: this._lastActiveEditor.string,
            forceSaveAs: true,
        };
    }

    get supportsSearch()
    {
        return true;
    }

    get numberOfSearchResults()
    {
        return this._lastActiveEditor.numberOfSearchResults;
    }

    get hasPerformedSearch()
    {
        return this._lastActiveEditor.currentSearchQuery !== null;
    }

    set automaticallyRevealFirstSearchResult(reveal)
    {
        this._lastActiveEditor.automaticallyRevealFirstSearchResult = reveal;
    }

    performSearch(query)
    {
        this._lastActiveEditor.performSearch(query);
    }

    searchCleared()
    {
        this._lastActiveEditor.searchCleared();
    }

    searchQueryWithSelection()
    {
        return this._lastActiveEditor.searchQueryWithSelection();
    }

    revealPreviousSearchResult(changeFocus)
    {
        this._lastActiveEditor.revealPreviousSearchResult(changeFocus);
    }

    revealNextSearchResult(changeFocus)
    {
        this._lastActiveEditor.revealNextSearchResult(changeFocus);
    }

    revealPosition(position, textRangeToSelect, forceUnformatted)
    {
        this._lastActiveEditor.revealPosition(position, textRangeToSelect, forceUnformatted);
    }

    // Private

    _refreshContent()
    {
        let createCallback = (container, textEditor) => {
            return (source) => {
                if (source === null) {
                    container.remove();
                    return;
                }

                if (!container.parentNode) {
                    switch (container) {
                    case this._computeContainer:
                    case this._vertexContainer:
                        this.element.insertAdjacentElement("afterbegin", container);
                        break;

                    case this._fragmentContainer:
                        this.element.insertAdjacentElement("beforeend", container);
                        break;
                    }
                }

                textEditor.string = source || "";
            };
        };

        switch (this.representedObject.programType) {
        case WI.ShaderProgram.ProgramType.Compute:
            this.representedObject.requestShaderSource(WI.ShaderProgram.ShaderType.Compute, createCallback(this._computeContainer, this._computeEditor));
            return;

        case WI.ShaderProgram.ProgramType.Render:
            this.representedObject.requestShaderSource(WI.ShaderProgram.ShaderType.Vertex, createCallback(this._vertexContainer, this._vertexEditor));
            this.representedObject.requestShaderSource(WI.ShaderProgram.ShaderType.Fragment, createCallback(this._fragmentContainer, this._fragmentEditor));
            return;
        }

        console.assert();
    }

    _updateShader(shaderType)
    {
        switch (shaderType) {
        case WI.ShaderProgram.ShaderType.Compute:
            this.representedObject.updateShader(shaderType, this._computeEditor.string);
            return;

        case WI.ShaderProgram.ShaderType.Fragment:
            this.representedObject.updateShader(shaderType, this._fragmentEditor.string);
            return;

        case WI.ShaderProgram.ShaderType.Vertex:
            this.representedObject.updateShader(shaderType, this._vertexEditor.string);
            return;
        }

        console.assert();
    }

    _editorFocused(event)
    {
        if (this._lastActiveEditor === event.target)
            return;

        let currentSearchQuery = null;

        if (this._lastActiveEditor) {
            currentSearchQuery = this._lastActiveEditor.currentSearchQuery;

            this._lastActiveEditor.searchCleared();
        }

        this._lastActiveEditor = event.target;

        if (currentSearchQuery)
            this._lastActiveEditor.performSearch(currentSearchQuery);
    }

    _numberOfSearchResultsDidChange(event)
    {
        this.dispatchEventToListeners(WI.ContentView.Event.NumberOfSearchResultsDidChange);
    }

    _contentDidChange(event)
    {
        switch (event.target) {
        case this._computeEditor:
            this._updateShader(WI.ShaderProgram.ShaderType.Compute);
            return;

        case this._fragmentEditor:
            this._updateShader(WI.ShaderProgram.ShaderType.Fragment);
            return;

        case this._vertexEditor:
            this._updateShader(WI.ShaderProgram.ShaderType.Vertex);
            return;
        }

        console.assert();
    }
};
