package loader

import java.util.Properties;
import org.lsst.ccs.bootstrap.BootstrapResourceUtils;
import org.lsst.ccs.subsystems.fcs.*
import org.lsst.ccs.subsystems.fcs.common.*
import org.lsst.ccs.subsystems.fcs.drivers.*
import org.lsst.ccs.subsystems.fcs.simulation.*
import org.lsst.ccs.drivers.canopenjni.*
import org.lsst.ccs.drivers.canopenjni.rmi.*
import org.lsst.ccs.description.groovy.CCSBuilder


//************************************************************************//
// subsystem properties
// org.lsst.ccs.run.mode can be "simulation" or "hardware"
// org.lsst.ccs.fcs.instance.loader can be "PROTO", "LO1" or "LO2"
//************************************************************************//
Properties props = BootstrapResourceUtils.getBootstrapSystemProperties();
def runMode = props.getProperty("org.lsst.ccs.run.mode", "simulation");
def instanceLO = props.getProperty("org.lsst.ccs.fcs.instance.loader", "LO1");
//************************************************************************//

//********************************************************************************//
// Groovy file for the loader prototype is different from the loader final hardware 
// for the sensors : loaderEngagedSensors and loaderHandoffSensors.
// In the prototype this sensors are not redondant while they are redondant for the final hardware.
//********************************************************************************//

//********************************************************************************//
//Loader variables
//********************************************************************************//
def bridgeToLoaderName = "loaderTcpProxy" // to monitor the loader sensors
def loaderPlutoGatewayName = "loaderPlutoGateway" // to monitor the loader sensors
//********************************************************************************//

def subsystemName
//decide which subsystem to launch depending on runMode and instanceLO
if ("simulation".equals(runMode)) {
    subsystemName = "loader-standalone-simu"
} else if ("PROTO".equals(instanceLO)) {
    subsystemName = "loader-standalone_PROTO"
} else if ("LO2".equals(instanceLO)) {
    subsystemName = "loader-standalone_LO2"
} else {
    subsystemName = "loader-standalone_LO1"
}

def canopenProxyClass
if ("hardware".equals(runMode)) {
    canopenProxyClass = LoaderCanOpenProxy.class;
} else {
    canopenProxyClass = SimuLoaderCanOpenProxy.class;
}

CCSBuilder builder = [subsystemName]

