/*
 * 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.
 */

#include "config.h"

#include "guacamole/error.h"
#include "guacamole/parser.h"
#include "guacamole/socket.h"
#include "guacamole/unicode.h"

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

static void guac_parser_reset(guac_parser* parser) {
    parser->opcode = NULL;
    parser->argc = 0;
    parser->state = GUAC_PARSE_LENGTH;
    parser->__elementc = 0;
    parser->__element_length = 0;
}

guac_parser* guac_parser_alloc() {

    /* Allocate space for parser */
    guac_parser* parser = malloc(sizeof(guac_parser));
    if (parser == NULL) {
        guac_error = GUAC_STATUS_NO_MEMORY;
        guac_error_message = "Insufficient memory to allocate parser";
        return NULL;
    }

    /* Init parse start/end markers */
    parser->__instructionbuf_unparsed_start = parser->__instructionbuf;
    parser->__instructionbuf_unparsed_end = parser->__instructionbuf;

    guac_parser_reset(parser);
    return parser;

}

int guac_parser_append(guac_parser* parser, void* buffer, int length) {

    char* char_buffer = (char*) buffer;
    int bytes_parsed = 0;

    /* Do not exceed maximum number of elements */
    if (parser->__elementc == GUAC_INSTRUCTION_MAX_ELEMENTS
            && parser->state != GUAC_PARSE_COMPLETE) {
        parser->state = GUAC_PARSE_ERROR;
        return 0;
    }

    /* Parse element length */
    if (parser->state == GUAC_PARSE_LENGTH) {

        int parsed_length = parser->__element_length;
        while (bytes_parsed < length) {

            /* Pull next character */
            char c = *(char_buffer++);
            bytes_parsed++;

            /* If digit, add to length */
            if (c >= '0' && c <= '9')
                parsed_length = parsed_length*10 + c - '0';

            /* If period, switch to parsing content */
            else if (c == '.') {
                parser->__elementv[parser->__elementc++] = char_buffer;
                parser->state = GUAC_PARSE_CONTENT;
                break;
            }

            /* If not digit, parse error */
            else {
                parser->state = GUAC_PARSE_ERROR;
                return 0;
            }

        }

        /* If too long, parse error */
        if (parsed_length > GUAC_INSTRUCTION_MAX_LENGTH) {
            parser->state = GUAC_PARSE_ERROR;
            return 0;
        }

        /* Save length */
        parser->__element_length = parsed_length;

    } /* end parse length */

    /* Parse element content */
    if (parser->state == GUAC_PARSE_CONTENT) {

        while (bytes_parsed < length && parser->__element_length >= 0) {

            /* Get length of current character */
            char c = *char_buffer;
            int char_length = guac_utf8_charsize((unsigned char) c);

            /* If full character not present in buffer, stop now */
            if (char_length + bytes_parsed > length)
                break;

            /* Record character as parsed */
            bytes_parsed += char_length;

            /* If end of element, handle terminator */
            if (parser->__element_length == 0) {

                *char_buffer = '\0';

                /* If semicolon, store end-of-instruction */
                if (c == ';') {
                    parser->state = GUAC_PARSE_COMPLETE;
                    parser->opcode = parser->__elementv[0];
                    parser->argv = &(parser->__elementv[1]);
                    parser->argc = parser->__elementc - 1;
                    break;
                }

                /* If comma, move on to next element */
                else if (c == ',') {
                    parser->state = GUAC_PARSE_LENGTH;
                    break;
                }

                /* Otherwise, parse error */
                else {
                    parser->state = GUAC_PARSE_ERROR;
                    return 0;
                }

            } /* end if end of element */

            /* Advance to next character */
            parser->__element_length--;
            char_buffer += char_length;

        }

    } /* end parse content */

    return bytes_parsed;

}

