import org.lsst.ccs.description.groovy.CCSBuilder
import org.lsst.ccs.bootstrap.BootstrapResourceUtils
import org.lsst.ccs.subsystem.refrig.RefrigMain
import org.lsst.ccs.subsystem.refrig.ColdCompressor
import org.lsst.ccs.subsystem.refrig.CryoCompressor
import org.lsst.ccs.subsystem.refrig.FanControl
import org.lsst.ccs.subsystem.refrig.CompMaq20Device
import org.lsst.ccs.subsystem.refrig.CompMaq20PWMControl
import org.lsst.ccs.subsystem.refrig.CompPlutoDevice
import org.lsst.ccs.subsystem.refrig.A1000Device
import org.lsst.ccs.subsystem.refrig.SimCompMaq20Device
import org.lsst.ccs.subsystem.refrig.SimCompMaq20PWMControl
import org.lsst.ccs.subsystem.refrig.SimCompPlutoDevice
import org.lsst.ccs.subsystem.refrig.SimA1000Device
import org.lsst.ccs.subsystem.refrig.SimMaq20Device
import org.lsst.ccs.subsystem.refrig.SimMaq20DiscControl
import org.lsst.ccs.subsystem.refrig.SimMaq20PulseControl
import org.lsst.ccs.subsystem.refrig.SimMaq20AnalogControl
import org.lsst.ccs.subsystem.common.devices.dataforth.Maq20Device
import org.lsst.ccs.subsystem.common.devices.dataforth.Maq20DiscControl
import org.lsst.ccs.subsystem.common.devices.dataforth.Maq20PulseControl
import org.lsst.ccs.subsystem.common.devices.dataforth.Maq20AnalogControl
import org.lsst.ccs.subsystem.refrig.SubCoolingChannel
import org.lsst.ccs.monitor.Channel


import org.lsst.ccs.subsystem.refrig.ColdCompLimits
import org.lsst.ccs.subsystem.refrig.CryoCompLimits





Properties props = BootstrapResourceUtils.getBootstrapSystemProperties()

runMode = props.getProperty("org.lsst.ccs.run.mode", "normal")
if (runMode.equals("simulation")) {
    compMaq20Device = SimCompMaq20Device
    compMaq20PWMControl = SimCompMaq20PWMControl
    compPlutoDevice = SimCompPlutoDevice
    a1000Device = SimA1000Device
    maq20Device = SimMaq20Device
    maq20DiscControl = SimMaq20DiscControl
    maq20PulseControl = SimMaq20PulseControl
    maq20AnalogControl = SimMaq20AnalogControl
}
else {
    compMaq20Device = CompMaq20Device
    compMaq20PWMControl = CompMaq20PWMControl
    compPlutoDevice = CompPlutoDevice
    a1000Device = A1000Device
    maq20Device = Maq20Device
    maq20DiscControl = Maq20DiscControl
    maq20PulseControl = Maq20PulseControl
    maq20AnalogControl = Maq20AnalogControl
} 

coldPresent = props.getProperty("org.lsst.ccs.cold.present", "1,2")
coldSet = new HashSet()
if (!coldPresent.isEmpty()) {
   for (j in coldPresent.split(",")) {
        coldSet.add(Integer.decode(j.trim()) - 1)
    }
}
coldOrder = props.getProperty("org.lsst.ccs.cold.order", "1,2").split(",")
coldCircs = new int[coldOrder.length]
for (j = 0; j < coldCircs.length; j++) {
    coldCircs[j] = Integer.decode(coldOrder[j].trim()) - 1
}
coldNames = ["Cold1","Cold2"]
coolValveChans = [2, 0]
coolFlowChans = [1, 3]

cryoPresent = props.getProperty("org.lsst.ccs.cryo.present", "")
cryoSet = new HashSet()
if (!cryoPresent.isEmpty()) {
    for (j in cryoPresent.split(",")) {
        cryoSet.add(Integer.decode(j.trim()) - 1)
    }
}
cryoOrder = props.getProperty("org.lsst.ccs.cryo.order", "1,2,3,4,5,6").split(",")
cryoCircs = new int[cryoOrder.length]
for (j = 0; j < cryoCircs.length; j++) {
    cryoCircs[j] = Integer.decode(cryoOrder[j].trim()) - 1
}
cryoNames = ["Cryo1", "Cryo2", "Cryo3", "Cryo4", "Cryo5", "Cryo6"]

CCSBuilder builder = ["refrig"]

