/*
* 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.
*/
import org.codehaus.jettison.json.JSONArray;
import org.codehaus.jettison.json.JSONObject;
import javax.ws.rs.core.UriBuilder;

public class PropsHelper {
    
    final private HttpHelper httpHelper;
    
    public PropsHelper(HttpHelper httpHelper) {
        this.httpHelper = httpHelper;
    }
    
    /**
     * Set component version properties using line-separated properties from a text area input.
     */
    public void setComponentVersionProperties(String url, String componentName, String versionName, String propertiesTextArea) {
        if (!propertiesTextArea) {
            println "No properties defined to set"
            return
        }
        
        def propertiesToSet = new Properties()
        propertiesToSet.load(new StringReader(propertiesTextArea))
        setComponentVersionProperties(url, componentName, versionName, propertiesToSet)
    }
    
    /**
     * Set component version properties using a Properties object.
     */
    public void setComponentVersionProperties(String url, String componentName, String versionName, Properties propertiesToSet) {
        if (propertiesToSet.isEmpty()) {
            println "No properties defined to set"
            return
        }
        
        // get the component version
        def versionsUrl = UriBuilder.fromUri(url).segment("rest", "deploy", "component", componentName, "versions", "false").build().toString()
        def versionsJson = new JSONArray(httpHelper.getContent(versionsUrl))
        
        def versionId
        for (int versionIndex = 0; versionIndex < versionsJson.length(); versionIndex++) {
            def versionJson = versionsJson.getJSONObject(versionIndex)
            if (versionName.equals(versionJson.getString("name"))) {
                versionId = versionJson.getString("id")
                break
            }
        }
        
        if (!versionId) {
            throw new Exception("Version ${versionName} not found on component ${componentName}")
        }
        
        def propDefsUrl = getPropDefsUrl(url, componentName)
        def propSheetDefContent = httpHelper.getContent(propDefsUrl)
        println "Component Version Prop Sheet Def:\n${propDefsUrl}\n${propSheetDefContent}"
        def propSheetDefJson = new JSONArray(propSheetDefContent)
        
        def propertiesToCreate = []
        for (def propertyName : propertiesToSet.keySet()) {
            println "Looking for property definition ${propertyName}"
            def foundProperty = false
            for (int psIndex = 0; psIndex < propSheetDefJson.length(); psIndex++) {
                def propSheetDef = propSheetDefJson.getJSONObject(psIndex)
                if (propertyName.equals(propSheetDef.getString("name"))) {
                    foundProperty = true
                    break
                }
            }
            if (!foundProperty) {
                propertiesToCreate.add(propertyName)
            }
        }
        
        if (!propertiesToCreate.empty) {
            println "Need to create property definitions: ${propertiesToCreate}"
            for (def propertyToCreate : propertiesToCreate) {
                // {"id":"caa95ea5-cf17-4369-80a4-9abcbffe0da0","name":"my_prop_def","label":"my_prop_def","type":"TEXT",
                // "value":"","required":false,"description":"","inherited":false}
                JSONObject propertyCreateJson = new JSONObject()
                propertyCreateJson.put("name", propertyToCreate)
                propertyCreateJson.put("label", "")
                propertyCreateJson.put("type", "TEXT")
                propertyCreateJson.put("value", "")
                propertyCreateJson.put("required", false)
                propertyCreateJson.put("description", "")
                propertyCreateJson.put("inherited", false)
                // the propDefsUrl changes with each properties created due to terrible we service design
                propDefsUrl = getPropDefsUrl(url, componentName)
                httpHelper.putContent(propDefsUrl, propertyCreateJson.toString())
                println "Created property definition for ${propertyToCreate}"
            }
        }
            
        
        // now set the properties
        def versionUrl = UriBuilder.fromUri(url).segment("rest", "deploy", "version", versionId).build().toString()
        def versionJson = new JSONObject(httpHelper.getContent(versionUrl))
        println "Component Version:\n${versionUrl}\n${versionJson}"
        
        def propSheetPath
        def propSheetVersion = 1
        def versionPropSheetsJson = versionJson.getJSONArray("propSheets")
        for (int vpsIndex = 0; vpsIndex < versionPropSheetsJson.length(); vpsIndex++) {
            def versionPropSheetJson = versionPropSheetsJson.getJSONObject(vpsIndex)
            if (!versionPropSheetJson.has("name")) {
                propSheetPath = versionPropSheetJson.getString("path")
                propSheetVersion = Integer.valueOf(versionPropSheetJson.getString("version"))
                break
            }
        }
        
        if (!propSheetPath) {
            throw new Exception("Did not find the location to update properties for the component version.")
        }
        
        def propSheetPathToUpdate = propSheetPath + "." + propSheetVersion
        def versionPropSheetGetUrl = UriBuilder.fromUri(url).segment("property", "propSheet", propSheetPathToUpdate, "propValues").build().toString()
        def versionPropSheetUrl = UriBuilder.fromUri(url).segment("property", "propSheet", propSheetPathToUpdate, "allPropValues").build().toString()
        
        def propertiesJson = new JSONObject()
        
        def existingProps = httpHelper.getContent(versionPropSheetGetUrl)
        def existingProperties = new JSONArray(existingProps)
        for (int i=0; i<existingProperties.length(); i++) {
            def propJson = existingProperties.get(i)
            propertiesJson.put(propJson.get("name"), propJson.get("value"))
        }
        
        for (def propertyName : propertiesToSet.keySet()) {
            def propertyValue = propertiesToSet.getProperty(propertyName) ?: ""
            println "Updating property ${propertyName} with value ${propertyValue}"
            propertiesJson.put(propertyName, propertyValue)
        }
        def headerProps = new HashMap<String, String>()
        headerProps.put("version", String.valueOf(propSheetVersion))
        httpHelper.putContentWithHeaders(versionPropSheetUrl, propertiesJson.toString(), headerProps)
        
        println "${componentName} ${versionName} properties updated successfully"
    }
    
    private String getPropDefsUrl(String url, String componentName) {
        // you can only create properties on the version that are defined on the component
        def componentUrl = UriBuilder.fromUri(url).segment("rest", "deploy", "component", componentName).build().toString()
        println "Component URL: ${componentUrl}"
        def componentContent = httpHelper.getContent(componentUrl)
        println "Component JSON:\n${componentContent}"
        
        def componentJson = new JSONObject(componentContent)
        def componentId = componentJson.getString("id")
        def propSheetDefPath = componentJson.getJSONObject("versionPropSheetDef").getString("path")
        propSheetDefPath += "." + componentJson.getJSONObject("versionPropSheetDef").getString("version")
        def propDefsUrl = UriBuilder.fromUri(url).segment("property", "propSheetDef", propSheetDefPath, "propDefs").build().toString()

    }
}
