// Copyright 2020 Google LLC
//
// 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
//
//     https://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.step.YOUR_PROJECT_NAME_HERE.servlets;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URLEncoder;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.json.JSONObject;

/** Servlet that handles searches. */
@WebServlet("/search")
public class SearchServlet extends HttpServlet {

  private static final String W3_CSE_ID = "INSERT_W3SCHOOL_CSE_ID";
  private static final String STACK_CSE_ID = "INSERT_STACKOVERFLOW_CSE_ID";
  private static final String GEEKS_CSE_ID = "INSERT_GEEKSFORGEEKS_CSE_ID";
  private static final String API_KEY = "INSERT_API_KEY";
  private static final String CSE_URL = "https://www.googleapis.com/customsearch/v1";

  private final HttpClient httpClient =
      HttpClient.newBuilder().version(HttpClient.Version.HTTP_2).build();

  private static String encodeValue(String value) {
    try {
      return URLEncoder.encode(value, StandardCharsets.UTF_8.toString());
    } catch (UnsupportedEncodingException ex) {
      return null;
    }
  }

  @Override
  public void doGet(HttpServletRequest request, HttpServletResponse response)
      throws IOException, ServletException {
    String param = request.getParameter("q");
    if (param == null || encodeValue(param) == null) {
      response.setContentType("text/html;");
      response.getWriter().println("Invalid Query");
      return;
    }

    String query = encodeValue(param);
    List<String> allLinks = new ArrayList<>();

    // TODO: after implementing scraping, consider changing getLink calls to a
    // for-loop

    /*
     * Send request to retrieve card content through w3School site link from Google
     * CSE
     */
    String w3Link = getLink(W3_CSE_ID, query);
    if (w3Link != null) {
      allLinks.add(w3Link);
      // TODO: Call scraping function to return JSON card content
    }

    /*
     * Send request to retrieve card content through StackOverflow site link from
     * Google CSE
     */
    String stackLink = getLink(STACK_CSE_ID, query);
    if (stackLink != null) {
      allLinks.add(stackLink);
      // TODO: Call stackoverflow API to return JSON card content
    }

    /*
     * Send request to retrieve card content through GeeksForGeeks site link from
     * Google CSE
     */
    String geeksLink = getLink(GEEKS_CSE_ID, query);
    if (geeksLink != null) {
      allLinks.add(geeksLink);
      // TODO: Call scraping function to return JSON card content
    }

    response.setContentType("text/html;");
    response.getWriter().println(allLinks);
  }

  private String getLink(String id, String query) {
    String cse_request = CSE_URL + "?key=" + API_KEY + "&cx=" + id + "&q=" + query;
    HttpRequest linkRequest =
        HttpRequest.newBuilder()
            .GET()
            .uri(URI.create(cse_request))
            .setHeader("User-Agent", "Java 11 HttpClient Bot")
            .build();
    HttpResponse<String> linkResponse;
    try {
      linkResponse = httpClient.send(linkRequest, HttpResponse.BodyHandlers.ofString());
    } catch (IOException | InterruptedException ex) {
      return null;
    }
    /* Parse JSON of CSE SRP to retrieve link from only the first search result */
    JSONObject obj = new JSONObject(linkResponse.body());
    String link = obj.getJSONArray("items").getJSONObject(0).getString("link");
    return link;
  }
}

@@ -640,16 +640,149 @@
 vlets;%0A%0A
+import com.google.step.YOUR_PROJECT_NAME_HERE.data.Card;%0Aimport com.google.step.YOUR_PROJECT_NAME_HERE.external.StackOverflowClient;%0A
 import j
@@ -793,32 +793,32 @@
 io.IOException;%0A
-
 import java.io.U
@@ -1492,30 +1492,41 @@
  = %22
-INSERT_W3SCHOOL_CSE_ID
+017022763452466193978:wutqur3vf1w
 %22;%0A 
@@ -1574,35 +1574,41 @@
  = %22
-INSERT_STACKOVERFLOW_CSE_ID
+017022763452466193978:5jkwwqhp3re
 %22;%0A 
@@ -1656,35 +1656,41 @@
  = %22
-INSERT_GEEKSFORGEEKS_CSE_ID
+017022763452466193978:hfcnls4tlio
 %22;%0A 
@@ -1733,22 +1733,47 @@
  = %22
-INSERT_API_KEY
+AIzaSyAu1kT7ulGy3DMTCksBHk0gMHio1t4ec0E
 %22;%0A 
@@ -2627,16 +2627,58 @@
 ist%3C%3E();
+%0A    List%3CCard%3E cards = new ArrayList%3C%3E();
 %0A%0A    //
@@ -3289,67 +3289,150 @@
     
-// TODO: Call s
+StackOverflowClient stackClient = new S
 tack
-o
+O
 verflow
- API to return JSON card content
+Client();%0A      Card stackCard = stackClient.search(stackLink);%0A      cards.add(stackCard);
 %0A   
@@ -3732,24 +3732,52 @@
 tent%0A    %7D%0A%0A
+    Gson gson = new Gson();%0A
     response
@@ -3789,34 +3789,40 @@
 ontentType(%22
-text/html;
+application/json
 %22);%0A    resp
@@ -3846,24 +3846,125 @@
 println(
-allLinks
+gson.Json(cards));%0A    request.getRequestDispatcher(%22WEB-INF/templates/search.jsp%22).forward(request, response
 );%0A  %7D%0A%0A

create card objs, convert to json