/**
* Licensed Materials - Property of IBM* and/or HCL**
* IBM 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.f5
import iControl.*
import iControl.LocalLBRuleRuleDefinition
import iControl.LocalLBRuleRuleStatistics
import iControl.CommonStatistic
import iControl.CommonULong64
import iControl.LocalLBVirtualServerVirtualServerStatisticEntry

public class F5iRule extends F5Server{

    // Constructor for F5iRule
    public F5iRule(Map<String,String> props) {
        super(props)
    }

    // Retrieves a String list of all iRules in the given partition
    public String[] getiRuleList() {
        return getConnection().getLocalLBRule().get_list()
    }

    // Confirms if an iRule exists
    // Will confirm with the partition's up-to-date list
    public Boolean doesiRuleExist(String rule) {
        for (iterRule in getiRuleList()) {
            if (rule == iterRule) {
                return true
            }
        }
        return false
    }

    // Confirms if an iRule exists within the given list
    // Useful to minimize unecessary getiRuleList() calls
    // Note: Only use a iRule list that was created immediately before this
    // call or else you might have a race condition
    public Boolean doesiRuleExist(String rule, String[] list) {
        for (iterRule in list) {
            if (rule == iterRule) {
                return true
            }
        }
        return false
    }

    // Create iRule: From iRule name and its definition code
    public int createiRule(String name, String definition) {
        def exitVal = 1
        if (!doesiRuleExist(name)) {
            println "Creating ${name}..."
            def ruleDef = (new LocalLBRuleRuleDefinition(name, definition)) as LocalLBRuleRuleDefinition[]
            def ruleStub = getConnection().getLocalLBRule()
            ruleStub.setTimeout(timeout * 1000)
            ruleStub.create(ruleDef)

            if (doesiRuleExist(name)) {
                println "iRule successfully created!"
                exitVal = 0
            }
            else {
                throw new Exception("Could not create iRule!")
            }
        }
        else {
            println "iRule ${name} already exists."
        }
        return exitVal
    }

    // Delete iRule using given iRule name
    public int deleteiRule(String name) {
        def exitVal = 1
        if (doesiRuleExist(name)) {
            println "Deleting ${name}..."
            def ruleStub = getConnection().getLocalLBRule()
            ruleStub.setTimeout(timeout * 1000)
            ruleStub.delete_rule([name] as String[])

            if (!doesiRuleExist(name)) {
                println "iRule successfully deleted!"
                exitVal = 0
            }
            else {
                throw new Exception("Could not delete iRule!")
            }
        }
        else {
            println "iRule ${name} does not exist."
        }
        return exitVal
    }

    // Retrieves the iRule Statistics of given iRules
    public LocalLBRuleRuleStatistics getiRuleStatistics(def names){
        println "Retrieve ${names} statistics..."
        def ruleStub = getConnection().getLocalLBRule()
        ruleStub.setTimeout(timeout * 1000)
        LocalLBRuleRuleStatistics ruleStats = ruleStub.get_statistics(names as String[])

        if (names.size() != ruleStats.getStatistics().size()) {
            println "WARNING: One or more iRules are empty and have no events assigned"
        }
        return ruleStats
    }

    /** Iterates through the Rule Statistics and prints them out in the following format:
     *  Rule: /Common/_sys_auth_ssl_cc_ldap
            Event Name: AUTH_RESULT
            Priority: 500
                STATISTIC_RULE_FAILURES : 0
                STATISTIC_RULE_ABORTS : 0
                STATISTIC_RULE_TOTAL_EXECUTIONS : 0
                STATISTIC_RULE_AVERAGE_CYCLES : 0
                STATISTIC_RULE_MAXIMUM_CYCLES : 0
                STATISTIC_RULE_MINIMUM_CYCLES : 0
                ...
      */
    public void printRuleStatistics(LocalLBRuleRuleStatistics ruleStats) {
        def t = ruleStats.time_stamp
        println "Statistics at ${t.getHour()}:${t.getMinute()}:${t.getSecond()} GMT on ${t.getMonth()}/${t.getDay()}/${t.getYear()}"
        def prevRule = ""
        for (rule in ruleStats.getStatistics()) {
            if (prevRule != rule.getRule_name()) {
                println "--------------------------------------------------------------"
                println "Rule: ${rule.getRule_name()}"
                prevRule = rule.getRule_name()
            }
            println "\tEvent Name: ${rule.getEvent_name()}"
            println "\tPriority: ${rule.getPriority()}"

            for (stat in rule.getStatistics()) {
                // stat.value contains two 32 bit numbers representing a 64 bit number
                def value64 = stat.getValue().getHigh() * 10**32 + stat.getValue().getLow()
                println "\t\t${stat.getType()} : ${value64}"
            }
        }
        println "--------------------------------------------------------------"
    }
}
