/**
* Licensed Materials - Property of IBM* and/or HCL**
* IBM UrbanCode Deploy
* (c) Copyright IBM Corporation 2011, 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.ibm.rational.air.plugin.worklight;

/**
* A utility class for helping to run the Worklight commands.
**/
public class Util {
    /**
    * Constants defining the Worklight Server versions.
    **/
    public static String WL_SERVER_60 = "6.0";
    public static String WL_SERVER_61 = "6.1";
    public static String WL_SERVER_62 = "6.2";
    public static String WL_SERVER_63 = "6.3";
    public static String WL_SERVER_70 = "7.0";
    public static String WL_SERVER_71 = "7.1";
    // Starts REST API support
    public static String WL_SERVER_80 = "8.0";

    /**
    * Handles determining server/client compatibility.
    * serverpath: The URL for the Worklight Server.
    * worklightAntJar: The client JAR for connecting to the server.
    * Returns the server version of the current configuration if the server
    *   and client JAR match. Otherwise, returns null.
    **/
    public static String determineServerVersion(File worklightAntJar, String serverpath,
        String user, String password, boolean secure) {
        def serverVersion = determineRuntimeVersion(worklightAntJar, serverpath, user,
            password, secure);
        // If not 8.0, assume Ant JAR deployments
        if (serverVersion != WL_SERVER_80) {
            def deployerVersion = determineDeployerJARVersion(worklightAntJar);
            if(deployerVersion == serverVersion) {
                return serverVersion;
            }
        } else {
            return serverVersion;
        }
        return null;
    }

    /**
    * Determine the version of the Worklight Ant Deployer JAR file using the property
    * files provided within the Ant JAR file.
    * worklightAntJar: The Worklight Ant Deployer JAR file to determine the version for.
    * Returns the version of the Worklight Ant Deployer JAR file using the WL_SERVER
    *   constants.
    **/
    private static String determineDeployerJARVersion(File worklightAntJar) {
        if(!worklightAntJar.isFile()) {
            println "Error: The path to the Worklight Ant Deployer JAR file is invalid.";
            System.exit(-1);
        }

        /*
        * wlPlatformVersion.properties could also be used, but is not available in all
        * client JAR versions.
        */
        def ant = new AntBuilder();
        ant.loadproperties( resource: "com/worklight/ant/worklight.properties",
            classpath: worklightAntJar.canonicalPath );

        def clientVersion = ant.project.properties.VERSION;
        def result;
        if(clientVersion == null) {
            println "Error: Unknown Worklight Ant Deployer JAR file version.";
            System.exit(-1);
        } else if(clientVersion.startsWith(WL_SERVER_60)) {
            result = WL_SERVER_60;
        } else if(clientVersion.startsWith(WL_SERVER_61)) {
            result = WL_SERVER_61;
        } else if(clientVersion.startsWith(WL_SERVER_62)) {
            result = WL_SERVER_62;
        } else if(clientVersion.startsWith(WL_SERVER_63)) {
            result = WL_SERVER_63;
        }else if(clientVersion.startsWith(WL_SERVER_70)) {
            result = WL_SERVER_70;
        }else if(clientVersion.startsWith(WL_SERVER_71)) {
            result = WL_SERVER_71;
        } else {
            println "Error: Unsupported Worklight Ant Deployer JAR file version.";
            System.exit(-1);
        }

        println "Deployer JAR Version: ${clientVersion}";
        return result;
    }

