/*
 * Copyright (C) 2018 Google Inc. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
 * in compliance with the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License
 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing permissions and limitations under
 * the License.
 */
package com.google.rbm.samples.servlets;

// [START callback servlet]

// [START import_libraries]
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.rbm.samples.BonjourRailBot;
import com.google.rbm.samples.lib.RbmApiHelper;

import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Base64;
import java.util.Properties;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;
import java.util.stream.Collectors;
// [END import_libraries]

/**
 * Servlet for Pub/Sub push request callback.
 *
 * JSON data is posted to /callback, parsed and passed to the Bonjour Rail bot message handler.
 */
@WebServlet(name = "BonjourRailCallback", value = "/callback")
public class BonjourRailCallback extends HttpServlet {
    private static final Logger logger = Logger.getLogger(BonjourRailCallback.class.getName());

    private ScheduledExecutorService backgroundExecutor;

    public BonjourRailCallback() {
        super();
    }

    @Override
    public void doPost(HttpServletRequest request, HttpServletResponse response)
            throws IOException {
        // check to see that this is a post
        if ("POST".equalsIgnoreCase(request.getMethod())) {// read the JSON data from the post body
            String jsonResponse = request.getReader().lines().collect(
                    Collectors.joining(System.lineSeparator())
            );

            logger.info(jsonResponse);

            // load the JSON string into a Json parser
            JsonObject obj = JsonParser.parseString​(jsonResponse).getAsJsonObject();

            // URL validation check
            if (obj.has("secret")) { 
                response.getWriter().println("{\"secret\": \"" + obj.get("secret").toString() + "\"}");
                response.getWriter().flush();
            }
            else if (obj.has("message")) { // make sure there is a message parameter
                obj = obj.get("message").getAsJsonObject();

                // check to see that the message parameter has data
                if (obj.has("data")) {
                    // get the base64 encodded response
                    String encodedResponse = obj.get("data").getAsString();

                    // decode the response
                    byte decodedResponse[] = Base64.getDecoder().decode(encodedResponse);

                    // convert the decoded bytes into a string
                    String decodedJsonResponse = new String(decodedResponse, "UTF-8");

                    // convert JSON response into an object
                    obj = JsonParser.parseString​(decodedJsonResponse).getAsJsonObject();

                    logger.info(obj.toString());

                    // make sure the Json object contains response text, either plaintext
                    // or a suggested response object
                    if (obj.has("text") || obj.has("suggestionResponse")) {
                        logger.info("handling response");

                        String userResponseText = "";
                        if (obj.has("text")) {
                            userResponseText = obj.get("text").getAsString();
                        }

                        if (obj.has("suggestionResponse")) {
                            userResponseText = obj
                                    .get("suggestionResponse")
                                    .getAsJsonObject()
                                    .get("postbackData")
                                    .getAsString();
                        }

                        logger.info("userResponseText: " + userResponseText);

                        if (userResponseText.length() > 0) {
                            String senderPhoneNumber = obj.get("senderPhoneNumber").getAsString();
                            String messageId = obj.get("messageId").getAsString();

                            final String responseForBackgroundThread = userResponseText;

                            // create a background thread to run the Bonjour Rail bot, this way
                            // the process of handling the response is non-blocking
                            backgroundExecutor = Executors.newSingleThreadScheduledExecutor();
                            backgroundExecutor.schedule(new Runnable() {
                                @Override
                                public void run() {
                                    // create an instance of the RBM API helper
                                    RbmApiHelper rbmApiHelper = new RbmApiHelper();

                                    // let the user know we received and read the message
                                    rbmApiHelper.sendReadMessage(messageId, senderPhoneNumber);

                                    // create instance of the bot
                                    BonjourRailBot bonjourRailBot
                                            = new BonjourRailBot(senderPhoneNumber);

                                    // forward the response to the bot handler
                                    bonjourRailBot.handleResponse(responseForBackgroundThread);
                                }
                            }, 0, TimeUnit.HOURS);
                        }
                    }
                }
            }
        }
    }
}
// [END callback servlet]