import java.util.logging.Level
import java.util.logging.Logger
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.Compressor
import org.lsst.ccs.subsystem.refrig.CompLimits
import org.lsst.ccs.subsystem.refrig.RefrigActionManager
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.CompMaq20DiscControl
import org.lsst.ccs.subsystem.refrig.CompPlutoDevice
import org.lsst.ccs.subsystem.refrig.SimRefrigPersist
import org.lsst.ccs.subsystem.common.devices.dataforth.Maq20PulseControl
import org.lsst.ccs.monitor.Channel

runMode = BootstrapResourceUtils.getBootstrapSystemProperties().getProperty("org.lsst.ccs.run.mode", "normal")
simulation = runMode.equals("simulation")
unit = BootstrapResourceUtils.getBootstrapSystemProperties().getProperty("org.lsst.ccs.subsystem.agent.property.refrig-unit", "")
LOG = Logger.getLogger("RefrigGroovy")
LOG.setLevel(Level.INFO)
LOG.log(Level.INFO, "Unit = {0}", unit)

cryoPresent = buildProperties().getProperty("org.lsst.ccs.cryo.present", "1,2,3,4,5,6")
cryoSet = new HashSet()
if (!cryoPresent.isEmpty()) {
    for (j in cryoPresent.split(",")) {
        cryoSet.add(Integer.decode(j.trim()) - 1)
    }
}
cryoOrder = buildProperties().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) {

    CryoCompLimits (CompLimits)

    ActionManager (RefrigActionManager)

    if (simulation) {
        SimRefrigPersist (SimRefrigPersist)
    }

    for (j in cryoSet) {

        comp = cryoNames[cryoCircs[j]]
        "$comp" (Compressor, discTempChan: "DischrgTmp_P", discPressChan: "DischrgPrs", suctTempChan: "SuctionTmp_P",
                 suctPressChan: "SuctionPrs", cmprPowerChan: "CompPower", phaseSepTempChan: "PhaseSepTmp",
                 oilLevelChan: "OilLevel") {
                     if (j % 3 == 0) {
                         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", "DIOL"]) {

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

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

                LineControl0 (CompMaq20DiscControl, modIndex: 2, index: 0)

                LineControl1 (CompMaq20DiscControl, modIndex: 3, index: 1)

            }

            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", hysteresis: 0.02,
                          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)

            waterChanIncr = (unit.equals("refrig2") && comp.equals("Cryo3")) ? -2 : 2  // Compensate for miswired TCs
            LOG.log(Level.INFO, "Comp = {0} waterChanIncr = {1}", new Object[]{comp, waterChanIncr})
    
            WaterInTmp   (Channel, description: "Water Inlet Temperature", units: "\u00b0C", format: ".1f",
                          devcName: maq20, hwChan: 2 - waterChanIncr, type: "0", subtype: "T220", checkHi:"alarm")

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

            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) {
                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")

        }

    }

}
