import org.lsst.ccs.description.groovy.CCSBuilder
import org.lsst.ccs.bootstrap.BootstrapResourceUtils
import org.lsst.ccs.subsystem.power.PowerControl
import org.lsst.ccs.subsystem.power.BK1696Device
import org.lsst.ccs.subsystem.power.CpfeDevice
import org.lsst.ccs.subsystem.power.SimPowerDevice
import org.lsst.ccs.subsystem.power.RebPsDevice
import org.lsst.ccs.subsystem.power.RebPowerSupplyMain
import org.lsst.ccs.subsystem.power.PowerSupplyConfiguration;
import org.lsst.ccs.subsystem.power.RebPowerSupplyWiring;
import org.lsst.ccs.subsystem.power.RebPowerSupplyNode;
import org.lsst.ccs.subsystem.power.RebPsHVRegulator;
import org.lsst.ccs.subsystem.power.CornerRaftRebPowerSupplyNode;
import org.lsst.ccs.subsystem.power.alerts.RebPowerAlertType;
import org.lsst.ccs.subsystem.power.RebPowerAlarm;
import org.lsst.ccs.subsystem.power.EmergencyResponseManager;
import org.lsst.ccs.monitor.Alarm;
import org.lsst.ccs.monitor.Channel
import org.lsst.ccs.subsystem.power.RebPsBoardAlarm;
import org.lsst.ccs.subsystem.common.RebTotalPower;

RebPowerSupplyWiring wiring = new RebPowerSupplyWiring(buildProperties());

CCSBuilder builder = ["rebpower"]

