#include "tex_table.h"

#include <string.h>
#include <ctype.h>
#include "tex_table_tags.h"
#include "zalloc_ext.h"
#include "zalloc.h"

/* unnecessary includes */
#include <stdio.h>

#define	MAX_TEX_STACK_LEVEL 128

enum tex_parse_err {
	PARSE_ERROR_UNDEF = 0,
	PARSE_ERROR,
	PARSE_ERROR_STACKOVERFLOW
};

char * const TEX_PARSING_ERROR = "Error parsing";
char * const TEX_PARSING_ERROR_STACKOVERFLOW = "Error parsing";

int parse_table(const char *table_source, size_t len, struct table_s *table, struct xerror_s *error)
{
	char *tag = NULL,
	     *brpar = NULL;
	size_t i = 0;

	if (!len)
		len = strlen(table_source);

	enum where_e
	{
		IN_UNDEF = 0, // undefined place
		IN_COMMENT, // any comment
		IN_TAG, // any tag
		IN_CRLBR, // parameter in curly bracket
		IN_SQRBR, // parameter in square bracket
		IN_TAG_BEGIN, // in \begin tag
		IN_TAGPARM, // in \tag{} curly braces
		IN_LONGTABLE, // in longtable
		IN_FORMULA, // in $...$

	} where_stack[MAX_TEX_STACK_LEVEL] = {IN_UNDEF};

	size_t tex_level = 0;

	for (i = 0; i < len; i++) {

		/* stack checking */
		if (tex_level + 1 == MAX_TEX_STACK_LEVEL) {
			error->code = -1;
			error->message = TEX_PARSING_ERROR_STACKOVERFLOW;
			return -1;
		}

		/* read one character from input stream */
		char c = table_source[i];

		/* looking at where_stack and encountered character */
		switch (where_stack[tex_level]) {
		case IN_UNDEF:
			if (c == '\\') {
				tag = zfree_null(tag);
				where_stack[tex_level] = IN_TAG;

			} else if (c == '%') {
				where_stack[++tex_level] = IN_COMMENT;

			} else {
				error->code = -1;
				error->message = TEX_PARSING_ERROR;
				return -1;
			}

		break;

		case IN_COMMENT:
			if (c == '\r' || c == '\n') {
				where_stack[tex_level--] = IN_UNDEF;
			}
		break;

		case IN_TAG:
			if (islower(c) || isdigit(c) || (!tag && c == '\\')) {
				tag = zalloc_append8_str(tag, c);

			} else {
				if (!tag) {
					error->code = -1;
					error->message = TEX_PARSING_ERROR;
					return -1;

				} else if (!strcmp(tag, TEX_TAG_BEGIN)) {
					where_stack[tex_level++] = IN_TAG_BEGIN;

				} else if (!strcmp(tag, TEX_TAG_CLINE)) {

				} else if (!strcmp(tag, TEX_TAG_END)) {

				} else if (!strcmp(tag, TEX_TAG_ENDFOOT)) {

				} else if (!strcmp(tag, TEX_TAG_ENDHEAD)) {

				} else if (!strcmp(tag, TEX_TAG_HLINE)) {

				} else if (!strcmp(tag, TEX_TAG_HSPACE)) {

				} else if (!strcmp(tag, TEX_TAG_MULTICOLUMN)) {

				} else if (!strcmp(tag, TEX_TAG_MULTIROW)) {

				} else if (!strcmp(tag, TEX_TAG_TABULARNEWLINE)) {

				} else if (!strcmp(tag, TEX_TAG_SLASH)) {

				}
			}
		break;

		case IN_TAG_BEGIN:
			if (c == '{') {
				where_stack[++tex_level] = IN_TAGPARM;

			} else if (isspace(c)) {

			} else {
				error->code = -1;
				error->message = TEX_PARSING_ERROR;
				return -1;
			}
		break;

		case IN_TAGPARM:
			if (c == '}') {
				where_stack[tex_level--] = IN_UNDEF;

			} else if (isgraph(c)) {
				brpar = zalloc_append8_str(brpar, c);

			} else if (isspace(c)) {

			} else {
				error->code = -1;
				error->message = TEX_PARSING_ERROR;
				return -1;
			}
		break;

		default:
				error->code = -1;
				error->message = TEX_PARSING_ERROR;
				return -1;
		break;
		}
	}

	table->id = "Drossel1.Table1";

	error->message = NULL;

	return 0;
}