package org.ihtsdo.buildcloud.controller.helper;

import org.codehaus.jackson.map.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;

import javax.servlet.http.HttpServletRequest;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;

public class HypermediaGenerator {

	@Autowired
	private ObjectMapper objectMapper;

	public List<Map<String, Object>> getEntityCollectionHypermedia(Collection<?> entities, HttpServletRequest request, String[] entityLinks) {
		return getEntityCollectionHypermedia(entities, request, entityLinks, null);
	}

	public List<Map<String,Object>> getEntityCollectionHypermedia(Collection<?> entities, HttpServletRequest request) {
		return getEntityCollectionHypermedia(entities, request, null, null);
	}

	public List<Map<String, Object>> getEntityCollectionHypermedia(Collection<?> entities, HttpServletRequest request, String[] entityLinks, String instanceRoot) {
		String url = getUrl(request);
		String apiRootUrl = getApiRootUrl(url, request);
		if (instanceRoot != null) {
			url = apiRootUrl + instanceRoot;
		}
		List<Map<String, Object>> entitiesHypermedia = new ArrayList<>();
		for (Object entity : entities) {
			entitiesHypermedia.add(getEntityHypermedia(entity, false, url, apiRootUrl, entityLinks));
		}
		return entitiesHypermedia;
	}

	/**
	 *
	 * @param entity
	 * @param currentResource - if true indicates that the URL already contains the entity id.  If false, the entity will be added.
	 * @param request
	 * @param entityLinks
	 * @return
	 */
	public Map<String, Object> getEntityHypermedia(Object entity, boolean currentResource, HttpServletRequest request, String... entityLinks) {
		String url = getUrl(request);
		String apiRootUrl = getApiRootUrl(url, request);
		return getEntityHypermedia(entity, currentResource, url, apiRootUrl, entityLinks);
	}

	public Map<String, Object> getEntityHypermediaOfAction(Object entity, HttpServletRequest request, String... entityLinks) {
		String url = getUrl(request);
		// Remove action name
		url = url.substring(0, url.lastIndexOf("/"));
		String apiRootUrl = getApiRootUrl(url, request);
		return getEntityHypermedia(entity, true, url, apiRootUrl, entityLinks);
	}

	private Map<String, Object> getEntityHypermedia(Object entity, boolean currentResource, String url, String apiRootUrl, String... entityLinks) {
		@SuppressWarnings("unchecked")
		Map<String,Object> entityMap = objectMapper.convertValue(entity, Map.class);
		if (!currentResource) {
			url = url + "/" + entityMap.get("id");
		}
		if (entityMap != null) {
			entityMap.put("url", url);
			if (entityLinks != null) {
				for (String link : entityLinks) {
					String linkName;
					if (link.contains("|")) {
						String[] linkParts = link.split("\\|");
						linkName = linkParts[0];
						link = linkParts[1];
					} else {
						linkName = link.replace("/", "");
					}
					String linkUrl = (link.startsWith("/") ? apiRootUrl : (url + "/")) + link;
					entityMap.put(linkName + "_url", linkUrl);
				}
			}
		}
		return entityMap;
	}

	private String getUrl(HttpServletRequest request) throws UnsupportedEncodingException {
		String requestUrl = request.getRequestURL().toString();
		requestUrl = URLDecoder.decode(requestUrl, "UTF-8");
		// Remove any trailing slash
		if (requestUrl.lastIndexOf('/') == requestUrl.length() - 1) {
			requestUrl = requestUrl.substring(0, requestUrl.length() - 1);
		}
		return requestUrl;
	}

	private String getApiRootUrl(String url, HttpServletRequest request) {
		String rootPath = request.getContextPath() + request.getServletPath();
		return url.substring(0, url.indexOf(rootPath) + rootPath.length());
	}
	
}

@@ -85,24 +85,81 @@
 jectMapper;%0A
+import org.slf4j.Logger;%0Aimport org.slf4j.LoggerFactory;%0A
 import org.s
@@ -516,16 +516,109 @@
 tMapper;
+%0A%09%0A%09private static final Logger LOGGER =  LoggerFactory.getLogger(HypermediaGenerator.class);
 %0A%0A%09publi
@@ -3350,47 +3350,11 @@
 est)
- throws UnsupportedEncodingException
  %7B%0A
+
 %09%09St
@@ -3403,24 +3403,33 @@
 toString();%0A
+%09%09try %7B%0A%09
 %09%09requestUrl
@@ -3471,16 +3471,117 @@
 TF-8%22);%0A
+%09%09%7D catch (UnsupportedEncodingException e) %7B%0A%09%09%09LOGGER.error(%22request Url can't be decoded%22, e);%0A%09%09%7D%0A
 %09%09// Rem

fix build failures