package de.faustedition.template;

import com.google.common.base.Functions;
import com.google.common.base.Preconditions;
import com.google.common.base.Throwables;
import com.google.common.collect.Lists;
import de.faustedition.FaustURI;
import de.faustedition.text.TextManager;
import freemarker.template.Configuration;
import freemarker.template.Template;
import org.restlet.data.*;
import org.restlet.engine.util.ConnegUtils;
import org.restlet.ext.freemarker.TemplateRepresentation;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.*;

@Component
public class TemplateRepresentationFactory {
	private static final List<Language> SUPPORTED_LANGUAGES = Collections.unmodifiableList(//
			Lists.newArrayList(new Language("de"), new Language("en")));

	@Autowired
	private Configuration configuration;

	@Autowired
	private TextManager textManager;

	@Autowired
	private Logger logger;

	public TemplateRepresentation create(String path, ClientInfo client) throws IOException {
		return create(path, client, new HashMap<String, Object>());
	}

	public TemplateRepresentation create(String path, ClientInfo client, Map<String, Object> model) {
		final Language language = getPreferredMetadata(SUPPORTED_LANGUAGES, client.getAcceptedLanguages());
		final Locale locale = (language == null ? Locale.GERMAN : new Locale(language.getName()));

		Template template;
		try {
			logger.debug("Getting template for " + path + " with locale " + locale);
			template = configuration.getTemplate(path + ".ftl", locale);
			Preconditions.checkNotNull(template, "Cannot find template for " + path);
		} catch (IOException e) {
			throw Throwables.propagate(e);
		}

		model.put("roles", Lists.transform(client.getRoles(), Functions.toStringFunction()));
		
		final ResourceBundle messages = ResourceBundle.getBundle("messages", locale);
		logger.debug("Putting message resource bundle '" + messages.getLocale() + "' into model (requested locale " + locale + ")");
		model.put("message", messages);

		final SortedMap<String, String> textTableOfContents = new TreeMap<String, String>();
		for (Map.Entry<FaustURI, String> tocEntry : textManager.tableOfContents().entrySet()) {
			final String textUriPath = tocEntry.getKey().getPath();
			final String textName = textUriPath.substring("/text/".length(), textUriPath.length() - ".xml".length());
			textTableOfContents.put(textName, tocEntry.getValue());
		}
		model.put("textToc", textTableOfContents);

		TemplateRepresentation representation = new TemplateRepresentation(template, model, MediaType.TEXT_HTML);
		representation.setLanguages(Collections.singletonList(language));

		return representation;
	}

	public static class TextTableOfContentsEntry {
		private final String path;
		private final String title;

		public TextTableOfContentsEntry(String path, String title) {
			this.path = path;
			this.title = title;
		}

		public String getPath() {
			return path;
		}

		public String getTitle() {
			return title;
		}
	}

	/**
	 * Copied from {@link ConnegUtils#getPreferredMetadata(List, List)} and
	 * patched to correctly update <code>maxQuality</code>.
	 * 
	 * @see ConnegUtils#getPreferredMetadata(List, List)
	 */
	private static <T extends Metadata> T getPreferredMetadata(List<T> supported, List<Preference<T>> preferences) {
		T result = null;
		float maxQuality = 0;

		if (supported != null) {
			for (Preference<T> pref : preferences) {
				if (supported.contains(pref.getMetadata()) && (pref.getQuality() > maxQuality)) {
					result = pref.getMetadata();
					// was not updated in original method
					maxQuality = pref.getQuality();
				}
			}
		}

		return result;
	}
}

@@ -499,24 +499,56 @@
 f4j.Logger;%0A
+import org.slf4j.LoggerFactory;%0A
 import org.s
@@ -598,16 +598,16 @@
 owired;%0A
-
 import o
@@ -753,16 +753,114 @@
 ctory %7B%0A
+%09private static final Logger LOG = LoggerFactory.getLogger(TemplateRepresentationFactory.class);%0A%0A
 %09private
@@ -1109,45 +1109,8 @@
 r;%0A%0A
-%09@Autowired%0A%09private Logger logger;%0A%0A
 %09pub
@@ -1589,22 +1589,51 @@
 ry %7B%0A%09%09%09
-logger
+if (LOG.isDebugEnabled()) %7B%0A%09%09%09%09LOG
 .debug(%22
@@ -1657,36 +1657,31 @@
 for 
-%22 + path + %22 with locale %22 +
+%7B%7D (locale: %7B%7D)%22, path,
  loc
@@ -1686,16 +1686,21 @@
 ocale);%0A
+%09%09%09%7D%0A
 %09%09%09templ
@@ -2076,20 +2076,48 @@
 ;%0A%09%09
-logger.debug
+if (LOG.isTraceEnabled()) %7B%0A%09%09%09LOG.trace
 (%22Pu
@@ -2225,16 +2225,20 @@
 + %22)%22);%0A
+%09%09%7D%0A
 %09%09model.

remove dependency on common logger