/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

var Guacamole = Guacamole || {};

/**
 * Simple Guacamole protocol parser that invokes an oninstruction event when
 * full instructions are available from data received via receive().
 *
 * @constructor
 */
Guacamole.Parser = function Parser() {

    /**
     * Reference to this parser.
     *
     * @private
     * @type {!Guacamole.Parser}
     */
    var parser = this;

    /**
     * Current buffer of received data. This buffer grows until a full
     * element is available. After a full element is available, that element
     * is flushed into the element buffer.
     *
     * @private
     * @type {!string}
     */
    var buffer = '';

    /**
     * Buffer of all received, complete elements. After an entire instruction
     * is read, this buffer is flushed, and a new instruction begins.
     *
     * @private
     * @type {!string[]}
     */
    var elementBuffer = [];

    /**
     * The character offset within the buffer of the current or most recently
     * parsed element's terminator. If sufficient characters have not yet been
     * read via calls to receive(), this may point to an offset well beyond the
     * end of the buffer. If no characters for an element have yet been read,
     * this will be -1.
     *
     * @private
     * @type {!number}
     */
    var elementEnd = -1;

    /**
     * The character offset within the buffer of the location that the parser
     * should start looking for the next element length search or next element
     * value.
     *
     * @private
     * @type {!number}
     */
    var startIndex = 0;

    /**
     * The declared length of the current element being parsed, in Unicode
     * codepoints.
     *
     * @private
     * @type {!number}
     */
    var elementCodepoints = 0;

    /**
     * The number of parsed characters that must accumulate in the begining of
     * the parse buffer before processing time is expended to truncate that
     * buffer and conserve memory.
     *
     * @private
     * @constant
     * @type {!number}
     */
    var BUFFER_TRUNCATION_THRESHOLD = 4096;

    /**
     * The lowest Unicode codepoint to require a surrogate pair when encoded
     * with UTF-16. In UTF-16, characters with codepoints at or above this
     * value are represented with a surrogate pair, while characters with
     * codepoints below this value are represented with a single character.
     *
     * @private
     * @constant
     * @type {!number}
     */
    var MIN_CODEPOINT_REQUIRES_SURROGATE = 0x10000;

    /**
     * Appends the given instruction data packet to the internal buffer of
     * this Guacamole.Parser, executing all completed instructions at
     * the beginning of this buffer, if any.
     *
     * @param {!string} packet
     *     The instruction data to receive.
     *
     * @param {!boolean} [isBuffer=false]
     *     Whether the provided data should be treated as an instruction buffer
     *     that grows continuously. If true, the data provided to receive()
     *     MUST always start with the data provided to the previous call. If
     *     false (the default), only the new data should be provided to
     *     receive(), and previously-received data will automatically be
     *     buffered by the parser as needed.
     */
    this.receive = function receive(packet, isBuffer) {

        if (isBuffer)
            buffer = packet;

        else {

            // Truncate buffer as necessary
            if (startIndex > BUFFER_TRUNCATION_THRESHOLD && elementEnd >= startIndex) {

                buffer = buffer.substring(startIndex);

                // Reset parse relative to truncation
                elementEnd -= startIndex;
                startIndex = 0;

            }

            // Append data to buffer ONLY if there is outstanding data present. It
            // is otherwise much faster to simply parse the received buffer as-is,
            // and tunnel implementations can take advantage of this by preferring
            // to send only complete instructions. Both the HTTP and WebSocket
            // tunnel implementations included with Guacamole already do this.
            if (buffer.length)
                buffer += packet;
            else
                buffer = packet;

        }

        // While search is within currently received data
        while (elementEnd < buffer.length) {

            // If we are waiting for element data
            if (elementEnd >= startIndex) {

                // If we have enough data in the buffer to fill the element
                // value, but the number of codepoints in the expected substring
                // containing the element value value is less that its declared
                // length, that can only be because the element contains
                // characters split between high and low surrogates, and the
                // actual end of the element value is further out. The minimum
                // number of additional characters that must be read to satisfy
                // the declared length is simply the difference between the
                // number of codepoints actually present vs. the expected
                // length.
                var codepoints = Guacamole.Parser.codePointCount(buffer, startIndex, elementEnd);
                if (codepoints < elementCodepoints) {
                    elementEnd += elementCodepoints - codepoints;
                    continue;
                }

                // If the current element ends with a character involving both
                // a high and low surrogate, elementEnd points to the low
                // surrogate and NOT the element terminator. We must shift the
                // end and reevaluate.
                else if (elementCodepoints && buffer.codePointAt(elementEnd - 1) >= MIN_CODEPOINT_REQUIRES_SURROGATE) {
                    elementEnd++;
                    continue;
                }

                // We now have enough data for the element. Parse.
                var element = buffer.substring(startIndex, elementEnd);
                var terminator = buffer.substring(elementEnd, elementEnd + 1);

                // Add element to array
                elementBuffer.push(element);

                // If last element, handle instruction
                if (terminator === ';') {

                    // Get opcode
                    var opcode = elementBuffer.shift();

                    // Call instruction handler.
                    if (parser.oninstruction !== null)
                        parser.oninstruction(opcode, elementBuffer);

                    // Clear elements
                    elementBuffer = [];

                    // Immediately truncate buffer if its contents have been
                    // completely parsed, so that the next call to receive()
                    // need not append to the buffer unnecessarily
                    if (elementEnd + 1 === buffer.length) {
                        elementEnd = -1;
                        buffer = '';
                    }

                }
                else if (terminator !== ',')
                    throw new Error('Element terminator of instruction was not ";" nor ",".');

                // Start searching for length at character after
                // element terminator
                startIndex = elementEnd + 1;

            }

            // Search for end of length
            var lengthEnd = buffer.indexOf('.', startIndex);
            if (lengthEnd !== -1) {

                // Parse length
                elementCodepoints = parseInt(buffer.substring(elementEnd + 1, lengthEnd));
                if (isNaN(elementCodepoints))
                    throw new Error('Non-numeric character in element length.');

                // Calculate start of element
                startIndex = lengthEnd + 1;

                // Calculate location of element terminator
                elementEnd = startIndex + elementCodepoints;

            }

            // If no period yet, continue search when more data
            // is received
            else {
                startIndex = buffer.length;
                break;
            }

        } // end parse loop

    };

    /**
     * Fired once for every complete Guacamole instruction received, in order.
     *
     * @event
     * @param {!string} opcode
     *     The Guacamole instruction opcode.
     *
     * @param {!string[]} parameters
     *     The parameters provided for the instruction, if any.
     */
    this.oninstruction = null;

};

