package cokr.xit.fims.task;

import java.lang.reflect.Method;
import java.util.List;
import java.util.Set;

import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.lang.Nullable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo.BuilderConfiguration;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

import cokr.xit.fims.FimsConf;

public class TaskRequestMappingHandlerMapping extends RequestMappingHandlerMapping {
	@Override
	@Nullable
	public RequestMappingInfo getMappingForMethod(Method method, Class<?> handlerType) {
		if (!FimsConf.get().isUrlPrefixedWithTask())
			return super.getMappingForMethod(method, handlerType);

		RequestMappingInfo info = super.getMappingForMethod(method, handlerType);
		Task task = AnnotatedElementUtils.findMergedAnnotation(method, Task.class);

		return task != null && info != null ?
			createRequestMappingInfo(task, method, info) :
			info;

	}

	protected RequestMappingInfo createRequestMappingInfo(Task task, Method method, RequestMappingInfo info) {
		List<String> tasks = FimsConf.get().getTasks();

		String[] prefix = task.value();
		String first = prefix[0];
		if ("ALL".equals(first)) {
			prefix = tasks.toArray(new String[tasks.size()]);
		} else if ("CMN".equals(first)) {
			String[] tasksArray = tasks.toArray(new String[tasks.size()]);
			prefix = new String[1 + tasksArray.length];
			System.arraycopy(new String[] {""}, 0, prefix, 0, 1);
			System.arraycopy(tasksArray, 0, prefix, 1, tasksArray.length);
		}

		RequestMapping rm = AnnotatedElementUtils.findMergedAnnotation(method, RequestMapping.class);

		Set<String> olds0 = info.getPatternValues();
		String[] olds = olds0.toArray(new String[olds0.size()]);
		String[] news = new String[prefix.length * olds.length];
		for (int i = 0; i < prefix.length; i++) {
			for (int j = 0; j < olds.length; j++) {
				String newPattern = (prefix[i].equals("") ? "" : "/") + prefix[i] + olds[j];
				news[i * (olds.length) + j] = newPattern;
			}
		}

		BuilderConfiguration bc = new RequestMappingInfo.BuilderConfiguration();
		bc.setContentNegotiationManager(super.getContentNegotiationManager());
		bc.setPatternParser(super.getPatternParser());

		return RequestMappingInfo
			.paths(super.resolveEmbeddedValuesInPatterns(news))
			.mappingName(rm.name())
			.methods(rm.method())
			.params(rm.params())
			.headers(rm.headers())
			.consumes(rm.consumes())
			.produces(rm.produces())
			.options(bc)
			.build();
	}
}