package org.openmrs.module.uicommons.message;

import org.openmrs.messagesource.MessageSourceService;
import org.openmrs.messagesource.PresentationMessage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.context.request.WebRequest;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.UUID;

/**
 * Integrates with Angular Translate, simply initialize as follows:
 * $translateProvider.useUrlLoader('/' + OPENMRS_CONTEXT_PATH + '/module/uicommons/messages/messages.json')
 */
@Controller
public class MessagesController {

    @Autowired
    private MessageSourceService messageSourceService;

    private static Map<Locale, Map<String,String>> messages;

    private static Set<String> codes;

    private static String eTag;

    @RequestMapping(value = "/module/uicommons/messages/messages.json", method = RequestMethod.GET)
    @ResponseBody
    public ResponseEntity<Map<String,String>> getMessages(@RequestParam("lang") String lang, WebRequest webRequest) {

        // TODO zip?
        // TODO how do we do a refresh on context refreshed (or are controllers refreshed by default?) would this include static methods

        Locale locale = new Locale(lang);

        // create the translation map if we haven't already
        if (messages == null) {
            messages = new HashMap<Locale, Map<String, String>>();
            eTag = UUID.randomUUID().toString();
            initializeKeySet();
        }

        // see if we have this locale
        if (!messages.containsKey(locale)) {
            generateMessagesForLocale(locale);
        }

        String eTagFromClient = webRequest.getHeader("If-None-Match");

        // see if this client already has the right version cached, if so send back not modified
        if (eTagFromClient != null && eTagFromClient.contains(eTag)) {
            return new ResponseEntity<Map<String, String>>(new HashMap<String, String>(), HttpStatus.NOT_MODIFIED);
        }
        // otherwise set eTag and return the codes requested
        else {
            HttpHeaders headers = new HttpHeaders();
            headers.setETag(eTag);
            return new ResponseEntity<Map<String, String>>(messages.get(locale), headers, HttpStatus.OK);
        }

    }

    private void initializeKeySet() {
        codes = new HashSet<String>();
        for (PresentationMessage message : messageSourceService.getPresentations()) {
            codes.add(message.getCode());
        }
    }

    private void generateMessagesForLocale(Locale locale) {
        Map<String,String> m = new HashMap<String, String>();
        for (String code : codes) {
            m.put(code, messageSourceService.getMessage(code, null, locale));
        }
        messages.put(locale, m);
    }

}

@@ -830,31 +830,8 @@
 Set;
-%0Aimport java.util.UUID;
 %0A%0A/*
@@ -1142,23 +1142,16 @@
 private 
-static 
 Map%3CLoca
@@ -1197,23 +1197,16 @@
 private 
-static 
 Set%3CStri
@@ -1233,26 +1233,34 @@
 ate 
-static String
+Map%3CLocale, Integer%3E
  eTag
+s
 ;%0A%0A 
@@ -1519,145 +1519,8 @@
 zip?
-%0A        // TODO how do we do a refresh on context refreshed (or are controllers refreshed by default?) would this include static methods
 %0A%0A  
@@ -1739,37 +1739,40 @@
 eTag
+s
  = 
-UUID.randomUUID().toString
+new HashMap%3CLocale, Integer%3E
 ();%0A
@@ -2190,16 +2190,40 @@
 ins(eTag
+s.get(locale).toString()
 )) %7B%0A   
@@ -2506,16 +2506,40 @@
 Tag(eTag
+s.get(locale).toString()
 );%0A     
@@ -2896,16 +2896,17 @@
 te void 
+ 
 generate
@@ -3159,16 +3159,57 @@
 le, m);%0A
+        eTags.put(locale, m.hashCode());%0A
     %7D%0A%0A%7D

Add Servlet that serves up message codes for Angular Translate Create eTags based on hashcode