#include "asn1fix_internal.h"
#include "asn1fix_constraint.h"
#include "asn1fix_crange.h"

static void _remove_exceptions(arg_t *arg, asn1p_constraint_t *ct);
static int constraint_value_resolve(arg_t *arg, asn1p_module_t *mod, asn1p_value_t **value, enum asn1p_constraint_type_e real_ctype);

int
asn1constraint_pullup(arg_t *arg) {
	asn1p_expr_t *expr = arg->expr;
	asn1p_constraint_t *ct_parent;
	asn1p_constraint_t *ct_expr;
	int ret;

	if(expr->combined_constraints)
		return 0;	/* Operation already performed earlier */

	switch(expr->meta_type) {
	case AMT_TYPE:
	case AMT_TYPEREF:
		break;
	default:
		return 0;	/* Nothing to do */
	}

	if(expr->expr_type == A1TC_REFERENCE) {
		asn1p_ref_t *ref = expr->reference;
		asn1p_expr_t *parent_expr;

		assert(ref);
		parent_expr = asn1f_lookup_symbol(arg, expr->module, ref);
		if(!parent_expr) {
			if(errno != EEXIST) {
				DEBUG("\tWhile fetching parent constraints: "
					"type \"%s\" not found: %s",
					asn1f_printable_reference(ref),
					strerror(errno));
				return -1;
			} else {
				/*
				 * -fknown-extern-type is given.
				 * Assume there are no constraints there.
				 */
				WARNING("External type \"%s\": "
					"assuming no constraints",
					asn1f_printable_reference(ref));
				ct_parent = 0;
			}
		} else {
			arg->expr = parent_expr;
			ret = asn1constraint_pullup(arg);
			arg->expr = expr;
			if(ret) return ret;

			ct_parent = parent_expr->combined_constraints;
		}
	} else {
		ct_parent = 0;
	}

	ct_expr = expr->constraints;

	if(!ct_parent && !ct_expr)
		return 0;	/* No constraints to consider */

	if(ct_parent) {
		ct_parent = asn1p_constraint_clone(ct_parent);
		assert(ct_parent);
	}

	/*
	 * If the current type does not have constraints, it inherits
	 * the constraints of a parent.
	 */
	if(ct_parent && !ct_expr) {
		expr->combined_constraints = ct_parent;
		return 0;
	}

	ct_expr = asn1p_constraint_clone(ct_expr);
	assert(ct_expr);

	/*
	 * Now we have a set of current expression's constraints,
	 * and an optional set of the parent expression's constraints.
	 */

	if(ct_parent) {
		/*
		 * If we have a parent, remove all the extensions (46.4).
		 */
		_remove_exceptions(arg, ct_parent);

		expr->combined_constraints = ct_parent;
		if(ct_expr->type == ACT_CA_SET) {
			unsigned int i;
			for(i = 0; i < ct_expr->el_count; i++) {
				if(asn1p_constraint_insert(
					expr->combined_constraints,
						ct_expr->elements[i])) {
					expr->combined_constraints = 0;
					asn1p_constraint_free(ct_expr);
					asn1p_constraint_free(ct_parent);
					return -1;
				} else {
					ct_expr->elements[i] = 0;
				}
			}
			asn1p_constraint_free(ct_expr);
		} else {
			asn1p_constraint_insert(expr->combined_constraints,
				ct_expr);
		}
	} else {
		expr->combined_constraints = ct_expr;
	}

	return 0;
}

