/*
* Licensed Materials - Property of IBM Corp.
* IBM UrbanCode Build
* (c) Copyright IBM Corporation 2012, 2014. All Rights Reserved.
*
* U.S. Government Users Restricted Rights - Use, duplication or disclosure restricted by
* GSA ADP Schedule Contract with IBM Corp.
*/
package com.urbancode.air.plugin.automation;

import org.apache.commons.codec.*
import org.apache.commons.httpclient.*
import org.apache.commons.httpclient.methods.*
import org.apache.http.HttpResponse
import org.apache.http.client.methods.HttpGet
import org.apache.http.client.methods.HttpPost
import org.apache.http.entity.StringEntity
import org.codehaus.jettison.json.JSONObject

import com.urbancode.air.*
import com.urbancode.commons.util.IO

public class CreateDefect extends AutomationBase {
    
    //**************************************************************************
    // CLASS
    //**************************************************************************

    //**************************************************************************
    // INSTANCE
    //**************************************************************************

    String projectKey
    String requirementKey
    String defectName
    String defectDesc
    String priority
    String severity
    String state
    String submitter
    String environment
    String build

    public void execute() {
        setupHttpClient()
        createDefect()
    }

    private void createDefect() {
        def workspaceRef = configureWorkspace()

        def jsonProject
        def jsonRequirement

        if (projectKey && projectKey.length() > 0) {
          def projectMethod = new HttpGet(url + "project?workspace=" + URLEncoder.encode(workspaceRef, "UTF-8") + "&query=" +
              URLEncoder.encode("(Name = \"" + projectKey + "\")" ,"UTF-8") + "&" + URLEncoder.encode("fetch", "UTF-8") + "=" +
                  URLEncoder.encode("true", "UTF-8"))
          println "GetProjectJSONUrl:" + url + "project?workspace=" + URLEncoder.encode(workspaceRef, "UTF-8") + "&query=" +
              URLEncoder.encode("(Name = \"" + projectKey + "\")" ,"UTF-8") + "&" + URLEncoder.encode("fetch", "UTF-8") + "=" +
              URLEncoder.encode("true", "UTF-8")
          HttpResponse response = client.execute(projectMethod)
          String responseText = IO.readText(response.entity.content)

          def jsonProjectFromQueryResults = new JSONObject(responseText)['QueryResult']['Results'].get(0)
          /*"Project": {
           "_rallyAPIMajor": "2",
           "_rallyAPIMinor": "0",
           "_ref": "https://rally1.rallydev.com/slm/webservice/v2.0/project/31478170091",
           "_refObjectUUID": "0f74e14b-6e43-47a2-b7e0-8bbef136c7e0",
           "_refObjectName": "Project 2",
           "_type": "Project"
          }*/
          jsonProject = new JSONObject();
          jsonProject.put("_rallyAPIMajor",jsonProjectFromQueryResults.get("_rallyAPIMajor"));
          jsonProject.put("_rallyAPIMinor",jsonProjectFromQueryResults.get("_rallyAPIMinor"));
          jsonProject.put("_ref",jsonProjectFromQueryResults.get("_ref"));
          jsonProject.put("_refObjectUUID",jsonProjectFromQueryResults.get("_refObjectUUID"));
          jsonProject.put("_refObjectName",jsonProjectFromQueryResults.get("_refObjectName"));
          jsonProject.put("_type",jsonProjectFromQueryResults.get("_type"));

          if (projectMethod != null) {
              projectMethod.releaseConnection()
          }
        }
        else {
          def requirementMethod = new HttpGet(url + "hierarchicalrequirement?workspace=" + URLEncoder.encode(workspaceRef, "UTF-8") +
              "&query=" + URLEncoder.encode("(FormattedID = " + requirementKey + ")" ,"UTF-8") + "&" + URLEncoder.encode("fetch", "UTF-8") +
                  "=" + URLEncoder.encode("true", "UTF-8"))
          println "GetHierarchicalReqJSONUrl:" + url + "hierarchicalrequirement?workspace=" + URLEncoder.encode(workspaceRef, "UTF-8") +
              "&query=" + URLEncoder.encode("(FormattedID = " + requirementKey + ")" ,"UTF-8") + "&" + URLEncoder.encode("fetch", "UTF-8") +
                  "=" + URLEncoder.encode("true", "UTF-8")
          HttpResponse response = client.execute(requirementMethod)
          String responseText = IO.readText(response.entity.content)
          def jsonQueryResult = new JSONObject(responseText)['QueryResult']['Results'].get(0)
          jsonProject = jsonQueryResult.get('Project');

          /*"Requirement": {
              "_rallyAPIMajor": "2",
              "_rallyAPIMinor": "0",
              "_ref": "https://rally1.rallydev.com/slm/webservice/v2.0/hierarchicalrequirement/31468184935",
              "_refObjectUUID": "2e23c190-9687-4e25-989d-71086f8fd414",
              "_refObjectName": "Browse safaris",
              "_type": "HierarchicalRequirement"
          }*/
          jsonRequirement = new JSONObject()
          jsonRequirement.put("_rallyAPIMajor",jsonQueryResult.get("_rallyAPIMajor"))
          jsonRequirement.put("_rallyAPIMinor",jsonQueryResult.get("_rallyAPIMinor"))
          jsonRequirement.put("_ref",jsonQueryResult.get("_ref"))
          jsonRequirement.put("_refObjectUUID",jsonQueryResult.get("_refObjectUUID"))
          jsonRequirement.put("_refObjectName",jsonQueryResult.get("_refObjectName"))
          jsonRequirement.put("_type",jsonQueryResult.get("_type"))

          if(requirementMethod != null) {
             requirementMethod.releaseConnection()
          }
        }

        def jsonDetails = new JSONObject()
        jsonDetails.put('Project', jsonProject)
        if (requirementKey && requirementKey.length() >0) {
            jsonDetails.put('Requirement', jsonRequirement)
        }
        jsonDetails.put('Description', defectDesc)
        jsonDetails.put('Name', defectName)
        jsonDetails.put('Priority', priority)
        jsonDetails.put('Severity', severity)
        jsonDetails.put('State', state)
        jsonDetails.put('Environment', environment)
        jsonDetails.put('FoundInBuild', build)
        if (submitter && submitter.length() >0) {
            def jsonSubmitter = getSubmitterJson(submitter)
            if (jsonSubmitter != null) {
                jsonDetails.put('SubmittedBy', jsonSubmitter)
            }
            else {
                println "Submitter '$submitter' information can't be gotten from Rally Server!"
                System.exit 1
            }
        }

        def jsonCreate = new JSONObject()
        jsonCreate.put('Defect', jsonDetails)

        def key = getKey()
        HttpPost method = new HttpPost(url + "defect/create?key=" + URLEncoder.encode(key, 'UTF-8'))
        method.setEntity(new StringEntity(jsonCreate.toString(), null, null));
        def result = client.execute(method)
        def responseText = IO.readText(result.entity.content)

        //check results
        def responseCode = result.statusLine.statusCode
        def createResult = new JSONObject(responseText).get('CreateResult')
        def errors = createResult.get('Errors')
        def warnings = createResult.get('Warnings')

        if (errors.length() == 0 && isGoodResponseCode(responseCode)) {
            def createObj = createResult.get('Object')
            def defectURL = createObj.get('_ref')
             println "Successfully created defect! ObjectRef =" + defectURL;
            if (warnings.length() > 0) {
                println "Warnings: $warnings"
            }
            System.exit 0
        }
        else {
          println "ERROR!!! Rally Server could not create defect! "
          if (errors.length() > 0) {
              println "Errors: $errors"
          }
          if (warnings.length() > 0) {
              println "Warnings: $warnings"
          }
          System.exit 1
        }
    }

