/*
 - Licensed Materials - Property of IBM* and/or HCL**
 * IBM UrbanCode Build
 * IBM UrbanCode Deploy
 * IBM UrbanCode Release
 * IBM AnthillPro
 * (c) Copyright IBM Corporation 2002, 2016. All Rights Reserved.
 * (c) Copyright HCL Technologies Ltd. 2018. All Rights Reserved.
 *
 * U.S. Government Users Restricted Rights - Use, duplication or disclosure restricted by
 * GSA ADP Schedule Contract with IBM Corp.
 *
 * Trademark of International Business Machines
 ** Trademark of HCL Technologies Limited
 */
package com.ibm.urbancode.zos.common;

import groovyx.net.http.*


public class Jobs extends zOSMFRESTService{

    def Jobs(baseURL, username, password, untrustedSSL){
        super(baseURL, username, password, untrustedSSL);
    }
    
    /**
     params: a map of Query parameters
       owner        User ID of the job owner whose jobs are being queried; the default is the z/OS user ID. Folded to uppercase; cannot exceed eight characters.
       prefix       Job name prefix; defaults is *. Folded to uppercase; cannot exceed eight characters.
       jobid        Job ID. Folded to uppercase; cannot exceed eight characters. This query parameter is mutually exclusive with user-correlator.
       max-jobs     Maximum number of jobs returned. The value must be between 1 and 1000, inclusive. If this parameter is not specified, or is specified incorrectly, the default value of 1000 is used.
       
       Observe the following conventions:
           Query parameters are optional; you can specify one or more query parameters, as needed.
           You use a question mark (?) to separate the first query parameter from the resource.
           To specify multiple query parameters in combination, use an ampersand (&).
           Wildcard characters are permitted in the owner and prefix query parameter values. Use an asterisk (*) for multiple characters, and a question mark (?) for a single character.
       Example:
           [prefix : "IZU*" , "max-jobs": 1000]
           
     return: response of the RESTClient call.
         
   */
   def listJobs(params){
       try{
           def count = 0;
           def path = "/zosmf/restjobs/jobs"
           client.contentType = "*/*"
           params << [count : count ]
           count ++
           
           def resp  = client.get(  path : path,
                            query : params,
                            requestContentType: ContentType.JSON
                         )
           printRequest(path, params.toString());
           if(processRespose(resp) && resp.data){
              println "" + resp.data.size() + "jobs found."
              return resp;
           }else{
               return null;
           }
       }catch (HttpResponseException e){
           processResponseException(e);
           return null;
       }
   }
   
   def getJobJCL(name, id){
       getJobJCL(name, id,0);
   }
   /**
     lines:  0 for the entire file
   */
   def getJobJCL(name, id, lines){
           assert !name.contains("/") : "Job name can not contain /";
           assert !id.contains("/") : "Job id can not contain /";
           def headerMap = [:]
           if(lines == 0){
                   headerMap["X-IBM-Record-Range"] = "0-0"
           }else{
                   headerMap["X-IBM-Record-Range"] = "0,${lines}"
               }
           
           client.contentType = "*/*"
           def path = "/zosmf/restjobs/jobs/${name}/${id}/files/JCL/records"
           def resp  = client.get(  path : path,
                                    headers :  headerMap,
                                    query: [mode:"text"],
                                    requestContentType: ContentType.TEXT
                     )
           return resp;
   }

   def getSpoolFiles(name, id){
       getSpoolFiles(name, id, "*", 0);
   }
   /**
     lines:  0 for the entire file
   */
   def getSpoolFiles(name, id, ddnames, lines){
       assert !name.contains("/") : "Job name can not contain /";
       assert !id.contains("/") : "Job id can not contain /";
       //assert !ddnames.contains("/") : "ddname can not contain /";
           
       try{
           def headerMap = [:]
           if(lines == 0){
                   headerMap["X-IBM-Record-Range"] = "0-0"
           }else{
                   headerMap["X-IBM-Record-Range"] = "0,${lines}"
           }
           
           client.contentType = "*/*"
           def path = "/zosmf/restjobs/jobs/${name}/${id}/files"
           def resp  = client.get(  path : path,
                        requestContentType: ContentType.JSON
                     )
           
           if(processRespose(resp) && resp.data){
               if(resp.data.size() <= 0 ){
                   println "No spool files found"
                   return null;
               }else{
                   def fileMap = [:]
                   resp.data.each{
                       if(matchName(it.ddname, ddnames)){
                           println "Retriving ${it.ddname} for job ${name} ${id} ..."
                           def URI_JOBS_FILE_RECORDS = "/zosmf/restjobs/jobs/${name}/${id}/files/${it.id}/records"
                           def recordsResp  = client.get(  path : URI_JOBS_FILE_RECORDS,
                                                                        headers :  headerMap,
                                                                    query: [mode:"text"],
                                                requestContentType: ContentType.TEXT
                                               )
                           if(recordsResp.status == 200){
                               println "${it.ddname} retrived."
                               fileMap[it.id+" "+it.ddname] = recordsResp.data.text
                           }else{
                               println "Failed to retrieve ${it.ddname}"
                               println recordsResp.statusLine
                           }
                      }else{
                          println "${it.ddname} does not match ${ddnames}."
                      }
                  }
                  return fileMap;
               }
            }else{
                return null;
            }
        }catch (HttpResponseException e){
            processResponseException(e);
            return null;
        }
   }
   
   
   def matchName(name, patterns){
      //match everything if there's no pattern
       if(patterns.size() == 0){
           return true;
       }
       
       def match = false;
       patterns.each{
          def patternText = it.trim();
          if(patternText != ""){
               def pattern;
               if(patternText.startsWith("/") && patternText.endsWith("/")){
                   //if pattern is regular expression
                   pattern = ~patternText.substring(1,patternText.length()-1)
               }else{
                   //if pattern conatins ISPF stype wildcards, convert it to regular expression
                   patternText = patternText.replace ("*", ".*")
                   patternText = patternText.replace ("?", ".")
                   pattern = ~patternText
               }
               if(name ==~ pattern){
                   match = true;
               }
          }
       }
       return match;
   }
       
       /**
        return JSON
        
       */
       def submitJob(jcl){
         try  {
                   def URI_JOBS_SUBMIT = "/zosmf/restjobs/jobs"
                   client.contentType = "text/plain"
           def resp  = client.put(  path : URI_JOBS_SUBMIT,
                                                            body : jcl,
                            requestContentType: ContentType.TEXT
                         )
           assert resp.status == 201
           //TODO response is in JSON actually, need to parse it.
               return resp
         }catch (HttpResponseException e){
                   //any HTTP status code > 399 will end up here.
                       println e.response.statusLine
                       println ""
                       println e.response.data? e.response.data.text : ""
                       println ""
                       throw e
               }
   }
    
    def boolean processSpecificRespose(resp){
    }
}

