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

#include "asn1parser.h"

asn1p_ioc_row_t *
asn1p_ioc_row_new(asn1p_expr_t *oclass) {
	asn1p_ioc_row_t *row;
	asn1p_expr_t *field;
	int columns = 0;

	assert(oclass->expr_type == A1TC_CLASSDEF);

	row = calloc(1, sizeof *row);
	if(!row) return NULL;

	TQ_FOR(field, &oclass->members, next)
		columns++;

	row->column = calloc(columns, sizeof *row->column);
	if(!row->column) {
		free(row);
		return NULL;
	}
	row->columns = columns;

	columns = 0;
	TQ_FOR(field, &oclass->members, next) {
		size_t fieldIdLen = strlen(field->Identifier);
		if(fieldIdLen > row->max_identifier_length)
			row->max_identifier_length = fieldIdLen;
		row->column[columns].field = field;
		row->column[columns].value = NULL;
		columns++;
	}

	return row;
}

void
asn1p_ioc_row_delete(asn1p_ioc_row_t *row) {
	if(row) {
		if(row->column) {
			for(size_t i = 0; i < row->columns; i++) {
				if(!row->column[i].new_ref && row->column[i].value) {
					/* 
					 * Field 'reference' comes from asn1fix_cws.c :
					 * TQ_FIRST(&cell->field->members)->reference
					 * so it should not be freed here.
					 */
					row->column[i].value->reference = NULL;
				}
				asn1p_expr_free(row->column[i].value);
			}
			free(row->column);
		}
		free(row);
	}
}

int
asn1p_ioc_row_match(const asn1p_ioc_row_t *a, const asn1p_ioc_row_t *b) {
    assert(a && b);

    if(a->columns != b->columns)
        return -1;  /* Bad! */

    for(size_t i = 0; i < a->columns; i++) {
        assert(a->column[i].field);
        assert(b->column[i].field);
        if(strcmp(a->column[i].field->Identifier,
                  b->column[i].field->Identifier)
           != 0) {
            return -1;  /* Bad! */
        }
        if((a->column[i].value && !b->column[i].value)
           || (!a->column[i].value && b->column[i].value)) {
            return 1;   /* Not match */
        }
        if(a->column[i].value && b->column[i].value) {
            if(asn1p_expr_compare(a->column[i].value, b->column[i].value)
               != 0) {
                return 1;   /* Not match */
            }
        }
    }

    return 0;
}

struct asn1p_ioc_cell_s *
asn1p_ioc_row_cell_fetch(asn1p_ioc_row_t *row, const char *fieldname) {
	for(size_t i = 0; i < row->columns; i++) {
		if(strcmp(row->column[i].field->Identifier, fieldname) == 0)
			return &row->column[i];
	}
	errno = ESRCH;
	return NULL;
}

asn1p_wsyntx_chunk_t *
asn1p_wsyntx_chunk_new() {
	asn1p_wsyntx_chunk_t *wc;

	wc = calloc(1, sizeof(*wc));

	return wc;
}

void
asn1p_wsyntx_chunk_free(asn1p_wsyntx_chunk_t *wc) {
	if(wc) {
		switch(wc->type) {
		case WC_LITERAL:
		case WC_WHITESPACE:
		case WC_FIELD:
			free(wc->content.token); break;
		case WC_OPTIONALGROUP:
			asn1p_wsyntx_free(wc->content.syntax);
			break;
		}
		free(wc);
	}
}

asn1p_wsyntx_chunk_t *
asn1p_wsyntx_chunk_clone(asn1p_wsyntx_chunk_t *wc) {
	asn1p_wsyntx_chunk_t *nc;

	nc = asn1p_wsyntx_chunk_new();
	if(nc) {
		nc->type = wc->type;
		switch(wc->type) {
		case WC_LITERAL:
		case WC_WHITESPACE:
		case WC_FIELD:
			nc->content.token = malloc(strlen(wc->content.token)+1);
			strcpy(nc->content.token, wc->content.token);
			break;
		case WC_OPTIONALGROUP:
			nc->content.syntax = asn1p_wsyntx_clone(wc->content.syntax);
			break;
		}
	}

	return nc;
}

asn1p_wsyntx_t *
asn1p_wsyntx_new() {
	asn1p_wsyntx_t *wx;

	wx = calloc(1, sizeof(*wx));
	if(wx) {
		TQ_INIT(&(wx->chunks));
	}

	return wx;
}

void
asn1p_wsyntx_free(asn1p_wsyntx_t *wx) {
	if(wx) {
		asn1p_wsyntx_chunk_t *wc;
		while((wc = TQ_REMOVE(&(wx->chunks), next)))
			asn1p_wsyntx_chunk_free(wc);
		free(wx);
	}
}

asn1p_wsyntx_t *
asn1p_wsyntx_clone(asn1p_wsyntx_t *wx) {
	asn1p_wsyntx_t *nw;

	nw = asn1p_wsyntx_new();
	if(nw) {
		asn1p_wsyntx_chunk_t *wc;
		asn1p_wsyntx_chunk_t *nc;
		TQ_FOR(wc, &(wx->chunks), next) {
			nc = asn1p_wsyntx_chunk_clone(wc);
			if(nc) {
				TQ_ADD(&(nw->chunks), nc, next);
			} else {
				asn1p_wsyntx_free(nw);
				return NULL;
			}
		}
	}

	return nw;
}

asn1p_wsyntx_chunk_t *
asn1p_wsyntx_chunk_fromstring(char *token, int do_copy) {
	asn1p_wsyntx_chunk_t *wc;

	if(do_copy) {
		static asn1p_wsyntx_chunk_t tmp;
		tmp.type = WC_LITERAL;
		tmp.content.token = token;
		wc = asn1p_wsyntx_chunk_clone(&tmp);
	} else {
		wc = asn1p_wsyntx_chunk_new();
		if(wc) {
			wc->type = WC_LITERAL;
			wc->content.token = token;
		}
	}

	return wc;
}


asn1p_wsyntx_chunk_t *
asn1p_wsyntx_chunk_fromsyntax(asn1p_wsyntx_t *syntax) {
	asn1p_wsyntx_chunk_t *wc;

	wc = asn1p_wsyntx_chunk_new();
	if(wc) {
		wc->type = WC_OPTIONALGROUP;
		wc->content.syntax = syntax;
		syntax->parent = wc;
	}

	return wc;
}

