/**
* 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.LocalLBLBMethod
import iControl.CommonIPPortDefinition
import iControl.LocalLBMonitorRule
import iControl.LocalLBMonitorRuleType
import iControl.LocalLBPoolMonitorAssociation
import iControl.CommonEnabledState
import iControl.LocalLBServiceDownAction

public class F5Pool extends F5Server{
    def poolName

    // Constructor for F5Pool class
    public F5Pool(Map<String,String> props) {
        super(props)
        this.poolName = getPoolName()
    }

    // Retrieves the pool name and parses the text into a useable format
    public String getPoolName() {
        if (!poolName) {
            if (getMajorVersion() < 11 || !folder) {
                poolName = props['poolName']?.trim().replaceAll("\\s","")
            }
            else {
                poolName = getFolderName() + props['poolName']?.trim().replaceAll("\\s","")
            }
        }
        return poolName

    }

    // Check if pool does (true) or does not exist (false).
    public boolean doesPoolExist() {
        println "Does pool exist..."
        def result = false
        for (pool in getConnection().getLocalLBPool().get_list()) {
            if (poolName.equalsIgnoreCase(pool)) {
                result = true
                break
            }
        }

        if (result) {
            println "Pool ${poolName} exists."
        }
        else {
            println "Pool ${poolName} does not exist."
        }

        return result
    }

    // Create a pool with the given load balancing parameter
    public void createPool(String lbMethod) {
        if(!doesPoolExist()) {
            println "Creating ${poolName} with $lbMethod load balancing"
            def poolStub = getConnection().getLocalLBPool()
            poolStub.setTimeout(timeout * 1000)
            poolStub.create(
                    [poolName] as String[],
                    [LocalLBLBMethod.fromString(lbMethod)] as LocalLBLBMethod[],
                    new CommonIPPortDefinition[1][0])
            if (doesPoolExist()) {
                println "Pool successfully created!"
            }
            else {
                throw new Exception("Could not create pool!")
            }
        } else {
            println "Pool $poolName already exists. Modifying existing pool..."
            setPoolLBMethod(lbMethod)
        }
    }

    // Sets the pool's load balance method
    public void setPoolLBMethod(String lbMethod) {
        println "Setting load balancing method to ${lbMethod}..."
        getConnection().getLocalLBPool().set_lb_method([poolName] as String[],
        [
            LocalLBLBMethod.fromString(lbMethod)] as LocalLBLBMethod[])
        println "Pool successfully updated! LBMethod"
    }

    // Set the pool's monitors
    public void addPoolMonitors(String[] monitorArray) {
        println "Updating pool monitors to ${monitorArray}"
        def monitorRule = new LocalLBMonitorRule(
                LocalLBMonitorRuleType.MONITOR_RULE_TYPE_AND_LIST,
                0,
                monitorArray)
        getConnection().getLocalLBPool().set_monitor_association(
                new LocalLBPoolMonitorAssociation(poolName, monitorRule))
    }

    // Set the pool's SNAT state
    public void setPoolAllowSNATState(String allowSnat) {
        println "Update Allow SNAT to ${allowSnat}"
        getConnection().getLocalLBPool().set_allow_snat_state(
                [poolName] as String[], [
                    CommonEnabledState.fromString(allowSnat)] as CommonEnabledState[])
    }

    // Set the pool's NAT state
    public void setPoolAllowNATState(String allowNat) {
        println "Update Allow NAT to ${allowNat}"
        getConnection().getLocalLBPool().set_allow_nat_state(
                [poolName] as String[], [
                    CommonEnabledState.fromString(allowNat)] as CommonEnabledState[])
    }

    // Set the pool's Action on Service Down to another pool member
    public void setPoolActionOnServiceDown(String serviceDownAction) {
        println "Update Action On Service Down to ${serviceDownAction}"
        getConnection().getLocalLBPool().set_action_on_service_down(
                [poolName] as String[],
                [LocalLBServiceDownAction.fromString(serviceDownAction)]
                as LocalLBServiceDownAction[])
    }

    // Set the pool's Slow Ramp Time
    public void setPoolSlowRampTime(String slowRampTime) {
        println "Update Slow Ramp Time to ${slowRampTime}"
        getConnection().getLocalLBPool().set_slow_ramp_time(
                [poolName] as String[],
                [Long.parseLong(slowRampTime)] as long[])
    }

    // Set the pool's client IP TOS
    public void setPoolClientIPTOS(String clientIpTos) {
        println "Update IP ToS to Client to ${clientIpTos}"
        getConnection().getLocalLBPool().set_client_ip_tos(
                [poolName] as String[],
                [Long.parseLong(clientIpTos)] as long[])
    }

    // Set the pool's server IP TOS
    public void setPoolServerIPTOS(String serverIpTos) {
        println "Update IP ToS to Server to ${serverIpTos}"
        getConnection().getLocalLBPool().set_server_ip_tos(
                [poolName] as String[],
                [Long.parseLong(serverIpTos)] as long[])
    }

    // Set the pool's client Link QOS
    public void setPoolClientLinkQOS(String clientLinkQos) {
        println "Update QoS to Client to ${clientLinkQos}"
        getConnection().getLocalLBPool().set_client_link_qos(
                [poolName] as String[],
                [Long.parseLong(clientLinkQos)] as long[])
    }

    // Set the pool's server Link QOS
    public void setPoolServerLinkQOS(String serverLinkQos) {
        println "Update QoS to Server to ${serverLinkQos}"
        getConnection().getLocalLBPool().set_server_link_qos(
                [poolName] as String[],
                [Long.parseLong(serverLinkQos)] as long[])
    }

    // Remove pool monitors
    // Used before adding new pool monitors
    public void removePoolMonitors() {
        println "Removing pool monitors..."
        getConnection().getLocalLBPool().remove_monitor_association([poolName] as String[])
    }

    // Remove pool from the F5 server
    public void deletePool() {
        if (doesPoolExist()) {
            println "Deleting ${poolName}"
            def poolStub = getConnection().getLocalLBPool()
            poolStub.setTimeout(timeout * 1000)
            poolStub.delete_pool(
                    [poolName] as String[])
            if (doesPoolExist()) {
                throw new Exception("Could not delete pool!")
            }
            else {
                println "Pool successfully deleted!"
            }
        } else {
            throw new Exception("Cannot delete a pool that does not exist!")
        }
    }
}