builder.main(RebPowerSupplyMain) {

    emergencyResponseManager (EmergencyResponseManager)

    for ( PowerSupplyConfiguration powerSupply : wiring.getRebPowerSuppyConfigurations() ) {
        def psName = powerSupply.getName();

        "RebPS/${psName}" (RebPsDevice, rebsList: powerSupply.getRebs(), isCornerRaft : powerSupply.isCornerRaft ) {
            

            BoardTemperatureAlarm   (RebPsBoardAlarm, alertType:RebPowerAlertType.REB_PS_BOARD_TEMPERATURE_TOO_HIGH)
            
            
            for (int i = 0; i < 7; i++) {
                if ( i == 5 ) {
                    "BoardTemp$i" (Channel, description: "Board temperature $i", units: "\u00b0C",
                            checkHi:"alarm", alarmHi:"RebPS/${psName}/BoardTemperatureAlarm",                       
                               hwChan: i, type: "TEMP")
                } else {
                    "BoardTemp$i" (Channel, description: "Board temperature $i", units: "\u00b0C",
                               hwChan: i, type: "TEMP")
                    
                }
            }  
            "FPGATemp" (Channel, description: "FPGA temperature", units: "\u00b0C", hwChan: 7, type: "TEMP")

            "TripState" (Channel, doNotTrend: true, description: "Trip Status", units: "unitless", hwChan: -1, type: "STATE")
        }
    }

   for ( String reb : wiring.getRebsList() ) {

        PowerSupplyConfiguration powerSupplyConfig = wiring.getPowerSupplyConfigurationForReb("$reb");

        int i = wiring.getPowerSupplyChannelForReb("$reb");

        boolean isCornerRaft = powerSupplyConfig.isCornerRaft();

        "${reb}" ( isCornerRaft ? CornerRaftRebPowerSupplyNode : RebPowerSupplyNode, powerSupplyConfiguration:powerSupplyConfig, channel:i) {

            def powerSupply = "RebPS/"+powerSupplyConfig.getName();

            def psn = "digital"

            "${psn}/VbefLDO" (Channel, description: "$reb $psn PS\\Voltage before LDO", units: "Volts",
                                     devcName: "$powerSupply", hwChan: 0, type: "$i:$psn")

            "${psn}/IbefLDO" (Channel, description: "Current before LDO", format: ".1f", units: "mA",
                                     devcName: "$powerSupply", hwChan: 1, type: "$i:$psn", scale: 1000)

            "${psn}/VaftLDO" (Channel, description: "Voltage after LDO", units: "Volts",
                                     devcName: "$powerSupply", hwChan: 2, type: "$i:$psn")

            "${psn}/IaftLDO" (Channel, description: "Current after LDO", format: ".1f", units: "mA",
                                     devcName: "$powerSupply", hwChan: 3, type: "$i:$psn", scale: 1000)

            "${psn}/VaftSwch" (Channel, description: "Voltage after switch", units: "Volts",
                                      devcName: "$powerSupply", hwChan: 4, type: "$i:$psn")

            psn = "analog"

            "${psn}/VbefLDO" (Channel, description: "$reb $psn PS\\Voltage before LDO", units: "Volts",
                                     devcName: "$powerSupply", hwChan: 0, type: "$i:$psn")

            "${psn}/IbefLDO" (Channel, description: "Current before LDO", format: ".1f", units: "mA",
                                     devcName: "$powerSupply", hwChan: 1, type: "$i:$psn", scale: 1000)

            "${psn}/VaftLDO" (Channel, description: "Voltage after LDO", units: "Volts",
                                     devcName: "$powerSupply", hwChan: 2, type: "$i:$psn")

            "${psn}/IaftLDO" (Channel, description: "Current after LDO", format: ".1f", units: "mA",
                                     devcName: "$powerSupply", hwChan: 3, type: "$i:$psn", scale: 1000)

            "${psn}/VaftSwch" (Channel, description: "Voltage after switch", units: "Volts",
                                      devcName: "$powerSupply", hwChan: 4, type: "$i:$psn")

            psn = "OD"

            "${psn}/VbefLDO" (Channel, description: "$reb $psn PS\\Voltage before LDO", units: "Volts",
                                     devcName: "$powerSupply", hwChan: 0, type: "$i:$psn")

            "${psn}/IbefLDO" (Channel, description: "Current before LDO", format: ".1f", units: "mA",
                                     devcName: "$powerSupply", hwChan: 1, type: "$i:$psn", scale: 1000)

            "${psn}/VaftLDO" (Channel, description: "Voltage after LDO", units: "Volts",
                                     devcName: "$powerSupply", hwChan: 2, type: "$i:$psn")

            "${psn}/VaftLDO2" (Channel, description: "Voltage after LDO2", units: "Volts",
                                      devcName: "$powerSupply", hwChan: 5, type: "$i:$psn")

            "${psn}/IaftLDO" (Channel, description: "Current after LDO", format: ".1f", units: "mA",
                                     devcName: "$powerSupply", hwChan: 3, type: "$i:$psn", scale: 1000)

            "${psn}/VaftSwch" (Channel, description: "Voltage after switch", units: "Volts",
                                      devcName: "$powerSupply", hwChan: 4, type: "$i:$psn")

            psn = "clockhi"

            "${psn}/VbefLDO" (Channel, description: "$reb $psn PS\\Voltage before LDO", units: "Volts",
                                     devcName: "$powerSupply", hwChan: 0, type: "$i:$psn")

            "${psn}/IbefLDO" (Channel, description: "Current before LDO", format: ".1f", units: "mA",
                                     devcName: "$powerSupply", hwChan: 1, type: "$i:$psn", scale: 1000)

            "${psn}/VaftLDO" (Channel, description: "Voltage after LDO", units: "Volts",
                                     devcName: "$powerSupply", hwChan: 2, type: "$i:$psn")

            "${psn}/IaftLDO" (Channel, description: "Current after LDO", format: ".1f", units: "mA",
                                     devcName: "$powerSupply", hwChan: 3, type: "$i:$psn", scale: 1000)

            "${psn}/VaftSwch" (Channel, description: "Voltage after switch", units: "Volts",
                                      devcName: "$powerSupply", hwChan: 4, type: "$i:$psn")

            psn = "clocklo"

            "${psn}/VbefLDO" (Channel, description: "$reb $psn PS\\Voltage before LDO", units: "Volts",
                                     devcName: "$powerSupply", hwChan: 0, type: "$i:$psn")

            "${psn}/IbefLDO" (Channel, description: "Current before LDO", format: ".1f", units: "mA",
                                     devcName: "$powerSupply", hwChan: 1, type: "$i:$psn", scale: 1000)

            "${psn}/VaftLDO" (Channel, description: "Voltage after LDO", units: "Volts",
                                     devcName: "$powerSupply", hwChan: 2, type: "$i:$psn")

            "${psn}/VaftLDO2" (Channel, description: "Voltage after LDO2", units: "Volts",
                                      devcName: "$powerSupply", hwChan: 5, type: "$i:$psn")

            "${psn}/IaftLDO" (Channel, description: "Current after LDO", format: ".1f", units: "mA",
                                     devcName: "$powerSupply", hwChan: 3, type: "$i:$psn", scale: 1000)

            "${psn}/VaftSwch" (Channel, description: "Voltage after switch", units: "Volts",
                                      devcName: "$powerSupply", hwChan: 4, type: "$i:$psn")




            if ( isCornerRaft ) {
                int heaterChannel = wiring.getPowerSupplyChannelForRebHeater("$reb");

                if ( heaterChannel >= 0 ) {
                    psn = "heater"
                    apsn = "digital"
                    

                    "${psn}/VbefLDO" (Channel, description: "$reb $psn PS\\Voltage before LDO", units: "Volts",
                                             devcName: "$powerSupply", hwChan: 0, type: "$heaterChannel:$apsn")

                    "${psn}/IbefLDO" (Channel, description: "Current before LDO", format: ".1f", units: "mA",
                                             devcName: "$powerSupply", hwChan: 1, type: "$heaterChannel:$apsn", scale: 1000)

                    "${psn}/VaftLDO" (Channel, description: "Voltage after LDO", units: "Volts",
                                             devcName: "$powerSupply", hwChan: 2, type: "$heaterChannel:$apsn")

                    "${psn}/IaftLDO" (Channel, description: "Current after LDO", format: ".1f", units: "mA",
                                             devcName: "$powerSupply", hwChan: 3, type: "$heaterChannel:$apsn", scale: 1000)

                    "${psn}/VaftSwch" (Channel, description: "Voltage after switch", units: "Volts",
                                              devcName: "$powerSupply", hwChan: 4, type: "$heaterChannel:$apsn")
                }


                psn = "dphi"

                "${psn}/VbefLDO" (Channel, description: "$reb $psn PS\\Voltage before LDO", units: "Volts",
                                         devcName: "$powerSupply", hwChan: 0, type: "$i:$psn")

                "${psn}/IbefLDO" (Channel, description: "Current before LDO", format: ".1f", units: "mA",
                                         devcName: "$powerSupply", hwChan: 1, type: "$i:$psn", scale: 1000)

                "${psn}/VaftLDO" (Channel, description: "Voltage after LDO", units: "Volts",
                                         devcName: "$powerSupply", hwChan: 2, type: "$i:$psn")

                "${psn}/IaftLDO" (Channel, description: "Current after LDO", format: ".1f", units: "mA",
                                         devcName: "$powerSupply", hwChan: 3, type: "$i:$psn", scale: 1000)

                "${psn}/VaftSwch" (Channel, description: "Voltage after switch", units: "Volts",
                                          devcName: "$powerSupply", hwChan: 4, type: "$i:$psn")

            } else {

                psn = "heater"

                "${psn}/VbefLDO" (Channel, description: "$reb $psn PS\\Voltage before LDO", units: "Volts",
                                         devcName: "$powerSupply", hwChan: 0, type: "$i:$psn")

                "${psn}/IbefLDO" (Channel, description: "Current before LDO", format: ".1f", units: "mA",
                                         devcName: "$powerSupply", hwChan: 1, type: "$i:$psn", scale: 1000)

                "${psn}/VaftLDO" (Channel, description: "Voltage after LDO", units: "Volts",
                                         devcName: "$powerSupply", hwChan: 2, type: "$i:$psn")

                "${psn}/IaftLDO" (Channel, description: "Current after LDO", format: ".1f", units: "mA",
                                        devcName: "$powerSupply", hwChan: 3, type: "$i:$psn", scale: 1000)

                "${psn}/VaftSwch" (Channel, description: "Voltage after switch", units: "Volts",
                                        devcName: "$powerSupply", hwChan: 4, type: "$i:$psn")
            }

            psn = "hvbias"

            "${psn}/HvBiasVoltageTooHigh"  (RebPowerAlarm, alertType:RebPowerAlertType.HVBIAS_VOLTAGE_TOO_HIGH)
            "${psn}/HvBiasCurrentTooHigh"  (RebPowerAlarm, alertType:RebPowerAlertType.HVBIAS_CURRENT_TOO_HIGH)


            "${psn}/VbefSwch" (Channel, description: "$reb $psn PS\\Voltage before switch", units: "Volts",
                                    devcName: "$powerSupply", hwChan: 0, type: "$i:$psn",
                            checkLo:"none",
                            checkHi:"alarm", alarmHi:"${reb}/${psn}/HvBiasVoltageTooHigh")

// see: https://github.com/lsst-camera-ccs/org-lsst-ccs-drivers-auxelex/blob/main/src/main/java/org/lsst/ccs/drivers/auxelex/RebPS.java   ...  CHAN_VOLT_DAC = -1,

            "${psn}/DAC" (Channel, description: "DAC setting", units: "unitless",
                                    devcName: "$powerSupply", hwChan: -1, type: "$i:$psn",
				    checkLo:"none", checkHi:"none")
//				    ,
//				    checkLo:"none", checkHi:"none", alarmLo:"none", alarmHi:"none")

            "${psn}/IbefSwch" (Channel, description: "Current before switch", format: ".3f", units: "mA",
                                    devcName: "$powerSupply", hwChan: 1, type: "$i:$psn", scale: 1000,
                            checkLo:"none",
                            checkHi:"alarm", alarmHi:"${reb}/${psn}/HvBiasCurrentTooHigh")

            "Power"           (Channel, description: "$reb all PSs\\Total power", units: "Watts",
                                    devcName: "$powerSupply", hwChan: 0, type: "$i:POWER")

            "RebState" (Channel, doNotTrend: true, description: "$reb Power State", units: "unitless",
                                    devcName: "$powerSupply",  hwChan:i, type: "STATE")
        }
    }
    
    "RebTotalPower" (RebTotalPower, description:"Reb Total Power", units:"Watts")    

    "HVRegulator" (RebPsHVRegulator)

 }
