// Copyright 2019 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.sps;

import java.io.IOException;
import org.jsoup.HttpStatusException;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;

/** Return the Google Shopping results for a given query in the form of an HTML page. */
public class GoogleShoppingQuerier {

  private String shoppingQuery;
  private final String GOOGLE_SEARCH_BASE_URL =
      "https://www.google.com/search?tbm=shop&tbs=vw:l&safe=strict&hl=en&source=h";
  // Above, "tbm=shop" is the search type; "tbs=vw" removes ads and specifies the viewing style;
  // "hl=en" is the language parameter and "safe=strict" is the parameter for safety check.

  public GoogleShoppingQuerier(String shoppingQuery) {
    this.shoppingQuery = shoppingQuery;
  }

  public String query() throws IOException, HttpStatusException {
    if (!isValidShoppingQuery(shoppingQuery)) {
      throw new IOException("Invalid Shopping query.");
    }

    shoppingQuery = cleanValidShoppingQuery(shoppingQuery);

    String query = "q=" + shoppingQuery;
    String maxResultsNum = "num=6";
    String searchURL = GOOGLE_SEARCH_BASE_URL + "&" + query + "&" + maxResultsNum;

    Document doc;
    try {
      // Without proper User-Agent, it will result in a 403 error.
      doc = Jsoup.connect(searchURL).userAgent("Mozilla/5.0").get();
    } catch (HttpStatusException e) {
      throw new HttpStatusException(
          "Error while getting results from Google search", e.getStatusCode(), e.getUrl());
    }

    // Send back the HTML code of the search results.
    return doc.html();
  }

  private boolean isValidShoppingQuery(String shoppingQuery) {
    if (shoppingQuery.isEmpty()) {
      return false;
    }
    return true;
  }

  private String cleanValidShoppingQuery(String shoppingQuery) {
    shoppingQuery =
        shoppingQuery
            .replaceAll("\\s+", " ") // Remove duplicate spaces
            .trim() // Remove spaces from the beginning and end of string
            .replaceAll(" ", "%20") // Replace all spaces with '%20'
            .replaceAll("[ ,\n-._=+^\";:~#></|!*]", ""); // Remove all other special characters
    return shoppingQuery;
  }
}

@@ -739,18 +739,19 @@
 /** 
-Return the
+%0A * Queries
  Goo
@@ -767,62 +767,30 @@
 ing 
-results for a given query in the form of an HTML page.
+with the given input.%0A
  */%0A
@@ -863,235 +863,232 @@
 ry;%0A
+%0A
   
-private final String GOOGLE_SEARCH_BASE_URL =%0A      %22https://www.google.com/search?tbm=shop&tbs=vw:l&safe=strict&hl=en&source=h%22;%0A  // Above, %22tbm=shop%22 is the search type; %22tbs=vw%22 removes ads and speci
+// The parameters for %7B@code GOOGLE_SEARCH_BASE_URL%7D define the following:%0A  // %22tbm%22 defines the type of search;%0A  // %22tbs%22 defines advanced search parameters;%0A  // %22safe%22 de
 fi
+n
 es the 
-viewing style
+level of filtering for adult content
 ;%0A  
@@ -1097,14 +1097,16 @@
  %22hl
-=en%22 i
+%22 define
 s th
@@ -1120,70 +1120,169 @@
 age 
-parameter and %22safe=strict%22 is the parameter for safety check.
+to use for the Google search.%0A  private final String GOOGLE_SEARCH_BASE_URL =%0A      %22https://www.google.com/search?tbm=shop&tbs=vw:l&safe=active&hl=en&source=h%22;
 %0A%0A  

Update comments