package com.google.sps.servlets;

import java.io.IOException;
import com.google.cloud.language.v1.Document;
import com.google.cloud.language.v1.LanguageServiceClient;
import com.google.cloud.language.v1.AnalyzeEntitiesRequest;
import com.google.cloud.language.v1.AnalyzeEntitiesResponse;
import com.google.cloud.language.v1.EncodingType;
import com.google.cloud.language.v1.Entity;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Given a tweet or sentence, the servlet will extract salient terms
 * and store them in a list.
 */
@WebServlet("/keyword")
public class KeywordServlet extends HttpServlet {

  private final List<String> tweets = new ArrayList<>();
  private final TreeMap<Entity, Float> terms = new TreeMap<>((term1, term2) -> {
    if (term1.getSalience() > term2.getSalience()) {
      return 1;
    } else if (term1.getSalience() < term2.getSalience()) {
      return -1;
    } else {
      return 0;
    }
  });

  @Override
  public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
    for (String tweet : tweets) {
      AnalyzeEntitiesResponse entityResponse = analyzeEntity(tweet);
      List<Entity> entities = entityResponse.getEntitiesList();
      for (Entity entity : entities) {
        if (entity.getSalience() == 0) {
          continue;
        }
        
        if (terms.size() < 10) {
          terms.put(entity, entity.getSalience());
        } else if (!terms.containsKey(entity) && entity.getSalience() > terms.get(terms.pollFirstEntry())) {
          terms.remove(terms.pollFirstEntry());
          terms.put(entity, entity.getSalience());
        } else {}
      }
    }

    String json = jsonBuilder(terms);
    response.getWriter().println(json);
  }

  @Override
  public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException {
    final String tweet = request.getParameter("keyword-sentence");
    if (tweet != null && !tweet.equals("")) {
      tweets.add(request.getParameter("keyword-sentence"));
    }
    response.sendRedirect("/index.html");
  }

  /**
   * Generates and returns a JSON usable by Mustache.
   */
  private String jsonBuilder(Map<Entity, Float> toJson) {
    List<String> terms = new ArrayList<>();
    for (Entity term : toJson.keySet()) {
      terms.add(keyValueJson("term", term.getName()));
    }

    // Remove extra comma at the end.
    String keywordPrefix = "{\"keywords\": [";
    return String.format(keywordPrefix + "%s]}", String.join(",", terms));
  }

  /**
   * Given a key-value pair, this function returns "{key: value}".
   */
  private String keyValueJson(String key, String value) {
    return String.format("{\"%s\": \"%s\"}", key, value);
  }

  /**
   * @return a response to the analyze-entity request
   */ 
  private AnalyzeEntitiesResponse analyzeEntity(String message) throws IOException {
    try (LanguageServiceClient language = LanguageServiceClient.create()) {
      Document doc = Document.newBuilder().setContent(message).setType(Document.Type.PLAIN_TEXT).build();
      AnalyzeEntitiesRequest request = AnalyzeEntitiesRequest.newBuilder()
          .setDocument(doc)
          .setEncodingType(EncodingType.UTF16)
          .build();
      AnalyzeEntitiesResponse response = language.analyzeEntities(request);
      language.close();
      return response;
    }
  }
}


@@ -1024,16 +1024,69 @@
 2) -%3E %7B%0A
+    // Sort the Entity keys by their salience scores%0A
     if (
@@ -1664,42 +1664,346 @@
     
- %0A        if (terms.size() %3C 10) %7B
+%0A        // We are only looking at (at most) the 10 most salient keywords. %0A        if (terms.size() %3C 10) %7B%0A          if (terms.containsKey(entity)) %7B  // Keep the max salience score if the term already exists in the map.%0A            terms.put(entity, Math.max(entity.getSalience(), terms.get(entity)));%0A            continue;%0A          %7D
 %0A   
@@ -2309,17 +2309,24 @@
  json = 
-j
+keywordJ
 sonBuild
@@ -2795,24 +2795,38 @@
 private 
-String j
+static String keywordJ
 sonBuild
@@ -2963,411 +2963,131 @@
 add(
-keyValueJson(%22term%22, term.getName()));%0A    %7D%0A%0A    // Remove extra comma at the end.%0A    String keywordPrefix = %22%7B%5C%22keywords%5C%22: %5B%22;%0A    return String.format(keywordPrefix + %22%25s%5D%7D%22, String.join(%22,%22, terms));%0A  %7D%0A%0A  /**%0A   * Given a key-value pair, this function returns %22%7Bkey: value%7D%22.%0A   */%0A  private String keyValueJson(String key, String value) %7B%0A    return String.format(%22%7B%5C%22%25s%5C%22: %5C%22%25s%5C%22%7D%22, key, value
+String.format(%22%7B%5C%22term%5C%22: %5C%22%25s%5C%22%7D%22, term));%0A    %7D%0A%0A    return String.format(%22%7B%5C%22keywords%5C%22: %5B%25s%5D%7D%22, String.join(%22,%22, terms)
 );%0A 

Fix nit, shorten code