package com.google.step.coffee.servlets;

import com.google.step.coffee.*;
import com.google.step.coffee.data.RequestStore;
import com.google.step.coffee.entity.ChatRequest;
import com.google.step.coffee.entity.ChatRequestBuilder;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/** Servlet to manage user requests for a chat. */
@WebServlet("/api/chat-request")
public class ChatRequestServlet extends JsonServlet {

  private RequestStore requestStore = new RequestStore();

  @Override
  public Object post(JsonServletRequest request) throws IOException, HttpError {
    PermissionChecker.ensureLoggedIn();

    if (OAuthService.userHasAuthorised(UserManager.getCurrentUserId())) {
      ChatRequest chatRequest = buildChatRequestFromHttpRequest(request);

      requestStore.addRequest(chatRequest);

      return "Success";
    } else {
      throw new HttpError(HttpServletResponse.SC_UNAUTHORIZED,
          "Please authorise app to schedule chat");
    }
  }

  private ChatRequest buildChatRequestFromHttpRequest(HttpServletRequest request) throws HttpError {
    List<String> tags = getParameterValues("tags", request);
    List<String> startDateStrings = getParameterValues("startDates", request);
    List<String> endDateStrings = getParameterValues("endDates", request);
    int minPeople = parseIntParam("minPeople", request);
    int maxPeople = parseIntParam("maxPeople", request);
    int durationMins = parseIntParam("durationMins", request);
    boolean matchRandom = parseBooleanParam("matchRandom", request, "false");
    boolean matchRecents = parseBooleanParam("matchRecents", request, "true");

    List<Date> startDates = startDateStrings.stream()
        .map(Long::parseLong)
        .map(Date::new)
        .collect(Collectors.toList());

    List<Date> endDates = endDateStrings.stream()
        .map(Long::parseLong)
        .map(Date::new)
        .collect(Collectors.toList());

    if (startDates.size() != endDates.size()) {
      throw new HttpError(HttpServletResponse.SC_BAD_REQUEST, "Mismatched date ranges");
    }

    return new ChatRequestBuilder()
        .withTags(tags)
        .onDates(startDates, endDates)
        .withGroupSize(minPeople, maxPeople)
        .withMaxChatLength(durationMins)
        .willMatchRandomlyOnFail(matchRandom)
        .willMatchWithRecents(matchRecents)
        .forUser(UserManager.getCurrentUserId())
        .build();
  }

  private String getParameterOrDefault(String name, HttpServletRequest req, String defaultValue) {
    String paramString = req.getParameter(name);
    return (paramString != null) ? paramString : defaultValue;
  }

  private String getParameter(String name, HttpServletRequest req) throws HttpError {
    String paramString = req.getParameter(name);
    if (paramString != null) {
      return paramString;
    } else {
      throw new HttpError(HttpServletResponse.SC_BAD_REQUEST, "Missing parameter: " + name);
    }
  }

  private List<String> getParameterValues(String name, HttpServletRequest req) {
    String paramString = req.getParameter(name);
    if (paramString == null || paramString.equals("")) {
      return new ArrayList<>();
    }

    return Arrays.asList(paramString.split(","));
  }

  private Integer parseIntParam(String name, HttpServletRequest req) throws HttpError {
    String paramString = getParameter(name, req);

    try {
      return Integer.parseInt(paramString);
    } catch (NumberFormatException e) {
      throw new HttpError(HttpServletResponse.SC_BAD_REQUEST,
          "Invalid integer parameter: " + name);
    }
  }

  private boolean parseBooleanParam(String name, HttpServletRequest req, String defaultValue) {
    String paramString = getParameterOrDefault(name, req, defaultValue);

    return Boolean.parseBoolean(paramString);
  }
}

@@ -1879,16 +1879,71 @@
 st%3CDate%3E
+ startDates;%0A    List%3CDate%3E endDates;%0A%0A    try %7B%0A      
  startDa
@@ -1974,32 +1974,34 @@
 tream()%0A        
+  
 .map(Long::parse
@@ -2006,32 +2006,34 @@
 seLong)%0A        
+ 
+ 
 .map(Date::new)%0A
@@ -2024,32 +2024,34 @@
 .map(Date::new)%0A
+  
         .collect
@@ -2074,34 +2074,25 @@
 st());%0A%0A    
-List%3CDate%3E
+ 
  endDates = 
@@ -2115,32 +2115,34 @@
 tream()%0A        
+  
 .map(Long::parse
@@ -2147,32 +2147,34 @@
 seLong)%0A        
+ 
+ 
 .map(Date::new)%0A
@@ -2165,32 +2165,34 @@
 .map(Date::new)%0A
+  
         .collect
@@ -2209,24 +2209,160 @@
 s.toList());
+%0A    %7D catch (NumberFormatException e) %7B%0A      throw new HttpError(HttpServletResponse.SC_BAD_REQUEST, %22Invalid date timestamp.%22);%0A    %7D
 %0A%0A    if (st

Handle erroneous date timestamps when parsing ranges from ChatRequestServlet