#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);

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) {
	unsigned int el;
	int rvalue = 0;
	int ret;

	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;
	}

	if(etype != A1TC_INVALID) {
		enum asn1p_constraint_type_e check_type;

		check_type = effective_type ? effective_type : ct->type;

		ret = asn1constraint_compatible(etype, check_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(check_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);
		RET2RVAL(ret, rvalue);
	}
	if(ct->range_start && ct->range_start->type == ATV_REFERENCED) {
		ret = _constraint_value_resolve(arg, mod, &ct->range_start);
		RET2RVAL(ret, rvalue);
	}
	if(ct->range_stop && ct->range_stop->type == ATV_REFERENCED) {
		ret = _constraint_value_resolve(arg, mod, &ct->range_stop);
		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) {
	asn1p_expr_t static_expr;
	asn1p_expr_t *tmp_expr;
	arg_t tmp_arg;
	int rvalue = 0;
	int ret;

	tmp_expr = asn1f_lookup_symbol(arg, mod, (*value)->value.reference);
	if(tmp_expr == NULL) {
		FATAL("Cannot find symbol %s (%s) "
			"used in %s subtype constraint at line %d",
			asn1f_printable_reference((*value)->value.reference),
			mod->Identifier,
			arg->expr->Identifier,
			arg->expr->_lineno);
		assert((*value)->type == ATV_REFERENCED);
		return -1;
	}

	static_expr = *tmp_expr;
	static_expr.value = *value;
	tmp_arg = *arg;
	tmp_arg.mod = tmp_expr->module;
	tmp_arg.expr = &static_expr;
	ret = asn1f_fix_dereference_values(&tmp_arg);
	RET2RVAL(ret, rvalue);
	assert(static_expr.value);
	*value = static_expr.value;

	return rvalue;
}
