package org.folio.rest.tools.client;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;

import org.folio.rest.tools.parser.JsonPathParser;

/**
 * @author shale
 *
 */
public class BuildCQL {

  private Response r;
  private String pathToExtractFrom;
  private String cqlPath;
  private String queryParamName = "query";
  private boolean addQuestionMark = true;
  private String operatorBetweenArgs = "or";

  private BuildCQL(){}

  /**
   * Builds a simple cql string by parsing through the Response's json, extracting values found in
   * the pathToExtractFrom path ({@link org.folio.rest.tools.parser.JsonPathParser}) and creating
   * a cql query string with cqlPath=values_found_in_path.
   * <br>
   * This could look something like this:
   * values found in <i>pathToExtractFrom</i>: <b>"hi", "hello", "whats up"</b>
   * <br>
   * <i>cqlPath</i>: <b>myField</b>
   * <br>
   * <i>result</i>: <b>?query=myField=hi+or+myField=hello+or+myField=whats%20up</b>
   * <br>The operator is 'or' by default
   * @param r
   * @param pathToExtractFrom
   * @param cqlPath
   * @param queryParamName - defaults to 'query'
   * @param addQuestionMark - defaults to 'true', if other params have already been added to the endpoint
   * change to false
   * @param operator - defaults to 'or'
   */
  public BuildCQL(Response r, String pathToExtractFrom, String cqlPath, String queryParamName, boolean addQuestionMark, String operator){
    this.r = r;
    this.pathToExtractFrom = pathToExtractFrom;
    this.queryParamName = queryParamName;
    this.addQuestionMark = addQuestionMark;
    this.cqlPath = cqlPath;
    this.operatorBetweenArgs = operator;
  }

  /**
   * Builds a simple cql string by parsing through the Response's json, extracting values found in
   * the pathToExtractFrom path ({@link org.folio.rest.tools.parser.JsonPathParser}) and creating
   * a cql query string with cqlPath=values_found_in_path.
   * <br>
   * This could look something like this:
   * values found in <i>pathToExtractFrom</i>: <b>"hi", "hello", "whats up"</b>
   * <br>
   * <i>cqlPath</i>: <b>myField</b>
   * <br>
   * <i>result</i>: <b>?query=myField=hi+or+myField=hello+or+myField=whats%20up</b>
   * <br>The operator is 'or' by default
   * @param r
   * @param pathToExtractFrom
   * @param cqlPath
   * @param queryParamName - defaults to 'query'
   */
  public BuildCQL(Response r, String pathToExtractFrom, String cqlPath, String queryParamName){
    this.r = r;
    this.pathToExtractFrom = pathToExtractFrom;
    this.queryParamName = queryParamName;
    this.cqlPath = cqlPath;
  }

  /**
   * Builds a simple cql string by parsing through the Response's json, extracting values found in
   * the pathToExtractFrom path ({@link org.folio.rest.tools.parser.JsonPathParser}) and creating
   * a cql query string with cqlPath=values_found_in_path.
   * <br>
   * This could look something like this:
   * values found in <i>pathToExtractFrom</i>: <b>"hi", "hello", "whats up"</b>
   * <br>
   * <i>cqlPath</i>: <b>myField</b>
   * <br>
   * <i>result</i>: <b>?query=myField=hi+or+myField=hello+or+myField=whats%20up</b>
   * <br>The operator is 'or' by default
   * @param r
   * @param pathToExtractFrom
   * @param cqlPath
   */
  public BuildCQL(Response r, String pathToExtractFrom, String cqlPath){
    this.r = r;
    this.pathToExtractFrom = pathToExtractFrom;
    this.cqlPath = cqlPath;
  }

  public String buildCQL() throws UnsupportedEncodingException {
    StringBuilder sb = new StringBuilder();
    if(addQuestionMark){
      sb.append("?");
    }
    else{
      sb.append("&");
    }
    sb.append(queryParamName).append("=");
    JsonPathParser jpp = new JsonPathParser( r.getBody() );
    Object o = jpp.getValueAt(pathToExtractFrom);
    List<Object> paths = null;
/*    if(o instanceof JsonArray){
      paths = ((JsonArray)o).getList();
    }*/
    if (o instanceof List){
      //assume list
      paths = (List<Object>)jpp.getValueAt(pathToExtractFrom);
    }
    else{
      //single value
      paths = new ArrayList<>();
      paths.add(o);
    }
    int size = paths.size();
    for (int i = 0; i < size; i++) {
      sb.append(cqlPath).append("==").append(URLEncoder.encode(paths.get(i).toString(), "UTF-8"));
      if(i<size-1){
        sb.append("+").append(operatorBetweenArgs).append("+");
      }
    }
    return sb.toString();
  }

}

@@ -3572,24 +3572,73 @@
 gBuilder();%0A
+    StringBuilder prefix = new StringBuilder();%0A%0A
     if(addQu
@@ -3648,34 +3648,38 @@
 ionMark)%7B%0A      
-sb
+prefix
 .append(%22?%22);%0A  
@@ -3690,34 +3690,38 @@
     else%7B%0A      
-sb
+prefix
 .append(%22&%22);%0A  
@@ -3724,26 +3724,30 @@
 ;%0A    %7D%0A    
-sb
+prefix
 .append(quer
@@ -3767,24 +3767,25 @@
 ppend(%22=%22);%0A
+%0A
     JsonPath
@@ -3917,14 +3917,14 @@
 ll;%0A
-/*
     
+/*
 if(o
@@ -4268,16 +4268,74 @@
  i++) %7B%0A
+      if(paths.get(i) == null)%7B%0A        continue;%0A      %7D%0A
       sb
@@ -4531,28 +4531,102 @@
     
-return sb.toString()
+if(sb.length() %3E 0)%7B%0A      return prefix.append(sb.toString()).toString();%0A    %7D%0A    return %22%22
 ;%0A  

handle null values