import org.lsst.ccs.description.groovy.CCSBuilder;
import org.lsst.ccs.subsystem.mcm.MCM_IR2;
import org.lsst.ccs.subsystem.mcm.MinionIR2;
import org.lsst.ccs.subsystem.mcm.MinionIR2Group;
import org.lsst.ccs.subsystem.mcm.AlertDispatcher.AlertHandler;
import org.lsst.ccs.subsystem.mcm.AlertDispatcher.AlertAction;
import org.lsst.ccs.subsystem.mcm.AlertDispatcher.EmailAlertAction;
import org.lsst.ccs.subsystem.mcm.AlertDispatcher.EmailAlertDeliveryStrategy;
import org.lsst.ccs.subsystem.mcm.AlertDispatcher.CommandAlertAction;
import org.lsst.ccs.subsystem.mcm.AlertDispatcher;
import org.lsst.ccs.subsystem.mcm.AlertNotification;
import org.lsst.ccs.subsystem.rafts.alerts.RaftAlert;
import org.lsst.ccs.bus.states.AlertState;
import java.util.function.Predicate;
import java.time.Duration;
import org.lsst.ccs.subsystem.mcm.ir2.actions.RebTemperatureTooHighAction
import org.lsst.ccs.subsystem.mcm.ir2.actions.FocalPlaneRebTemperatureTooHighAction
import org.lsst.ccs.bootstrap.BootstrapResourceUtils;

CCSBuilder builder = ["mcm-ir2"]

Properties props = BootstrapResourceUtils.getBootstrapSystemProperties()
def isSimulated = props.getProperty("org.lsst.ccs.run.mode", "normal").equals("simulation")


def fromEmail = isSimulated ? "SIMULATED-ccs-alarm@lsst-mcm.slac.stanford.edu" : "ccs-alarm@lsst-mcm.slac.stanford.edu"
def replyToEmail = isSimulated ? "SIMULATED-lsstcam-opsprob@slac.stanford.edu" : "lsstcam-opsprob@slac.stanford.edu";

def infrastructureList = ["turri@slac.stanford.edu"];


def environmentList = isSimulated ? infrastructureList : ["jtice@SLAC.Stanford.EDU","tether@slac.stanford.edu","marshall@slac.stanford.edu","youtsumi@slac.stanford.edu"];
def cryostatList = isSimulated ? infrastructureList : ["turri@slac.stanford.edu","qiu@SLAC.Stanford.EDU","marshall@slac.stanford.edu","youtsumi@slac.stanford.edu"];
def comcamList = isSimulated ? infrastructureList : ["turri@slac.stanford.edu","homer@SLAC.Stanford.EDU","margaux@SLAC.Stanford.EDU","reil@SLAC.Stanford.EDU"];
def ts7List = isSimulated ? infrastructureList : ["turri@slac.stanford.edu","tonyj@slac.stanford.edu","marshall@slac.stanford.edu","youtsumi@slac.stanford.edu"];
def ts72List = isSimulated ? infrastructureList : ["turri@slac.stanford.edu","tonyj@slac.stanford.edu","marshall@slac.stanford.edu","homer@SLAC.Stanford.EDU","herrmann@slac.stanford.edu","youtsumi@slac.stanford.edu"];
def cameraList = isSimulated ? infrastructureList : ["turri@slac.stanford.edu","tonyj@slac.stanford.edu","marshall@slac.stanford.edu","youtsumi@SLAC.STANFORD.EDU","homer@slac.stanford.edu","bowdish@slac.stanford.edu"];
//Global selectors
def alarmSelector = {notification -> return notification.getSeverity() == AlertState.ALARM } as Predicate<AlertNotification>
def warningSelector = {notification -> return notification.getSeverity() == AlertState.WARNING } as Predicate<AlertNotification>



//Raft selectors
def raftOriginSelector = { n -> return n.getSubsystemType().equals(MinionIR2.RAFT) } as Predicate<AlertNotification>
def rebConnectionAlertSelector = { n -> return n.getAlert().getAlertId() ==  RaftAlert.REB_NOT_CONNECTED.getAlertId() } as Predicate<AlertNotification>
def rebConnectionActionSelector = raftOriginSelector.and(rebConnectionAlertSelector);


//Dummy AlertAction to print something
class PrintWhatToDo extends AlertAction {
    def msg;
    PrintWhatToDo(String msg) {
        this.msg = msg;
    }
        
    def void accept(AlertNotification notif) {
        System.out.println(notif.getSeverity().toString()+" "+msg);
    }        

    def String getDescription() {
        return "Prints to standard output: "+msg;
    }        
}


