/*
 * Licensed Materials - Property of IBM Corp.
 * IBM UrbanCode Build
 * IBM UrbanCode Deploy
 * IBM UrbanCode Release
 * (c) Copyright IBM Corporation 2017. All Rights Reserved.
 *
 * U.S. Government Users Restricted Rights - Use, duplication or disclosure restricted by
 * GSA ADP Schedule Contract with IBM Corp.
 */
 import com.urbancode.air.AirPluginTool
 import com.urbancode.air.plugin.kubernetes.KubernetesHelper
 import com.urbancode.air.plugin.kubernetes.HelmHelper
 import com.urbancode.ud.client.ResourceClient
 import org.codehaus.jettison.json.JSONObject;
 import org.codehaus.jettison.json.JSONArray;

 // Get step properties
 AirPluginTool apTool = new AirPluginTool(this.args[0], this.args[1])
 Properties inProps   = apTool.getStepProperties()
 String chart         = inProps['chart']?.trim();
 String version       = inProps['version']?.trim();
 String releaseName   = inProps['releaseName']?.trim();
 String flags         = inProps['flags']?.trim();
 String serverUrl     = inProps['serverUrl']?.trim();
 String resourceId    = inProps['resourceId']?.trim();
 String path          = inProps['path'].trim();
 String kubeconfig    = inProps['kubeconfig'].trim();

 // Set up helper
 if (!path) {
   path = "helm"
 }
 File workDir = new File(".").canonicalFile
 KubernetesHelper kh = new KubernetesHelper(workDir, path)
 if (kubeconfig) {
   kh.addEnvironmentVariable("KUBECONFIG", kubeconfig);
 }

 // Step specific commands
 ArrayList args = []
 args << 'install'
 if (HelmHelper.getHelmMajorVersion(kh) > 2) {
   if (releaseName) {
     args << releaseName
   }
   else {
     args << '--generate-name'
   }
 }
 else {
  if (releaseName) {
    args << '--name'
    args << releaseName
  }
 }
 args << chart
 if (version) {
   args << '--version'
   args << version
 }
 kh.setFlags(args, flags)
 output = (kh.getOutputFromCommand('[action] Installing chart ' + chart, args, 'Chart ' + chart + ' installed', 'Could not install chart ' + chart)) 

 // get the release name returned by Helm (especially needed if user chose to let helm generate a name for them)
 // we assume the first line returned from helm is in the format NAME: releaseName
 outputArray = output.split("\n");
 firstLine = outputArray[0];
 returnedreleaseName = firstLine.substring(5).trim()
 println "[info] The release is named " + returnedreleaseName

 // set the release name as an output property
 apTool.setOutputProperty("helm.release", returnedreleaseName);
 apTool.setOutputProperties();

 // update the resource role property to store the release name, if desired
 if (resourceId) {
   serverUri = KubernetesHelper.stringToUri(serverUrl)
   username = apTool.getAuthTokenUsername()
   password = apTool.getAuthToken()
   ResourceClient resourceClient = new ResourceClient(serverUri,  username, password)

   // the group of resource role properties has a name.
   // by default, the group of resource role properties has the same name as the resource role,
   // however, if the resource role name is changed, the resource role properties name does not.
   // so, we need to get the resource role properties name in order to set the helm.release property.
   // i don't see how it is possible, but ucd returns an array of resource role property groups, so
   // maybe it is possible to have multiple resource role property groups.

   println "[info] Searching resource role properties..."
   // get all resource roles
   resourceRoles = resourceClient.getResourceRoles(resourceId);
   def resourceRolePropertiesName = "";

   try {
     if (resourceRoles.length() > 0) {
       for (int i = resourceRoles.length() - 1; i >= 0; i--) {
         JSONObject obj = resourceRoles.getJSONObject(i);
         println "[info] Found resource role properties named " + obj.getString("name");
         // get the propDefs for this resource role properties group,
         // then see if it contains a property named helm.release
         propDefsString = obj.getString("propDefs");
         JSONArray propDefs = new JSONArray(propDefsString);
         if (propDefs.length() > 0) {
           for (int j = propDefs.length() - 1; j >= 0; j--) {
             JSONObject pdObj = propDefs.getJSONObject(j);
             pdName = "";
             try {
               pdName = pdObj.getString("name");
             }
             catch (NullPointerException) {
               // swallow
             }
             if (pdName.equals("helm.release")) {
               println "[info] Found property helm.release inside resource role properties named " + obj.getString("name");
               if (resourceRolePropertiesName.equals("")) {
                 resourceRolePropertiesName = obj.getString("name");
               }
               else {
                 throw new RuntimeException("Found more than one resource role property named helm.release.");
               }
             }
           }
         }
       }
     }
   }
   catch (Exception e) {
     println "[warn] Exception when trying to deterime the name of the resource role properties to use: " + e;
     println "[warn] Could not determine the name of the resource role properties to use. Defaulting to name of the resource.";
     resource = resourceClient.getResourceById(resourceId)
     resourceRolePropertiesName = resource.name;
   }

   if (resourceRolePropertiesName == "") {
     throw new RuntimeException("Could not find the resource role property containing the helm.release property.");
   }

   resourceClient.setResourceRoleProperty(resourceRolePropertiesName, resourceId, "helm.release", returnedreleaseName)
   println "[info] Resource role property helm.release has been set to " + returnedreleaseName
 }

