/**
   * Spray a variable/delimited data file onto a target cluster on the target HPCC System
   *
   * @param fileName - The existing file (on the target HPCC System) to spray
   * @param targetFileLabel - The full label the sprayed file will be assigned
   * @param targetCluster - The cluster on which to spray
   * @param options - Delimited file description
   * @param overwritesprayedfile - Boolean, overwrite possibly sprayed file of same name
   * @param format - FileFormat
   * @return - Boolean, success.
   */
  public boolean sprayVariableHPCCFile(
      String fileName,
      String targetFileLabel,
      String targetCluster,
      DelimitedDataOptions options,
      boolean overwritesprayedfile,
      SprayVariableFormat format) {
    boolean success = false;

    try {
      HPCCFileSprayClient fileSprayClient = getFileSprayClient();
      if (fileSprayClient != null)
        success =
            handleSprayResponse(
                fileSprayClient.sprayVariableLocalDropZone(
                    options,
                    fileName,
                    targetFileLabel,
                    "",
                    targetCluster,
                    overwritesprayedfile,
                    format));
      else throw new Exception("Could not initialize HPCC FileSpray Client");
    } catch (org.hpccsystems.ws.client.gen.filespray.v1_13.ArrayOfEspException e) {
      Utils.println(
          System.out, "Error: Could not spray file" + e.getLocalizedMessage(), true, true);
    } catch (RemoteException e) {
      Utils.println(
          System.out, "Error: Could not spray file" + e.getLocalizedMessage(), true, true);
    } catch (Exception e) {
      e.printStackTrace();
    }

    return success;
  }
  /**
   * Spray a fixed record length data file onto a target cluster on the target HPCC System
   *
   * @param fileName - The existing file (on the target HPCC System) to spray
   * @param targetFileLabel - The full label the sprayed file will be assigned
   * @param recordSize - The record length
   * @param targetCluster - The cluster on which to spray
   * @param overwritesprayedfile - Boolean, overwrite possibly sprayed file of same name
   * @return - Boolean, success.
   */
  public boolean sprayFlatHPCCFile(
      String fileName,
      String targetFileLabel,
      int recordSize,
      String targetCluster,
      boolean overwritesprayedfile) {
    boolean success = true;

    try {
      HPCCFileSprayClient fileSprayClient = getFileSprayClient();

      if (fileSprayClient != null)
        success =
            handleSprayResponse(
                fileSprayClient.sprayFixedLocalDropZone(
                    fileName,
                    recordSize,
                    targetFileLabel,
                    "",
                    targetCluster,
                    overwritesprayedfile));
      else throw new Exception("Could not initialize HPCC fileSpray Client");
    } catch (org.hpccsystems.ws.client.gen.filespray.v1_13.ArrayOfEspException e) {
      Utils.println(
          System.out, "Error: Could not spray file" + e.getLocalizedMessage(), true, verbosemode);
    } catch (RemoteException e) {
      Utils.println(
          System.out, "Error: Could not spray file" + e.getLocalizedMessage(), true, verbosemode);
    } catch (Exception e) {
      e.printStackTrace();
    }

    return success;
  }
  /**
   * Spray a variable/delimited data file onto a target cluster on the target HPCC System
   *
   * @param fileName - The existing file (on the target HPCC System) to spray
   * @param targetFileLabel - The full label the sprayed file will be assigned
   * @param targetCluster - The cluster on which to spray
   * @param escapedEscapeSequence - The escape character sequence (must be escaped)
   * @param escapedFieldDelim - The field delimiter (must be escaped)
   * @param escapedQuote - The data quote (must be escaped)
   * @param escapedRecTerminator - The record terminator sequence (must be escaped)
   * @param overwritesprayedfile - Boolean, overwrite possibly sprayed file of same name
   * @return - Boolean, success.
   */
  public boolean sprayCustomCSVHPCCFile(
      String fileName,
      String targetFileLabel,
      String targetCluster,
      String escapedEscapeSequence,
      String escapedFieldDelim,
      String escapedQuote,
      String escapedRecTerminator,
      boolean overwritesprayedfile,
      SprayVariableFormat format) {
    boolean success = true;

    try {
      success =
          sprayVariableHPCCFile(
              fileName,
              targetFileLabel,
              targetCluster,
              new DelimitedDataOptions(
                  escapedRecTerminator, escapedFieldDelim, escapedEscapeSequence, escapedQuote),
              overwritesprayedfile,
              format);
    } catch (Exception e) {
      Utils.println(System.out, "Error: Could not spray file", true, true);
      success = false;
    }

    return success;
  }
  /**
   * Submits the given ECL to compile/execute on the targetclust, and returns results.
   *
   * @param ecl - The ECL query to compile and execute
   * @param targetcluster - The cluster on which this query should be compiled and ran
   * @param resultLimit - Directive to limit the resulting set
   * @param maxwait - Maxwait in millis
   * @return - If successful, the resulting dataset(s)
   * @throws Exception
   */
  public String submitECLandGetResults(WorkunitInfo wu) throws Exception {
    String results = null;
    HPCCWsWorkUnitsClient wsWorkunitsClient = getWsWorkunitsClient();

    try {
      if (wsWorkunitsClient != null)
        results = wsWorkunitsClient.createAndRunWUFromECLAndGetResults(wu);
      else throw new Exception("Could not initialize HPCC WsWorkUnits Client");
    } catch (Exception e) {
      Utils.println(
          System.err, "Error submitting ECL: " + e.getLocalizedMessage(), false, verbosemode);
      throw e;
    }

    return results;
  }
  private boolean handleSprayResponse(ProgressResponse sprayResponse) throws Exception {
    boolean success = false;

    org.hpccsystems.ws.client.gen.filespray.v1_13.ArrayOfEspException exceptions =
        sprayResponse.getExceptions();
    if (exceptions != null) {
      for (EspException espexception : exceptions.getException()) {
        Utils.println(
            System.out,
            "Error spraying file: " + espexception.getSource() + espexception.getMessage(),
            false,
            verbosemode);
      }
    } else {
      HPCCFileSprayClient fileSprayClient = getFileSprayClient();

      if (fileSprayClient == null)
        throw new Exception("Could not initialize HPCC FileSpray Client");

      ProgressRequest dfuprogressparams = new ProgressRequest();
      dfuprogressparams.setWuid(sprayResponse.getWuid());
      Utils.println(System.out, "Spray file DWUID: " + sprayResponse.getWuid(), true, verbosemode);
      ProgressResponse progressResponse =
          fileSprayClient.fileSprayServiceSoapProxy.getDFUProgress(dfuprogressparams);

      if (progressResponse.getExceptions() != null) {
        Utils.println(System.out, "Spray progress status fetch failed.", false, verbosemode);
      } else {
        String state = progressResponse.getState();
        Utils.println(System.out, progressResponse.getState(), true, verbosemode);
        if (!state.equalsIgnoreCase("FAILED")) {
          // this should be in a dedicated thread.
          for (int i = 0;
              i < 10
                  && progressResponse.getPercentDone() < 100
                  && !progressResponse.getState().equalsIgnoreCase("FAILED");
              i++) {
            Utils.println(System.out, progressResponse.getProgressMessage(), true, verbosemode);
            progressResponse =
                fileSprayClient.fileSprayServiceSoapProxy.getDFUProgress(dfuprogressparams);

            try {
              Thread.sleep(100);
            } catch (InterruptedException e) {
              e.printStackTrace();
            }
          }
          Utils.println(System.out, progressResponse.getProgressMessage(), true, verbosemode);
          success = true;
        } else {
          Utils.println(System.out, "Spray failed.", false, verbosemode);
        }
        Utils.println(
            System.out,
            "Final summary from server: " + progressResponse.getSummaryMessage(),
            true,
            verbosemode);

        Utils.println(
            System.out,
            "Spray attempt completed, verify DWUID: " + sprayResponse.getWuid(),
            false,
            verbosemode);
      }
    }
    return success;
  }