builder.
    main(MCM_IR2, 
        minions:[(MinionIR2Group.INFRASTRUCTURE):["jython-server":MinionIR2.JYTHONCONSOLE,"py4j-server":MinionIR2.PY4J_SERVER, "localdb":MinionIR2.LOCALBD, "rest-server":MinionIR2.REST_SERVER, "mcm-ir2":MinionIR2.MCM, "cluster-monitor":MinionIR2.CLUSTER_MONITOR],
                 (MinionIR2Group.IR2_ENVIRONMENT) :["ir2-airwatch":MinionIR2.AIRWATCH,"ccs-doorman":MinionIR2.DOORMAN],
                 (MinionIR2Group.ALIVENESS_TEST) :["aliveness-rebps":MinionIR2.POWER, "aliveness-raft":MinionIR2.RAFT],
                 (MinionIR2Group.TS71G) :["ts7-1":MinionIR2.TS7, "ts7-rebps":MinionIR2.POWER, "ts8-raft":MinionIR2.RAFT],
                 (MinionIR2Group.TS72G) :["ts7-2":MinionIR2.TS7, "ts7-2-rebps":MinionIR2.POWER, "ts7-2-raft":MinionIR2.RAFT],
                 (MinionIR2Group.TEST_STAND_8) :["ts8-bench":MinionIR2.TS8_BENCH],
                 (MinionIR2Group.CRYOSTAT) :["pump-plate":MinionIR2.PUMP_PLATE],
                 (MinionIR2Group.COMCAM) :["comcam-vacuum":MinionIR2.VACUUM, "comcam-fp":MinionIR2.FOCAL_PLANE, "comcam-rebps":MinionIR2.POWER],
                 (MinionIR2Group.CAMERA) :["vacuum":MinionIR2.VACUUM, "quadbox":MinionIR2.QUADBOX, "refrig":MinionIR2.REFRIG,
                    "focal-plane":MinionIR2.FOCAL_PLANE, "rebpower":MinionIR2.POWER, "ccob":MinionIR2.CCOB, "bot-motorplatform":MinionIR2.BOT_MOTOR,  
                    "bot-bench":MinionIR2.BOT_BENCH, "thermal":MinionIR2.THERMAL, "pap-pdu":MinionIR2.PUMPANDPURGE, "mpm":MinionIR2.MASTER_PROTECTION_MODULE],
                 (MinionIR2Group.METROLOGY) :["metrology":MinionIR2.METROLOGY, "ts7-2":MinionIR2.TS7]] ) {

    infrastructure (AlertDispatcher, group: MinionIR2Group.INFRASTRUCTURE) {
        infrastructureEmailNotification (AlertHandler, handlerName: "infrastructureEmailNotification") {
            infrastructurePublicMailAction (EmailAlertAction, emailList: infrastructureList, fromEmail:"$fromEmail", replyToEmail:"$replyToEmail") {
                localDbEmailStrategy (EmailAlertDeliveryStrategy, sendFirstEmail: false, origin:"localdb", maxAccumulation: Duration.ofMinutes(30))
                defaultEmailStrategy (EmailAlertDeliveryStrategy, sendFirstEmail: true, origin:".*", maxAccumulation: Duration.ofMinutes(0))
            }
        }        
    }
    
    environment (AlertDispatcher, group: MinionIR2Group.IR2_ENVIRONMENT) {
        environmentEmailNotification (AlertHandler, handlerName: "environmentEmailNotification") {
             environmentPublicMailAction (EmailAlertAction, emailList: environmentList, fromEmail:"$fromEmail", replyToEmail:"$replyToEmail")
        }        
    }

    ts71gTest (AlertDispatcher, group: MinionIR2Group.TS71G) {
        ts71gEmailNotification (AlertHandler, handlerName: "ts71gEmailNotification") {
            publicMailAction (EmailAlertAction, emailList: ts7List, fromEmail:"$fromEmail", replyToEmail:"$replyToEmail", filePath:"/etc/ccs/emails.list")
        }
        rebTemperatureTooHighHandler (AlertHandler, handlerName: "rebTemperatureTooHighHandler") {
            rebTemperatureTooHighAction (RebTemperatureTooHighAction)
        }        
    }
    
    ts72gTest (AlertDispatcher, group: MinionIR2Group.TS72G) {
        ts72gEmailNotificationTs2 (AlertHandler, handlerName: "ts72gEmailNotification") {
            publicMailActionTs2 (EmailAlertAction, emailList: ts72List, fromEmail:"$fromEmail", replyToEmail:"$replyToEmail", filePath:"/etc/ccs/emails.list")
        }
        rebTemperatureTooHighHandlerTs2 (AlertHandler, handlerName: "rebTemperatureTooHighHandler") {
            rebTemperatureTooHighActionTs2 (RebTemperatureTooHighAction)
        }        
    }

    cryostat (AlertDispatcher, group: MinionIR2Group.CRYOSTAT) {
        cryostatEmailNotification (AlertHandler, handlerName: "cryostatEmailNotification") {
             cryostatPublicMailAction (EmailAlertAction, emailList: cryostatList, fromEmail:"$fromEmail", replyToEmail:"$replyToEmail")
        }        
    }

    comcam (AlertDispatcher, group: MinionIR2Group.COMCAM) {
        comcamEmailNotification (AlertHandler, handlerName: "comcamEmailNotification") {
             comcamPublicMailAction (EmailAlertAction, emailList: comcamList, fromEmail:"$fromEmail", replyToEmail:"$replyToEmail")
        }        
        comcamRebTemperatureTooHighHandler (AlertHandler, handlerName: "comcamRebTemperatureTooHighHandler") {
            comcamRebTemperatureTooHighAction (FocalPlaneRebTemperatureTooHighAction)
        }        
    }

    camera (AlertDispatcher, group: MinionIR2Group.CAMERA) {
        cameraEmailNotification (AlertHandler, handlerName: "cameraEmailNotification") {
             cameraPublicMailAction (EmailAlertAction, emailList: cameraList, fromEmail:"$fromEmail", replyToEmail:"$replyToEmail", filePath:"/etc/ccs/camera-emails.list")
        }        
        focalPlaneRebTemperatureTooHighHandler (AlertHandler, handlerName: "focalPlaneRebTemperatureTooHighHandler") {
            focalPlaneRebTemperatureTooHighAction (FocalPlaneRebTemperatureTooHighAction)
        }        
    }
}