/**
 * Returns the number of Unicode codepoints (not code units) within the given
 * string. If character offsets are provided, only codepoints between those
 * offsets are counted. Unlike the length property of a string, this function
 * counts proper surrogate pairs as a single codepoint. High and low surrogate
 * characters that are not part of a proper surrogate pair are counted
 * separately as individual codepoints.
 *
 * @param {!string} str
 *     The string whose contents should be inspected.
 *
 * @param {number} [start=0]
 *     The index of the location in the given string where codepoint counting
 *     should start. If omitted, counting will begin at the start of the
 *     string.
 *
 * @param {number} [end]
 *     The index of the first location in the given string after where counting
 *     should stop (the character after the last character being counted). If
 *     omitted, all characters after the start location will be counted.
 *
 * @returns {!number}
 *     The number of Unicode codepoints within the requested portion of the
 *     given string.
 */
Guacamole.Parser.codePointCount = function codePointCount(str, start, end) {

    // Count only characters within the specified region
    str = str.substring(start || 0, end);

    // Locate each proper Unicode surrogate pair (one high surrogate followed
    // by one low surrogate)
    var surrogatePairs = str.match(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g);

    // Each surrogate pair represents a single codepoint but is represented by
    // two characters in a JavaScript string, and thus is counted twice toward
    // string length. Subtracting the number of surrogate pairs adjusts that
    // length value such that it gives us the number of codepoints.
    return str.length - (surrogatePairs ? surrogatePairs.length : 0);

};

/**
 * Converts each of the values within the given array to strings, formatting
 * those strings as length-prefixed elements of a complete Guacamole
 * instruction.
 *
 * @param {!*[]} elements
 *     The values that should be encoded as the elements of a Guacamole
 *     instruction. Order of these elements is preserved. This array MUST have
 *     at least one element.
 *
 * @returns {!string}
 *     A complete Guacamole instruction consisting of each of the provided
 *     element values, in order.
 */
Guacamole.Parser.toInstruction = function toInstruction(elements) {

    /**
     * Converts the given value to a length/string pair for use as an
     * element in a Guacamole instruction.
     *
     * @private
     * @param {*} value
     *     The value to convert.
     *
     * @return {!string}
     *     The converted value.
     */
    var toElement = function toElement(value) {
        var str = '' + value;
        return Guacamole.Parser.codePointCount(str) + "." + str;
    };

    var instr = toElement(elements[0]);
    for (var i = 1; i < elements.length; i++)
        instr += ',' + toElement(elements[i]);

    return instr + ';';

};