builder.main (RefrigMain) {

    ColdCompLimits (ColdCompLimits)
    CryoCompLimits (CryoCompLimits)

    CoolMaq20 (maq20Device, modules: ["VD"])

    for (j in coldSet) {

        comp = coldNames[coldCircs[j]]
        "$comp" (ColdCompressor, discTempChan: "DischrgTmp_P", discPressChan: "DischrgPrs",
                 suctTempChan: "SuctionTmp_P", cmprPowerChan: "CompPower", liquidTempChan: "LiquidTmp_P") {

            FanCtrl (FanControl, fanCntrl: ["$comp/Maq20/FanControl"],
                     ambientTemp: "$comp/AmbientTmp", cabinetTemp: "$comp/CabinetTmp")

            Plc (compPlutoDevice)

            Maq20 (compMaq20Device, modules: ["TTC", "DIOL:pwm:pulse", "DIOL:pulse:pulse", "VO"]) {

                FanControl (compMaq20PWMControl, modIndex: 1, funcIndex: 0, frequency: 200.0)

                PulseControl0 (maq20PulseControl, modIndex: 1, funcIndex: 1, pulsesPerRevn: 6)

                PulseControl1 (maq20PulseControl, modIndex: 2, funcIndex: 0, pulsesPerRevn: 6)

                PulseControl2 (maq20PulseControl, modIndex: 2, funcIndex: 1, pulsesPerRevn: 6)

                ValveControl (maq20AnalogControl, modIndex: 3, ranges: ["VP10", "VP10", "VP10"] as String[])

                LineControl  (maq20DiscControl, modIndex: 2)

            }

            Vfd (a1000Device)

            plc = "$comp/Plc"
            maq20 = "$comp/Maq20"
            vfd = "$comp/Vfd"

            DischrgTmp_P (Channel, description: "Discharge Temperature (PLC)", units: "\u00b0C", format: ".1f",
                          devcName: plc, hwChan: 1, type: "ADDREG:0", scale: 0.01)

            DischrgTmp_M (Channel, description: "Discharge Temperature (Maq20)", units: "\u00b0C", format: ".1f",
                          devcName: maq20, hwChan: 3, type: "0", subtype: "T220")

            DischrgPrs   (Channel, description: "Discharge Pressure", units: "psia", format: ".1f",
                          devcName: plc, hwChan: 1, type: "ADDREG:3", scale: 0.1)

            SuctionTmp_P (Channel, description: "Suction Temperature (PLC)", units: "\u00b0C", format: ".1f",
                          devcName: plc, hwChan: 1, type: "ADDREG:1", scale: 0.01)

            SuctionPrs   (Channel, description: "Suction Pressure", units: "psia", format: ".1f",
                          devcName: plc, hwChan: 1, type: "ADDREG:4", scale: 0.1)

            LiquidTmp_P  (Channel, description: "Liquid Temperature (PLC)", units: "\u00b0C", format: ".1f",
                          devcName: plc, hwChan: 1, type: "ADDREG:2", scale: 0.01)

            LiquidTmp_M  (Channel, description: "Liquid Temperature (Maq20)", units: "\u00b0C", format: ".1f",
                          devcName: maq20, hwChan: 1, type: "0", subtype: "T220")

            PriOilSepTmp (Channel, description: "Primary Oil Separator Temp", units: "\u00b0C", format: ".1f",
                          devcName: maq20, hwChan: 2, type: "0", subtype: "T220")

            SecOilSepTmp (Channel, description: "Secondary Oil Separator Temp", units: "\u00b0C", format: ".1f",
                          devcName: maq20, hwChan: 7, type: "0", subtype: "T220")

            CompVoltage  (Channel, description: "Compressor Voltage", units: "Volts", format: ".1f",
                          devcName: plc, hwChan: 1, type: "ADDREG:6", scale: 0.1)

            CompCurrent  (Channel, description: "Compressor Current", units: "Amps", format: ".1f",
                          devcName: plc, hwChan: 1, type: "ADDREG:5", scale: 0.01)

            CompPower    (Channel, description: "Compressor Power", units: "VA", format: ".1f",
                          devcName: plc, hwChan: 0, type: "ADDINT:9", scale: 0.001)

            CompVfdVolt  (Channel, description: "Compressor VFD Voltage", units: "Volts", format: ".1f",
                          devcName: vfd, hwChan: A1000Device.CHAN_VOLTAGE)

            CompVfdCurr  (Channel, description: "Compressor VFD Current", units: "Amps", format: ".1f",
                          devcName: vfd, hwChan: A1000Device.CHAN_CURRENT)

            CompVfdFreq  (Channel, description: "Compressor VFD Frequency", units: "Hz", format: ".1f",
                          devcName: vfd, hwChan: A1000Device.CHAN_FREQUENCY)

            CompVfdTemp  (Channel, description: "Compressor VFD Temperature", units: "\u00b0C", format: ".0f",
                          devcName: vfd, hwChan: A1000Device.CHAN_TEMPERATURE)

            HGBValvePosn (Channel, description: "HGB Valve Position", units: "%", format: ".1f",
                          devcName: maq20, hwChan: CompMaq20Device.CHAN_HGB_VALVE, type: "3", scale: 10.0)

            EEPRValvePosn (Channel, description: "EEPR Valve Position", units: "%", format: ".1f",
                           devcName: maq20, hwChan: CompMaq20Device.CHAN_EEPR_VALVE, type: "3", scale: 10.0)

            CoolValvePosn (Channel, description: "Coolant Valve Position", units: "%", format: ".1f",
                           devcName: "CoolMaq20", hwChan: coolValveChans[j], type: "0", subtype: "V10", scale: 10.0)

            CoolFlowRate (Channel, description: "Coolant Flow Rate", units: "l/min", format: ".2f",
                          devcName: "CoolMaq20", hwChan: coolFlowChans[j], type: "0", subtype: "V10", scale: 2.0)

            WaterInTmp   (Channel, description: "Water Inlet Temperature", units: "\u00b0C", format: ".1f",
                          devcName: maq20, hwChan: 0, type: "0", subtype: "T220")

            WaterOutTmp  (Channel, description: "Water Outlet Temperature", units: "\u00b0C", format: ".1f",
                          devcName: maq20, hwChan: 4, type: "0", subtype: "T220")

            CabinetTmp   (Channel, description: "Cabinet Temperature", units: "\u00b0C", format: ".1f",
                          devcName: maq20, hwChan: 6, type: "0", subtype: "T220")

            AmbientTmp   (Channel, description: "Ambient Temperature", units: "\u00b0C", format: ".1f",
                          devcName: maq20, hwChan: 5, type: "0", subtype: "T220")

            Fan1Speed    (Channel, description: "Fan 1 Speed", units: "rpm", format: ".0f",
                          devcName: maq20, hwChan: CompMaq20Device.CHAN_PULSE_RPM, type: "1", subtype: "1")

            Fan2Speed    (Channel, description: "Fan 2 Speed", units: "rpm", format: ".0f",
                          devcName: maq20, hwChan: CompMaq20Device.CHAN_PULSE_RPM, type: "2", subtype: "0")

            Fan3Speed    (Channel, description: "Fan 3 Speed", units: "rpm", format: ".0f",
                          devcName: maq20, hwChan: CompMaq20Device.CHAN_PULSE_RPM, type: "2", subtype: "1")

            LiquidSubCooling   (SubCoolingChannel, description: "$comp SubCooling", units: "\u00b0C", format: ".2f",
                        dischargePressureChannel: ref("$comp/DischrgPrs"), liquidTempChannel:ref("$comp/LiquidTmp_M"))
        }
    }

    for (j in cryoSet) {

        comp = cryoNames[cryoCircs[j]]
//        "$comp" (CryoCompressor, discTempChan: "DischrgTmp_P", discPressChan: "DischrgPrs", suctTempChan: "SuctionTmp_P",
//                 suctPressChan: "SuctionPrs", cmprPowerChan: "CompPower", phaseSepTempChan: "PhaseSepTmp") {

        "$comp" (CryoCompressor, discTempChan: "DischrgTmp_P", discPressChan: "DischrgPrs", suctTempChan: "SuctionTmp_P",
                 suctPressChan: "SuctionPrs", cmprPowerChan: "CompPower", phaseSepTempChan: "PhaseSepTmp",
                 oilLevelChan: "OilLevel") {


//            if (j % 3 == 0) {
            if (j == 0 || j == 2) {
                ctrl2 = cryoSet.contains(j + 1) ? "${cryoNames[cryoCircs[j + 1]]}/Maq20/FanControl" : null
                ctrl3 = cryoSet.contains(j + 2) ? "${cryoNames[cryoCircs[j + 2]]}/Maq20/FanControl" : null
                FanCtrl (FanControl, fanCntrl: ["$comp/Maq20/FanControl", ctrl2, ctrl3],
                         ambientTemp: "$comp/AmbientTmp", cabinetTemp: "$comp/CabinetTmp")
            }

            Plc (compPlutoDevice)

            Maq20 (compMaq20Device, modules: ["TTC", "TTC", "DIOL:pwm:pulse"]) {

                FanControl (compMaq20PWMControl, modIndex: 2, funcIndex: 0, frequency: 200.0)

                PulseControl (maq20PulseControl, modIndex: 2, funcIndex: 1, pulsesPerRevn: 6)

                LineControl  (maq20DiscControl, modIndex: 2)

            }

            plc = "$comp/Plc"
            maq20 = "$comp/Maq20"

            DischrgTmp_P (Channel, description: "Discharge Temperature (PLC)", units: "\u00b0C", format: ".1f",
                          devcName: plc, hwChan: 1, type: "ADDREG:0", scale: 0.01)

            DischrgTmp_M (Channel, description: "Discharge Temperature (MAQ20)", units: "\u00b0C", format: ".1f",
                          devcName: maq20, hwChan: 3, type: "0", subtype: "T220")

            DischrgPrs   (Channel, description: "Discharge Pressure", units: "psia", format: ".1f",
                          devcName: plc, hwChan: 1, type: "ADDREG:3", scale: 0.1)

            SuctionTmp_P (Channel, description: "Suction Temperature (PLC)", units: "\u00b0C", format: ".1f",
                          devcName: plc, hwChan: 1, type: "ADDREG:1", scale: 0.01)

            SuctionTmp_M (Channel, description: "Suction Temperature (MAQ20)", units: "\u00b0C", format: ".1f",
                          devcName: maq20, hwChan: 2, type: "0", subtype: "T220")

            SuctionPrs   (Channel, description: "Suction Pressure", units: "psia", format: ".1f",
                          devcName: plc, hwChan: 1, type: "ADDREG:4", scale: 0.1)

            OilLevel     (Channel, description: "Oil Level", units: "mm", format: ".1f",
                          devcName: plc, hwChan: 1, type: "ADDREG:2", scale: 0.01818, offset: -36.36)

            CompVoltage  (Channel, description: "Compressor Voltage", units: "Volts", format: ".1f",
                          devcName: plc, hwChan: 1, type: "ADDREG:6", scale: 0.1)

            CompCurrent  (Channel, description: "Compressor Current", units: "Amps", format: ".1f",
                          devcName: plc, hwChan: 1, type: "ADDREG:5", scale: 0.01)

            CompPower    (Channel, description: "Compressor Power", units: "VA", format: ".1f",
                          devcName: plc, hwChan: 0, type: "ADDINT:9", scale: 0.001)

            WaterInTmp   (Channel, description: "Water Inlet Temperature", units: "\u00b0C", format: ".1f",
                          devcName: maq20, hwChan: 0, type: "0", subtype: "T220")

            WaterOutTmp  (Channel, description: "Water Outlet Temperature", units: "\u00b0C", format: ".1f",
                          devcName: maq20, hwChan: 4, type: "0", subtype: "T220")

            AfterCoolTmp (Channel, description: "After Cooler Temperature", units: "\u00b0C", format: ".1f",
                          devcName: maq20, hwChan: 1, type: "0", subtype: "T220")

            PhaseSepTmp  (Channel, description: "Phase Separator Temperature", units: "\u00b0C", format: ".1f",
                          devcName: maq20, hwChan: 5, type: "0", subtype: "T220")

            OilSepTmp    (Channel, description: "Oil Separator Temperature", units: "\u00b0C", format: ".1f",
                          devcName: maq20, hwChan: 6, type: "0", subtype: "T220")

            SurgeTankTmp (Channel, description: "Surge Tank Temperature", units: "\u00b0C", format: ".1f",
                          devcName: maq20, hwChan: 7, type: "0", subtype: "T220")

//            if (j % 3 == 0) {
            if (j == 0 || j == 2) {
                CabinetTmp (Channel, description: "Cabinet Temperature", units: "\u00b0C", format: ".1f",
                            devcName: maq20, hwChan: 1, type: "1", subtype: "T220")

                AmbientTmp (Channel, description: "Ambient Temperature", units: "\u00b0C", format: ".1f",
                            devcName: maq20, hwChan: 0, type: "1", subtype: "T220")
            }

            FanSpeed     (Channel, description: "Fan Speed", units: "rpm", format: ".0f",
                          devcName: maq20, hwChan: CompMaq20Device.CHAN_PULSE_RPM, type: "2", subtype: "1")

        }

    }

}
