package com.twilio.survey.controllers;

import com.twilio.survey.Server;
import com.twilio.survey.models.Question;
import com.twilio.survey.models.Response;
import com.twilio.survey.models.SurveyService;
import com.twilio.survey.models.Survey;
import com.twilio.survey.models.IncomingCall;
import com.twilio.sdk.verbs.Gather;
import com.twilio.sdk.verbs.Record;
import com.twilio.sdk.verbs.Say;
import com.twilio.sdk.verbs.TwiMLException;
import com.twilio.sdk.verbs.TwiMLResponse;

import freemarker.cache.ClassTemplateLoader;
import freemarker.template.Configuration;

import com.google.gson.Gson;

import spark.ModelAndView;
import spark.Route;
import spark.Spark;
import spark.template.freemarker.FreeMarkerEngine;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.HashMap;
import java.util.Map;

public class SurveyController {
  private static SurveyService surveys = new SurveyService(Server.config.getMongoURI());
  private static FreeMarkerEngine templateEngine;

  // Configure and attach FreeMarker template engine to the class variable for easy access in route
  // definitions.
  public static void initializeTemplateEngine() {
    templateEngine = new FreeMarkerEngine();
    Configuration freeMarkerConfig = new Configuration();
    freeMarkerConfig.setTemplateLoader(new ClassTemplateLoader(SurveyService.class, "/"));
    templateEngine.setConfiguration(freeMarkerConfig);
  };

  // Render landing page.
  public static Route index = (req, res) -> {
    initializeTemplateEngine();

    // Create template keys/values
      Map<String, Object> templateValues = new HashMap<>();
      templateValues.put("greeting", "Ahoy hoy!");

      return templateEngine.render(new ModelAndView(templateValues, "index.ftl"));
    };

  // Main interview loop.
  public static Route interview = (request, response) -> {
    IncomingCall call = new IncomingCall(parseBody(request.body()));
    TwiMLResponse twiml = new TwiMLResponse();
    Survey existingSurvey = surveys.getSurvey(call.getFrom());
    if (existingSurvey == null) {
      Survey survey = surveys.createSurvey(call.getFrom());
      twiml.append(new Say("Thanks for taking our survey."));
      continueSurvey(survey, twiml);
    } else {
      existingSurvey.appendResponse(new Response(call.getInput()));
      surveys.updateSurvey(existingSurvey);
      continueSurvey(existingSurvey, twiml);
    }
    return twiml.toXML();
  };

  // Helper methods
  private static String continueSurvey(Survey survey, TwiMLResponse twiml)
      throws TwiMLException {
    Question q = Server.config.getQuestions()[survey.getIndex()];
    Say say = new Say(q.getText());
    twiml.append(say);
    switch (q.getType()) {
      case "text":
        Record text = new Record();
        text.setFinishOnKey("#");
        twiml.append(text);
        break;
      case "boolean":
        Gather booleanGather = new Gather();
        booleanGather.setNumDigits(1);
        twiml.append(booleanGather);
        break;
      case "number":
        Gather numberGather = new Gather();
        numberGather.setNumDigits(3);
        twiml.append(numberGather);
        break;
    }
    return twiml.toXML();
  }
  public static Map<String, String> parseBody(String body) throws UnsupportedEncodingException {
    String[] unparsedParams = body.split("&");
    Map<String, String> parsedParams = new HashMap<String, String>();
    for (int i=0; i<unparsedParams.length; i++) {
      String[] param = unparsedParams[i].split("=");
      if (param.length == 2) {
        parsedParams.put(URLDecoder.decode(param[0], "utf-8"), URLDecoder.decode(param[1], "utf-8"));
      }
      else if (param.length == 1){
        parsedParams.put(URLDecoder.decode(param[0], "utf-8"), "");
      }
    }
    return parsedParams;
  }
}

@@ -2240,16 +2240,46 @@
   %7D else
+ if (!existingSurvey.isDone())
  %7B%0A     
@@ -2426,24 +2426,129 @@
 ey, twiml);%0A
+    %7D else %7B%0A      twiml.append(new Say(%22Your responses have been recorded. Thank you for your time!%22));%0A
     %7D%0A    re
@@ -2667,22 +2667,16 @@
 e twiml)
-%0A     
  throws 
@@ -2875,134 +2875,494 @@
     
-Record text = new Record();%0A        text.setFinishOnKey(%22#%22);%0A        twiml.append(text);%0A        break;%0A      case %22boolean%22:
+Say textInstructions =%0A            new Say(%22Your response will be recorded after the tone. %22%0A                + %22Once you have finished recording, press the # key.%22);%0A        twiml.append(textInstructions);%0A        Record text = new Record();%0A        text.setFinishOnKey(%22#%22);%0A        twiml.append(text);%0A        break;%0A      case %22boolean%22:%0A        Say boolInstructions =%0A        new Say(%22Press 1 to respond 'true,' and press 2 to respond 'false.'%22);%0A    twiml.append(boolInstructions);
 %0A   
@@ -3515,16 +3515,157 @@
 umber%22:%0A
+        Say numInstructions =%0A        new Say(%22Enter the number on your keypad, followed by the # key.%22);%0A    twiml.append(numInstructions);%0A
         
@@ -3825,16 +3825,17 @@
 ();%0A  %7D%0A
+%0A
   public
@@ -4058,14 +4058,18 @@
 nt i
-=
+ = 
 0; i
-%3C
+ %3C 
 unpa
@@ -4190,32 +4190,45 @@
     parsedParams
+%0A            
 .put(URLDecoder.
@@ -4300,22 +4300,16 @@
 %0A      %7D
-%0A     
  else if
@@ -4328,16 +4328,17 @@
 th == 1)
+ 
 %7B%0A      

Enhance survey instructions.