/*
 * Copyright (C) 2016 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.
 */

importScripts(...[
    "../../External/Esprima/esprima.js",
    "FormatterUtilities.js",
    "FormatterContentBuilder.js",
    "ESTreeWalker.js",
    "EsprimaFormatter.js",
    "CSSFormatter.js",
]);

FormatterWorker = class FormatterWorker
{
    constructor()
    {
        self.addEventListener("message", this._handleMessage.bind(this));
    }

    // Actions

    formatJavaScript(sourceText, isModule, indentString, includeSourceMapData)
    {
        let sourceType = isModule ? EsprimaFormatter.SourceType.Module : EsprimaFormatter.SourceType.Script;

        // Format a JavaScript program.
        let formatter = new EsprimaFormatter(sourceText, sourceType, indentString);
        if (formatter.success) {
            let result = {formattedText: formatter.formattedText};
            if (includeSourceMapData) {
                result.sourceMapData = formatter.sourceMapData;
                // NOTE: With the EsprimaFormatter, multi-line tokens, such as comments and strings,
                // would not have had their newlines counted properly by the builder. Rather then
                // modify the formatter to check and account for newlines in every token just
                // compute the list of line endings directly on the result.
                result.sourceMapData.formattedLineEndings = result.formattedText.lineEndings();
            }
            return result;
        }

        // Format valid JSON.
        // The formatter could fail if this was just a JSON string. So try a JSON.parse and stringify.
        // This will produce empty source map data, but it is not code, so it is not as important.
        try {
            let jsonStringified = JSON.stringify(JSON.parse(sourceText), null, indentString);
            let result = {formattedText: jsonStringified};
            if (includeSourceMapData)
                result.sourceMapData = {mapping: {original: [], formatted: []}, originalLineEndings: [], formattedLineEndings: []};
            return result;
        } catch { }

        // Format invalid JSON and anonymous functions.
        // Some applications do not use JSON.parse but eval on JSON content. That is more permissive
        // so try to format invalid JSON. Again no source map data since it is not code.
        // Likewise, an unnamed function's toString() produces a "function() { ... }", which is not
        // a valid program on its own. Wrap it in parenthesis to make it a function expression,
        // which is a valid program.
        let invalidJSONFormatter = new EsprimaFormatter("(" + sourceText + ")", sourceType, indentString);
        if (invalidJSONFormatter.success) {
            let formattedTextWithParens = invalidJSONFormatter.formattedText;
            let result = {formattedText: formattedTextWithParens.substring(1, formattedTextWithParens.length - 2)}; // Remove "(" and ")\n".
            if (includeSourceMapData)
                result.sourceMapData = {mapping: {original: [], formatted: []}, originalLineEndings: [], formattedLineEndings: []};
            return result;
        }

        return {formattedText: null};
    }

    formatCSS(sourceText, indentString, includeSourceMapData)
    {
        let result = {formattedText: null};
        let formatter = new CSSFormatter(sourceText, indentString);
        if (formatter.success) {
            result.formattedText = formatter.formattedText;
            if (includeSourceMapData)
                result.sourceMapData = formatter.sourceMapData;
        }
        return result;
    }

    // Private

    _handleMessage(event)
    {
        let data = event.data;

        // Action.
        if (data.actionName) {
            let result = this[data.actionName](...data.actionArguments);
            self.postMessage({callId: data.callId, result});
            return;
        }

        console.error("Unexpected FormatterWorker message", data);
    }
};

self.formatterWorker = new FormatterWorker;