int guac_parser_read(guac_parser* parser, guac_socket* socket, int usec_timeout) {

    char* unparsed_end   = parser->__instructionbuf_unparsed_end;
    char* unparsed_start = parser->__instructionbuf_unparsed_start;
    char* instr_start    = parser->__instructionbuf_unparsed_start;
    char* buffer_end     = parser->__instructionbuf + sizeof(parser->__instructionbuf);

    /* Begin next instruction if previous was ended */
    if (parser->state == GUAC_PARSE_COMPLETE)
        guac_parser_reset(parser);

    while (parser->state != GUAC_PARSE_COMPLETE
        && parser->state != GUAC_PARSE_ERROR) {

        /* Add any available data to buffer */
        int parsed = guac_parser_append(parser, unparsed_start, unparsed_end - unparsed_start);

        /* Read more data if not enough data to parse */
        if (parsed == 0 && parser->state != GUAC_PARSE_ERROR) {

            int retval;

            /* If no space left to read, fail */
            if (unparsed_end == buffer_end) {

                /* Shift backward if possible */
                if (instr_start != parser->__instructionbuf) {

                    int i;

                    /* Shift buffer */
                    int offset = instr_start - parser->__instructionbuf;
                    memmove(parser->__instructionbuf, instr_start,
                            unparsed_end - instr_start);

                    /* Update tracking pointers */
                    unparsed_end -= offset;
                    unparsed_start -= offset;
                    instr_start = parser->__instructionbuf;

                    /* Update parsed elements, if any */
                    for (i=0; i < parser->__elementc; i++)
                        parser->__elementv[i] -= offset;

                }

                /* Otherwise, no memory to read */
                else {
                    guac_error = GUAC_STATUS_NO_MEMORY;
                    guac_error_message = "Instruction too long";
                    return -1;
                }

            }

            /* No instruction yet? Get more data ... */
            retval = guac_socket_select(socket, usec_timeout);
            if (retval <= 0)
                return -1;
           
            /* Attempt to fill buffer */
            retval = guac_socket_read(socket, unparsed_end,
                    buffer_end - unparsed_end);

            /* Set guac_error if read unsuccessful */
            if (retval < 0) {
                guac_error = GUAC_STATUS_SEE_ERRNO;
                guac_error_message = "Error filling instruction buffer";
                return -1;
            }

            /* EOF */
            if (retval == 0) {
                guac_error = GUAC_STATUS_CLOSED;
                guac_error_message = "End of stream reached while "
                                     "reading instruction";
                return -1;
            }

            /* Update internal buffer */
            unparsed_end += retval;

        }

        /* If data was parsed, advance buffer */
        else
            unparsed_start += parsed;

    } /* end while parsing data */

    /* Fail on error */
    if (parser->state == GUAC_PARSE_ERROR) {
        guac_error = GUAC_STATUS_PROTOCOL_ERROR;
        guac_error_message = "Instruction parse error";
        return -1;
    }

    parser->__instructionbuf_unparsed_start = unparsed_start;
    parser->__instructionbuf_unparsed_end = unparsed_end;
    return 0;

}

int guac_parser_expect(guac_parser* parser, guac_socket* socket, int usec_timeout, const char* opcode) {

    /* Read next instruction */
    if (guac_parser_read(parser, socket, usec_timeout) != 0)
        return -1;

    /* Validate instruction */
    if (strcmp(parser->opcode, opcode) != 0) {
        guac_error = GUAC_STATUS_PROTOCOL_ERROR;
        guac_error_message = "Instruction read did not have expected opcode";
        return -1;
    }

    /* Return non-zero only if valid instruction read */
    return parser->state != GUAC_PARSE_COMPLETE;

}

int guac_parser_length(guac_parser* parser) {

    char* unparsed_end   = parser->__instructionbuf_unparsed_end;
    char* unparsed_start = parser->__instructionbuf_unparsed_start;

    return unparsed_end - unparsed_start;

}

int guac_parser_shift(guac_parser* parser, void* buffer, int length) {

    char* copy_end   = parser->__instructionbuf_unparsed_end;
    char* copy_start = parser->__instructionbuf_unparsed_start;

    /* Contain copy region within length */
    if (copy_end - copy_start > length)
        copy_end = copy_start + length;

    /* Copy buffer */
    length = copy_end - copy_start;
    memcpy(buffer, copy_start, length);

    parser->__instructionbuf_unparsed_start = copy_end;

    return length;

}

void guac_parser_free(guac_parser* parser) {
    free(parser);
}