    /**
    * Determine the version of the Worklight Server runtime that is running using JAR Ant API.
    * worklightAntJar: The Worklight Ant Deployer JAR file to connect to the WL 6.2 or
    *   newer server.
    * serverpath: The URL of the Worklight Server.
    * user: The username.
    * password: The user password.
    * secure: Whether to connect using a secure method (for WL 6.2).
    * Returns the version of the Worklight Server runtime using the WL_SERVER constants.
    **/
    private static String determineRuntimeVersion(File worklightAntJar, String serverpath,
        String user, String password, boolean secure) {
        // When migrating a plug-in, the password may be an empty String; reset it to null.
        if(user?.trim()?.length() == 0) {
            user = null;
        }
        if(password?.trim()?.length() == 0) {
            password = null;
        }
        // First try to see if the server is version 6.0, 6.1, or 8.0 using REST.
        WLRestClient wlrc = new WLRestClient(URI.create(serverpath), user, password);
        def serverVersion = wlrc.getServerVersion();
        def result;
        if(serverVersion == null) {
            // Try checking if it is a server version newer than 6.1
            def ant = getWLADMAnt(worklightAntJar);
            try {
                ant.wladm ( url:serverpath, user:user, password:password, secure:secure ) {
                    'show-info' ( outputproperty:"version" )
                }
            } catch (Exception e) {
                println "Unable to find the server version using the wladm Ant task - ${e.message}";
            }

            serverVersion = ant.project.properties.version;
            if(serverVersion != null) {
                serverVersion = serverVersion.split(".*productVersion=\"");
                if(serverVersion?.size() >= 2) {
                    serverVersion[1].find(~/^\d.\d/) { version ->
                        result = version;
                    }
                }
            }
        } else if(serverVersion.startsWith(WL_SERVER_60)) {
            result = WL_SERVER_60;
        } else if(serverVersion.startsWith(WL_SERVER_61)) {
            result = WL_SERVER_61;
        } else if(serverVersion.startsWith(WL_SERVER_80)) {
            result = WL_SERVER_80;
        } else {
            println "Error: Unsupported Worklight Server version.";
            System.exit(-1);
        }

        println "Server Version: ${serverVersion}";
        return result;
    }

    /**
    * Provides access to the wladm Ant tasks by setting up the AntBuilder.
    * worklightAntJar: The Worklight Ant Deployer JAR file containing the Ant task
    *   definition.
    * Returns the AntBuilder to use for calling the wladm Ant tasks.
    **/
    public static def getWLADMAnt(File worklightAntJar) {
        def ant = new AntBuilder();
        try {
            ant.taskdef ( resource: "com/worklight/ant/deployers/antlib.xml",
                classpath: worklightAntJar.absolutePath )
        } catch (Exception e) {
            println "Error: The resource file com.worklight.ant.deployers.antlib.xml" +
                    "is not found in the specified Worklight Ant Deployer JAR file: " +
                    "${worklightAntJar.getCanonicalPath()}."
            println "Explanation: This error occurs if the JAR file specified in the " +
                    "Worklight Ant JAR File Path attribute is not correct."
            println "User response: Change the value of the Worklight Ant JAR File Path " +
                    "attribute to the path to the Worklight Ant Deployer JAR file. For " +
                    "example, use " +
                    "/opt/IBM/Worklight/WorklightServer/worklight-ant-deployer.jar."
            System.exit(-1)
        }
        return ant;
    }

    /**
    * Determines if the supplied Worklight Ant Deployer JAR file is valid.
    * worklightAntJar: The Worklight Ant Deployer JAR file to check.
    * Returns whether the JAR file is valid.
    **/
    public static boolean isWorklightDeployerAntJar(File worklightAntJar) {
        return (determineDeployerJARVersion(worklightAntJar) != null);
    }


    /**
    * Takes a string, separates it based on commas and new lines
    * Then places each new element into a String array
    * Can choose to remove all spaces or just trim()
    * Use Case: Parse names, IP Addresses, and when any character can be entered
    * Only removes beginning and ending whitespace
    */
    public static def text2List(String input) {
        return text2List(input, false)
    }

    /**
    * Can specify to remove all whitespace
    */
    public static def text2List(String input, boolean removeAllSpaces) {
        def output = []
        if (input) {
            output = input.replaceAll('\n', ',').split(',').findAll{
                it && it.trim().size() > 0
            }
            if (removeAllSpaces) {
                output = output.collect {it.replaceAll("\\s","")}
            }
            else {
                output = output.collect {it.trim()}
            }
        }
        return output
    }
}
