/*
* Licensed Materials - Property of IBM* and/or HCL**
* UrbanCode Deploy
* (c) Copyright IBM Corporation 2002-2017. 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.urbancode.air.plugin.iisconfiguration.helper
import org.codehaus.jettison.json.JSONObject
import org.codehaus.jettison.json.JSONArray

class XMLToCompareJSONHelper {
    //convert archive.xml to specific JSON format for UCD comparisons
    //JSONArray must include JSONObjects with the following required attributes:
    //1. Name
    //2. Parent
    //3. Path (Foaticr tree to visualize)
    //4. roleProperties (JSONObject with attributes inside)
    public static JSONArray getCompareJSONFromXMLFile(File xmlFile){
        def lineList = xmlFile.readLines()
        def xmlSlurped = new XmlSlurper().parseText(xmlFile.text)
        def resultJSONArray = new JSONArray()
        def pathStack = ["/"] as Stack
        AddCompareJSONToJSONArray(resultJSONArray, pathStack, xmlSlurped)

        println(resultJSONArray.toString(4))
        return resultJSONArray
    }

    //traverse xml from file and convert it to specific JSON format for UCD compare
    private static JSONArray AddCompareJSONToJSONArray(JSONArray resultJSONArray, pathStack, node){
        //1. traverse first xml node and create jsonobject to represent it
        def childJSONObject = new JSONObject()
        def roleProperties = new JSONObject()
        def duplicateFound = false

        //2. jsonobject "name" = xml node "name"
        def name = node.name()
        //pattern to check for this name in the path, or this name with a digit on the end
        //then the string boundary.
        def namePattern = pathStack.join("/").replace("//", "/") =~ /\/${name}\d*\b/
        //if it exists, we need to add a number to the name to make it
        //unique since the path we make using this name must be unique
        if(namePattern.find()){
            //we need to pop down 1 to reach the parent that this child needs to go under, so pop
            def count = pathStack.pop()[-1..-1]
            //if the last char of this string is not a number, we need to initiate with a 0 on the end
            if (!count.isNumber()){
                name += 0
            }
            else {
                //otherwise, increment the number
                count = count.toInteger()
                count++
                name = name[0..-1] + "${count}"
            }
        }

        childJSONObject.put("name", name)

        //3. set parent == path for parent
        def path = pathStack.join("/").replace("//", "/")
        def parent = path
        childJSONObject.put("parent", parent)

        //4. set path for this object by pushing its name to the path stack
        pathStack.push(name)
        path = pathStack.join("/").replace("//","/")
        childJSONObject.put("path", path)

        //5. each attribute for this xml node will be roleProperty for jsonobject
        def key, value
        node.attributes().each{
            key = it.key
            value = it.value
            roleProperties.put(key, value)
        }
        childJSONObject.put("roleProperties", roleProperties)
        resultJSONArray.put(childJSONObject)

        //6. step 1, repeat until all xml traversed
        def deepClonePathStack = [] as Stack
        pathStack.each{ deepClonePathStack << it }
        node.children().each{ AddCompareJSONToJSONArray(resultJSONArray, deepClonePathStack, it) }

        return resultJSONArray
    }
}
