package water.api;

import hex.GridSearch;

import java.util.*;

import water.H2O;
import water.util.RString;

/**
 *
 * @author peta
 */
public class RequestQueries extends RequestArguments {

  /** Overwrite this method to be able to change / disable values of other
   * arguments on certain argument changes.
   *
   * This is done for both query checking and request checking.
   */
  protected void queryArgumentValueSet(Argument arg, Properties inputArgs) {

  }


  /** Checks the given arguments.
   *
   * When first argument is found wrong, generates the json error and returns the
   * result to be returned if any problems were found. Otherwise returns
   *
   * @param args
   * @param type
   * @return
   */
  protected final String checkArguments(Properties args, RequestType type) {
    // Why the following lines duplicate lines from Request#92 - handling query?
    // reset all arguments
    for (Argument arg: _arguments)
      arg.reset();
    // return query if in query mode
    if (type == RequestType.query)
      return buildQuery(args,type);

    /*
    // Check that for each actual input argument from the user, there is some
    // request argument that this method is expecting.
    //*/
    if (H2O.OPT_ARGS.check_rest_params && !(this instanceof GridSearch) && !(this instanceof HTTP500)) {
      Enumeration en = args.propertyNames();
      while (en.hasMoreElements()) {
        boolean found = false;
        String key = (String) en.nextElement();
        for (Argument arg: _arguments) {
          if (arg._name.equals(key)) {
            found = true;
            break;
          }
        }
        if (!found) {
          return jsonError("Request specifies the argument '"+key+"' but it is not a valid parameter for this query " + this.getClass().getName()).toString();
        }
      }
    }

    // check the arguments now
    for (Argument arg: _arguments) {
      if (!arg.disabled()) {
        try {
          arg.check(RequestQueries.this, args.getProperty(arg._name,""));
          queryArgumentValueSet(arg, args);
        } catch( IllegalArgumentException e ) {
          if (type == RequestType.json)
            return jsonError("Argument '"+arg._name+"' error: "+e.getMessage()).toString();
          else
            return buildQuery(args,type);
        }
      }
    }
    return null;
  }

  protected static final String _queryHtml =
            "<div class='container'>"
          + "<div class='row-fluid'>"
          + "<div class='span12'>"
          + "<h3>Request %REQ_NAME <a href='%REQ_NAME.help'><i class='icon-question-sign'></i></a></h3>"
          + "<p></p>"
          + "  <dl class='dl-horizontal'><dt></dt><dd>"
          + "    <button class='btn btn-primary' onclick='query_submit()'>Submit</button>"
          + "    <button class='btn btn-info' onclick='query_refresh(event || window.event)'>Refresh</button>"
          + "    <button class='btn' onclick='query_reset()'>Reset</button>"
          + "  </dd></dl>"
          + "    %QUERY"
          + "  <dl class='dl-horizontal'><dt></dt><dd>"
          + "    <button class='btn btn-primary' onclick='query_submit()'>Submit</button>"
          + "    <button class='btn btn-info' onclick='query_refresh(event || window.event)'>Refresh</button>"
          + "    <button class='btn' onclick='query_reset()'>Reset</button>"
          + "  </dd></dl>"
          + "  <script type='text/javascript'>"
          + "    %SCRIPT"
          + "  </script>"
          + "</div></div></div>"
          ;

  private static final String _queryJs =
            "\nfunction query_refresh(event) {\n"
          + "  query_submit('.query', event.data, null);\n"
          + "}\n"
          + "function query_submit(requestType, specArg, specValue) {\n"
          + "  query_refresh(window.event)"
          + "  if (typeof(requestType) === 'undefined')\n"
          + "    requestType='.html';\n"
          + "  var request = {};\n"
          + "  %REQUEST_ELEMENT{"
          + "%ELEMENT_PREQ request.%ELEMENT_NAME = query_value_%ELEMENT_NAME();\n"
          + "  }\n"
          + "  var location = '%REQUEST_NAME'+requestType+'?'+$.param(request);\n"
          + "  if (requestType == '.query') {\n"
          + "    window.location.replace(location);\n"
          + "  } else {\n"
          + "    window.location = location;\n"
          + "  }\n"
          + "}\n"
          + "function query_reset() {\n"
          + "  window.location.replace('%REQUEST_NAME.query');\n"
          + "}\n"
          + "%ELEMENT_VALUE{ %BODY\n }"
          + "%ELEMENT_ADDONS{ %BODY\n }"
          + "%ELEMENT_ONCHANGE{ %BODY\n }"
          ;


  /** Returns the request query form produced from the given input arguments.
   */
  protected String buildQuery(Properties parms, RequestType type) {
    if (parms.isEmpty())
      type = RequestType.query;
    RString result = new RString(_queryHtml);
    result.replace("REQ_NAME", this.getClass().getSimpleName());
    StringBuilder query = new StringBuilder();
    query.append("<form onsubmit='return false;'>");
    RString script = new RString(_queryJs);
    script.replace("REQUEST_NAME", getClass().getSimpleName());
    for (Argument arg: _arguments) {
      try {
        arg.check(RequestQueries.this, parms.getProperty(arg._name,""));
        queryArgumentValueSet(arg, parms);
      } catch( IllegalArgumentException e ) {
        // in query mode only display error for arguments present
        if ((type != RequestType.query) || !parms.getProperty(arg._name,"").isEmpty())
          query.append("<div class='alert alert-error'>"+e.getMessage()+"</div>");
      }
      if (arg._hideInQuery)
        continue;
      if (!arg.disabled()) {
        RString x = script.restartGroup("REQUEST_ELEMENT");
        x.replace("ELEMENT_NAME",arg._name);
        // If some Argument has prerequisites, and those pre-reqs changed on
        // this very page load then we do not assign the arg here: the values
        // passed will be something valid from the PRIOR page - based on the
        // old pre-req - and won't be correct.  Not assigning them here means
        // we'll act "as if" the field was never filled in.
        if( arg._prerequisites != null ) {
          StringBuilder sb = new StringBuilder("if( ");
          ArrayList<RequestArguments.Argument> preqs = arg._prerequisites;
          for( RequestArguments.Argument dep : preqs )
            sb.append("specArg!=='").append(dep._name).append("' && ");
          sb.append("true ) ");
          x.replace("ELEMENT_PREQ",sb);
        }
        x.append();
        x = script.restartGroup("ELEMENT_VALUE");
        x.replace("ELEMENT_NAME",arg._name);
        x.replace("BODY","function query_value_"+arg._name+"() { "+arg.jsValue()+"} ");
        x.append();
      }
      if (arg.refreshOnChange()) {
        RString x = script.restartGroup("ELEMENT_ONCHANGE");
        x.replace("BODY",arg.jsRefresh("query_refresh"));
        x.append();
      }
      RString x = script.restartGroup("ELEMENT_ADDONS");
      x.replace("BODY", arg.jsAddons());
      x.append();
    }
    for(Argument arg:_arguments){
      if (arg._hideInQuery)
        continue;
      query.append(arg.query());
    }
    query.append("</form>");
    result.replace("QUERY",query.toString());
    result.replace("SCRIPT",script.toString());
    return result.toString();
  }

}

@@ -3769,52 +3769,8 @@
 %5Cn%22%0A
-          + %22  query_refresh(window.event)%22%0A
     

Revert "back button in browser preserves user inputs"