package com.uas.report.axis;

import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Map;
import java.util.Map.Entry;

public class ResourceHandlerRegistry {

	private Map<String, Class<? extends BasicResourceHandler>> typeHandlers;
	private Map<String, BasicResourceHandler> handlers;
	private Map<String, String> resourceTypes;

	public ResourceHandlerRegistry() throws ClassNotFoundException, InstantiationException, IllegalAccessException {
		init();
	}

	private void initTypeHandlers() {
		typeHandlers = new HashMap<>();
		typeHandlers.put(ResourceDescriptor.TYPE_FOLDER, FolderHandler.class);
		typeHandlers.put(ResourceDescriptor.TYPE_IMAGE, FileResourceHandler.class);
		typeHandlers.put(ResourceDescriptor.TYPE_JRXML, FileResourceHandler.class);
		typeHandlers.put(ResourceDescriptor.TYPE_FONT, FileResourceHandler.class);
		typeHandlers.put(ResourceDescriptor.TYPE_JRXML, FileResourceHandler.class);
		typeHandlers.put(ResourceDescriptor.TYPE_XML, FileResourceHandler.class);
		typeHandlers.put(ResourceDescriptor.TYPE_JAR, FileResourceHandler.class);
		typeHandlers.put(ResourceDescriptor.TYPE_REFERENCE, FileResourceHandler.class);
		typeHandlers.put(ResourceDescriptor.TYPE_UNKNOW, FileResourceHandler.class);
	}

	public void init() throws ClassNotFoundException, InstantiationException, IllegalAccessException {
		initTypeHandlers();
		handlers = new HashMap<>();
		resourceTypes = new HashMap<>();

		for (Iterator<Entry<String, Class<? extends BasicResourceHandler>>> it = typeHandlers.entrySet().iterator(); it
				.hasNext();) {
			Entry<String, Class<? extends BasicResourceHandler>> entry = it.next();
			String wsType = entry.getKey();
			BasicResourceHandler handler = null;

			Class<?> handlerClass = entry.getValue();

			handler = (BasicResourceHandler) handlerClass.newInstance();

			handlers.put(wsType, handler);

			Class<?> resourceType = handler.getResourceType();
			resourceTypes.put(resourceType.getName(), wsType);

		}
	}

	public BasicResourceHandler getHandler(String wsType) throws WSException {
		BasicResourceHandler handler = handlers.get(wsType);
		if (handler == null) {
			throw new WSException(WSException.GENERAL_ERROR, "不支持该类型的资源！");
		}
		return handler;
	}

	public BasicResourceHandler getHandler(Resource resource) throws WSException {
		String resourceType = resource.getResourceType();
		String wsType = resourceTypes.get(resourceType);
		if (wsType == null) {
			synchronized (resourceTypes) {
				// determine a (more generic) type for the resource
				wsType = determineWSType(resource);
				// cache the type
				resourceTypes.put(resourceType, wsType);
			}
		}
		return getHandler(wsType);
	}

	protected String determineWSType(Resource resource) {
		String wsType = null;

		LinkedList<Class<?>> itfQueue = new LinkedList<>();
		Class<?>[] itfs = resource.getClass().getInterfaces();
		for (int i = 0; i < itfs.length; i++) {
			itfQueue.add(itfs[i]);
		}

		while (!itfQueue.isEmpty()) {
			Class<?> itf = itfQueue.removeFirst();
			wsType = resourceTypes.get(itf.getName());
			if (wsType != null) {
				break;
			}

			Class<?>[] interfaces = itf.getInterfaces();
			for (int i = 0; i < interfaces.length; i++) {
				itfQueue.add(interfaces[i]);
			}
		}

		return wsType;
	}

	public boolean typeExtends(String type, String parentType) {
		BasicResourceHandler handler = handlers.get(type);
		Class<?> resourceType = handler.getResourceType();
		BasicResourceHandler parentHandler = handlers.get(parentType);
		Class<?> parentResourceType = parentHandler.getResourceType();
		return parentResourceType.isAssignableFrom(resourceType);
	}

	public Map<String, Class<? extends BasicResourceHandler>> getTypeHandlers() {
		return typeHandlers;
	}

	public void setTypeHandlers(Map<String, Class<? extends BasicResourceHandler>> typeHandlers) {
		this.typeHandlers = typeHandlers;
	}
}