int
asn1constraint_resolve(arg_t *arg, asn1p_module_t *mod, asn1p_constraint_t *ct, asn1p_expr_type_e etype, enum asn1p_constraint_type_e effective_type) {
	enum asn1p_constraint_type_e real_constraint_type;
	unsigned int el;
	int rvalue = 0;
	int ret;

	DEBUG("(\"%s\")", arg->expr->Identifier);

	if(!ct) return 0;

	/* Don't touch information object classes */
	switch(ct->type) {
	case ACT_CT_SIZE:
	case ACT_CT_FROM:
		if(effective_type && effective_type != ct->type) {
			FATAL("%s at line %d: "
				"Incompatible nested %s within %s",
				arg->expr->Identifier, ct->_lineno,
				asn1p_constraint_type2str(ct->type),
				asn1p_constraint_type2str(effective_type)
			);
		}
		effective_type = ct->type;
		break;
	case ACT_CT_WCOMP:
	case ACT_CT_WCOMPS:
	case ACT_CA_CRC:
		return 0;
	default:
		break;
	}

	real_constraint_type = effective_type ? effective_type : ct->type;

	if(etype != A1TC_INVALID) {

		ret = asn1constraint_compatible(etype, real_constraint_type);
		switch(ret) {
		case -1:	/* If unknown, assume OK. */
		case  1:
			break;
		case 0:
			if(effective_type == ACT_CT_SIZE
			&& (arg->flags & A1F_EXTENDED_SizeConstraint))
				break;
		default:
			FATAL("%s at line %d: "
				"Constraint type %s is not applicable to %s",
				arg->expr->Identifier, ct->_lineno,
				asn1p_constraint_type2str(real_constraint_type),
				ASN_EXPR_TYPE2STR(etype)
			);
			rvalue = -1;
			break;
		}
	} else {
		WARNING("%s at line %d: "
			"Constraints ignored: Unresolved parent type",
			arg->expr->Identifier, arg->expr->_lineno);
	}

	/*
	 * Resolve all possible references, wherever they occur.
	 */
	if(ct->value && ct->value->type == ATV_REFERENCED) {
		ret = constraint_value_resolve(arg, mod,
			&ct->value, real_constraint_type);
		RET2RVAL(ret, rvalue);
	}
	if(ct->range_start && ct->range_start->type == ATV_REFERENCED) {
		ret = constraint_value_resolve(arg, mod,
			&ct->range_start, real_constraint_type);
		RET2RVAL(ret, rvalue);
	}
	if(ct->range_stop && ct->range_stop->type == ATV_REFERENCED) {
		ret = constraint_value_resolve(arg, mod,
			&ct->range_stop, real_constraint_type);
		RET2RVAL(ret, rvalue);
	}

	/*
	 * Proceed recursively.
	 */
	for(el = 0; el < ct->el_count; el++) {
		ret = asn1constraint_resolve(arg, mod, ct->elements[el],
			etype, effective_type);
		RET2RVAL(ret, rvalue);
	}

	return rvalue;
}

static void
_remove_exceptions(arg_t *arg, asn1p_constraint_t *ct) {
	unsigned int i;

	for(i = 0; i < ct->el_count; i++) {
		if(ct->elements[i]->type == ACT_EL_EXT)
			break;
		_remove_exceptions(arg, ct->elements[i]);
	}

	/* Remove the elements at and after the extensibility mark */
	for(; i < ct->el_count; ct->el_count--) {
		asn1p_constraint_t *rm;
		rm = ct->elements[ct->el_count-1];
		asn1p_constraint_free(rm);
	}

	if(i < ct->el_size)
		ct->elements[i] = 0;
}


static int
constraint_value_resolve(arg_t *arg, asn1p_module_t *mod,
	asn1p_value_t **value, enum asn1p_constraint_type_e real_ctype) {
	asn1p_expr_t static_expr;
	arg_t tmp_arg;
	int rvalue = 0;
	int ret;

	(void)mod;

	DEBUG("(\"%s\", within <%s>)",
		asn1f_printable_value(*value),
		asn1p_constraint_type2str(real_ctype));

	static_expr = *arg->expr;
	static_expr.value = *value;
	static_expr.meta_type = AMT_VALUE;
	tmp_arg = *arg;
	tmp_arg.mod = arg->expr->module;
	tmp_arg.expr = &static_expr;
	ret = asn1f_value_resolve(&tmp_arg, &static_expr, &real_ctype);
	RET2RVAL(ret, rvalue);
	assert(static_expr.value);
	*value = static_expr.value;

	return rvalue;
}