    private JSONObject getSubmitterJson(String submitter) {
        def submitterUrl = url + "user/?query=" + URLEncoder.encode("(Name = " + submitter + ")" ,"UTF-8") +
            "&" + URLEncoder.encode("fetch = ", "UTF-8") + URLEncoder.encode("true", "UTF-8")
        println "Getting submitter url : $submitterUrl"
        def submitterMethod = new HttpGet(submitterUrl)
        HttpResponse response = client.execute(submitterMethod)

        def responseCode = response.statusLine.statusCode
        String responseText = IO.readText(response.entity.content)

        def queryResult = new JSONObject(responseText).get('QueryResult')
        def errors = queryResult.get('Errors')
        def warnings = queryResult.get('Warnings')

        /*"SubmittedBy": {
            "_rallyAPIMajor": "2",
            "_rallyAPIMinor": "0",
            "_ref": "https://rally1.rallydev.com/slm/webservice/v2.0/user/31468180759",
            "_refObjectUUID": "4ac2305f-ec37-472b-98a1-5752feae0b87",
            "_refObjectName": "mlbw",
            "_type": "User"
        },*/
        JSONObject jsonSubmitter = null
        if (errors.length() == 0 && isGoodResponseCode(responseCode)) {
            int totalResultCount = queryResult['TotalResultCount']
            if (totalResultCount == 0) {
                println "Rally Server could not find the submitter '$submitter' ! "
            }
            else {
                def jsonQueryResult = queryResult['Results'].get(0)
                jsonSubmitter = jsonQueryResult
            }
        }
        else {
            println "ERROR!!! Rally Server could not find the submitter '$submitter' ! "
            if (errors.length() > 0) {
                println "Errors: $errors"
            }
            if (warnings.length() > 0) {
                println "Warnings: $warnings"
            }
            System.exit 1
        }

        return jsonSubmitter
    }
}