package it.mice.voila.runtime.validator;

import java.lang.annotation.Annotation;
import java.security.AccessController;
import java.util.Arrays;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;

import javax.validation.groups.Default;

import org.hibernate.validator.util.GetAnnotationParameter;
import org.springframework.validation.Errors;

public class ValidatorUtils {
	private static final String prefix = "label.";
	private static final String GROUPS = "value";

	public static String[] getCodes(String objectName, String field) {
		List<String> codes = new LinkedList<String>();
		addCode(objectName + Errors.NESTED_PATH_SEPARATOR + field, codes);
		addCode(field, codes);
		String fixedField = field;
		if (field.contains("NullSafe") || field.contains("FilterFrom") || field.contains("FilterTo")) {
			fixedField = field.replaceAll("NullSafe", "");
			fixedField = fixedField.replaceAll("FilterFrom", "");
			fixedField = fixedField.replaceAll("FilterTo", "");
			addCode(fixedField, codes);
		}
		int pos = fixedField.indexOf(".") + 1;
		while (pos > 0) {
			fixedField = fixedField.substring(pos);
			addCode(fixedField, codes);
			pos = fixedField.indexOf(".") + 1;
		}
		
		return codes.toArray(new String[codes.size()]);
	}

	public static void addCode(String field, List<String> codes) {
		codes.add(prefix + field);
	}

	public static Set<Class<?>> buildGroupSet(Annotation annotation, Class<?> implicitGroup) {
		Set<Class<?>> groupSet = new HashSet<Class<?>>();
		final Class<?>[] groupsFromAnnotation;
		GetAnnotationParameter<Class[]> action = GetAnnotationParameter.action( annotation, GROUPS, Class[].class );
		if ( System.getSecurityManager() != null ) {
			groupsFromAnnotation = AccessController.doPrivileged( action );
		}
		else {
			groupsFromAnnotation = action.run();
		}
		if ( groupsFromAnnotation.length == 0 ) {
			groupSet.add( Default.class );
		}
		else {
			groupSet.addAll( Arrays.asList( groupsFromAnnotation ) );
		}

		// if the constraint is part of the Default group it is automatically part of the implicit group as well
		if ( implicitGroup != null && groupSet.contains( Default.class ) ) {
			groupSet.add( implicitGroup );
		}
		return groupSet;
	}

}