builder.
    main ( LoaderMain, bridge:ref("$bridgeToLoaderName")
    )
{ //begin description of Main submodules

    // tcp Proxy
    "$bridgeToLoaderName"(canopenProxyClass, hardwareBootTimeout:3000) {
        
        //real hardware
        if ( runMode.equals("hardware") && "PROTO".equals(instanceLO) ) {
            //loader CANbus is canbus1
            canInterface(CanOpenCommands, coi:new CanOpenRMIClient("192.168.30.122", "canbus1"))

            "$loaderPlutoGatewayName" (CanOpenPlutoGateway, nodeID:1, serialNB:"22d6")
            
            // can open devices
            hooksController (CanOpenEPOS, nodeID:0x1b, serialNB:"79007141") 

            carrierController (CanOpenEPOS, nodeID:0x1a, serialNB:"80003184")
            
        } else if ( runMode.equals("hardware") && "LO1".equals(instanceLO)) { 
            //loader CANbus is canbus1
            canInterface(CanOpenCommands, coi:new CanFestivalJNI())

            "$loaderPlutoGatewayName" (CanOpenPlutoGateway, nodeID:0x5, serialNB:"310f")
            
            // can open devices
            hooksController (CanOpenEPOS, nodeID:0x5b, serialNB:"79018738") 

            carrierController (CanOpenEPOS, nodeID:0x5a, serialNB:"80006442")            
        
        //simulated CAN open devices 
        } else {
            
            canInterface(SimuCanOpenInterface)
            
            // description of plutoGateway
            "$loaderPlutoGatewayName" (SimuLoaderStandalonePlutoGateway, 
                nodeID:1,serialNB:"22d6")

            hooksController (SimuLoaderClampController,
                nodeID:0x1b,serialNB:"79007141",
                plutoGateway:ref("$loaderPlutoGatewayName")) 

            carrierController (SimuLoaderCarrierController,
                nodeID:0x1a,serialNB:"80003184",
                plutoGateway:ref("$loaderPlutoGatewayName"))
        }
        
    }//end description of bridge's childrens
    //----------------------------------------------
    // END Bridge To LOADER description
    //----------------------------------------------
                
    //begin description of loader
    loader (Loader)
    {//begin description of loader's children

        carrier(LoaderCarrier,
            handoffSensors:ref("loaderHandoffSensors"),
            storageSensors:ref("loaderStorageSensors"),
            engagedSensors:ref("loaderEngagedSensors")
        )
        {//begin description of loader carrier's children
            
            //definition of engaged and handoff position sensors
            if ( "PROTO".equals(instanceLO)) {
                //for loader prototype engaged and handoff position sensors are not redondant
                            
                //user_to_gateway n° 1
                loaderHandoffSensors (DigitalSensor,
                    dioName:loaderPlutoGatewayName,inputNumero:7,byteNumero:3)

                loaderEngagedSensors (DigitalSensor,
                    dioName:loaderPlutoGatewayName,inputNumero:6,byteNumero:3)
                
            } else {
                //for LO1 and LO2 engaged and handoff position sensors are redondant.
                loaderEngagedSensors (RedondantSensors,
                    sensor:ref("loaderEngagedPositionSensor0"), 
                    sensorR: ref("loaderEngagedPositionSensor1")
                )
                {//begin description of loader engagedSensors
                    loaderEngagedPositionSensor0 ( DigitalSensor ,
                        dioName:loaderPlutoGatewayName,inputNumero:6,byteNumero:3)

                    loaderEngagedPositionSensor1 ( DigitalSensor ,
                        dioName:loaderPlutoGatewayName,inputNumero:7,byteNumero:3)
                }//end description of loader engagedSensors

                loaderHandoffSensors (RedondantSensors,
                    sensor:ref("loaderHandoffPositionSensor0"), 
                    sensorR: ref("loaderHandoffPositionSensor1")
                )
                {//begin description of loader handoffSensors
                    //user_to_gateway n° 2
                    loaderHandoffPositionSensor0 ( DigitalSensor ,
                        dioName:loaderPlutoGatewayName,inputNumero:0,byteNumero:6)

                    loaderHandoffPositionSensor1 ( DigitalSensor ,
                        dioName:loaderPlutoGatewayName,inputNumero:1,byteNumero:6)
                }//end description of loader handoffSensors
            }

            
            loaderStorageSensors (RedondantSensors,
                sensor:ref("loaderStoragePositionSensor0"),
                sensorR:ref("loaderStoragePositionSensor1"),
            )
            {//begin description of loader storageSensors
                //user_to_gateway n° 1
                loaderStoragePositionSensor0 ( DigitalSensor ,
                    dioName:loaderPlutoGatewayName, inputNumero:4,byteNumero:3)

                loaderStoragePositionSensor1 ( DigitalSensor ,
                    dioName:loaderPlutoGatewayName, inputNumero:5, byteNumero:3)  
            }//end description of loader storageSensors
        }//end description of loader carrier's children

        clamp(LoaderClamp,
            hook1:ref("hook1"),hook2:ref("hook2"), hook3:ref("hook3"),hook4:ref("hook4"),
            forceSensor0:ref("forceSensor0"), forceSensor1:ref("forceSensor1"),
            clampedStatusSensor: ref("clampedStatusSensor"),
            )
        {//begin description of loader clamp's children
            int[] inputNumeroClose = [4,5,6,7];
            int[] inputNumeroOpen = [0,1,2,3];
            for (int i = 1; i<5; i++) {
            
            "hook${i}"(LoaderHook,
                    closeSensor:ref("loaderCloseSensor${i}"), openSensor:ref("loaderOpenSensor${i}"))
                { //user_to_gateway n° 1
                    "loaderCloseSensor${i}" ( DigitalSensor , //closeHookSensor0
                        dioName:loaderPlutoGatewayName, inputNumero:inputNumeroClose[i-1], byteNumero:2)
                       
                    "loaderOpenSensor${i}" ( DigitalSensor , //openHookSensor0
                        dioName:loaderPlutoGatewayName, inputNumero:inputNumeroOpen[i-1], byteNumero:2)
                }
            }
            
            forceSensor0(ForceSensor, deviceName:loaderPlutoGatewayName, byteNumero:4)
            
            forceSensor1(ForceSensor, deviceName:loaderPlutoGatewayName, byteNumero:8)

            // user_to_gateway n° 2
            unclampedStatusSensor ( DigitalSensor ,
                dioName:loaderPlutoGatewayName,inputNumero:2,byteNumero:6)
            
            underClampedStatusSensor ( DigitalSensor ,
                dioName:loaderPlutoGatewayName,inputNumero:3,byteNumero:6)
            
            clampedStatusSensor ( DigitalSensor ,
                dioName:loaderPlutoGatewayName,inputNumero:4,byteNumero:6) 
            
            overClampedStatusSensor ( DigitalSensor ,
                dioName:loaderPlutoGatewayName,inputNumero:5,byteNumero:6)
            
//            loaderCarrierRelayStatus ( DigitalSensor ,
//                dioName:loaderPlutoGatewayName,inputNumero:6,byteNumero:6)
//            
//            loaderHooksRelayStatus ( DigitalSensor ,
//                dioName:loaderPlutoGatewayName,inputNumero:7,byteNumero:6)
//            
//            loaderChainPresenceSensor ( DigitalSensor ,
//                dioName:loaderPlutoGatewayName,inputNumero:5,byteNumero:7) 
//            
//            loaderDefaultStatus ( DigitalSensor ,
//                dioName:loaderPlutoGatewayName,inputNumero:6,byteNumero:7)
//
//            loaderFilterGoodPositionStatus ( DigitalSensor ,
//                dioName:loaderPlutoGatewayName,inputNumero:7,byteNumero:7)
        }//end description of loader clamp's children

       
        loaderFilterPresenceSensors (RedondantSensors,
            sensor:ref("loaderFilterPresenceSensor0"),
            sensorR:ref("loaderFilterPresenceSensor1"),
        )
        { // user_to_gateway n° 1
            loaderFilterPresenceSensor0(DigitalSensor ,
                dioName:loaderPlutoGatewayName,inputNumero:0, byteNumero:3)

            loaderFilterPresenceSensor1(DigitalSensor ,
                dioName:loaderPlutoGatewayName, inputNumero:1, byteNumero:3) 
        }

        loaderOnCameraSensors (RedondantSensors,
            sensor:ref("loaderOnCameraSensor0"),
            sensorR:ref("loaderOnCameraSensor1"),
        )
        { // user_to_gateway n° 1
            loaderOnCameraSensor0(DigitalSensor ,
                dioName:loaderPlutoGatewayName, inputNumero:2, byteNumero:3)

            loaderOnCameraSensor1(DigitalSensor ,
                dioName:loaderPlutoGatewayName, inputNumero:3, byteNumero:3)
        }
        //Signals comming from autochanger//
        //AP2 user_to_gateway 3 input 0
        //AF0 user_to_gateway 3 input 1
        //AF1 user_to_gateway 3 input 2
        //AF3 user_to_gateway 3 input 3
        acAP2 (ComplementarySensors,
            sensor:ref("acAP2s"),
            sensorC:ref("acAP2b"),
        ) {
            acAP2s (DigitalSensor,
                dioName:loaderPlutoGatewayName, inputNumero:0, byteNumero:11)
            acAP2b (DigitalSensor,
                dioName:loaderPlutoGatewayName, inputNumero:1, byteNumero:11)
        }
        
        acAF0 (ComplementarySensors,
            sensor:ref("acAF0s"),
            sensorC:ref("acAF0b"),
        ) {
            acAF0s (DigitalSensor,
                dioName:loaderPlutoGatewayName, inputNumero:2, byteNumero:11)
            acAF0b (DigitalSensor,
                dioName:loaderPlutoGatewayName, inputNumero:3, byteNumero:11)
        } 
        
        acAF1 (ComplementarySensors,
            sensor:ref("acAF1s"),
            sensorC:ref("acAF1b"),
        ) {
            acAF1s (DigitalSensor,
                dioName:loaderPlutoGatewayName, inputNumero:4, byteNumero:11)
            acAF1b (DigitalSensor,
                dioName:loaderPlutoGatewayName, inputNumero:5, byteNumero:11)
        } 
        
        acAF3 (ComplementarySensors,
            sensor:ref("acAF3s"),
            sensorC:ref("acAF3b"),
        ) {
            acAF3s (DigitalSensor,
                dioName:loaderPlutoGatewayName, inputNumero:6, byteNumero:11)
            acAF3b (DigitalSensor,
                dioName:loaderPlutoGatewayName, inputNumero:7, byteNumero:11)
        } 
        //end of Signals comming from autochanger// 
        
        //key lock or lockOut
        keyLockSensors (ComplementarySensors,
            sensor:ref("keyLock"),
            sensorC:ref("keyLockb"),
        ) {
            keyLock (DigitalSensor,
                dioName:loaderPlutoGatewayName, inputNumero:0, byteNumero:10)
            keyLockb (DigitalSensor,
                dioName:loaderPlutoGatewayName, inputNumero:1, byteNumero:10)
        }
        
        //engineering key
        keyEngSensors (ComplementarySensors,
            sensor:ref("keyEng"),
            sensorC:ref("keyEngb"),
        ) {
            keyEng (DigitalSensor,
                dioName:loaderPlutoGatewayName, inputNumero:2, byteNumero:10)
            keyEngb (DigitalSensor,
                dioName:loaderPlutoGatewayName, inputNumero:3, byteNumero:10)
        }
        
//        //Camera Protection Signals coming from loader
//        loLRH (ComplementarySensors,
//            sensor:ref("loLRHs"),
//            sensorC:ref("loLRHb"),
//        ) {
//            loLRHs (DigitalSensor,
//                dioName:loaderPlutoGatewayName, inputNumero:4, byteNumero:10)
//            loLRHb (DigitalSensor,
//                dioName:loaderPlutoGatewayName, inputNumero:5, byteNumero:10)
//        } 
//
//        loLPS (ComplementarySensors,
//            sensor:ref("loLPSs"),
//            sensorC:ref("loLPSb"),
//        ) {
//            loLPSs (DigitalSensor,
//                dioName:loaderPlutoGatewayName, inputNumero:6, byteNumero:10)
//            loLPSb (DigitalSensor,
//                dioName:loaderPlutoGatewayName, inputNumero:7, byteNumero:10)
//        }
        
            
    }//end description of loader's children
    
    /**********************************************************************/
    /*                FAKE AUTOCHANGER DESCRIPTION                       */
    /**********************************************************************/
    //in the loader standalone subsystem the fake autochanger is a switch which
    //simulate that autochanger holds a filter at HANDOFF 
    autochanger(FakeFilterHolder, holdingFilterSensorName:"acAF3", notHoldingFilterSensorName:"acAF0")

    /**********************************************************************/
    /*                END of FAKE AUTOCHANGER DESCRIPTION                 */
    /**********************************************************************/
    
} //end description of LoaderMain
                


