
#the mux files are converted from ezmux source code by Hairong Shang
proc APSSwitchMux {args} {
    set flag ""
    set location MCR
    set monitor ""
    set system ""
    set statusCallback ""
    set trackMV200 0
    APSStrictParseArguments {flag location monitor system statusCallback trackMV200}
    
    if {![string length $flag] || ![string length $location] || ![string length $monitor] || \
            ![string length $system]} {
        return -code error "APSSwitchMux: flag, location, monitor and system all have to be provided for SwitchMux!"
    }
    set location0 [string toupper $location]
    switch $location0 {
        MCR -
        ICR {
            set location $location0
        }
        LASER_ROOM -
        "LASER ROOM" {
            set location Laser_Room
        }
        STREAMING {
            set location Streaming
        }
        QUAD_DISPLAY -
        "QUAD DISPLAY" {
            set location Quad_Display
        }
        FRAME_GRABBERS -
        "FRAME GRABBERS" {
            set location Frame_Grabbers
        }
        default {
            return -code error "Invalid location - $location given, it has to be MCR, ICR, Frame_Grabbers, Laser_Room, Quad_Display or Streaming.!"
        }
    }
    if {$system=="PTB" || $system=="LTP"} {
        set system0 PAR
    } elseif {$system=="BTS"} {
        set system0 BOOSTER
    } else {
        set system0 [string toupper $system]
    }
    set muxFile /home/helios/oagData/beamImages/setupFiles/${location}_MuxSwitch.sdds
    set mv200File /home/helios/oagData/beamImages/setupFiles/MV200_MuxSwitch.sdds 
    set tmpRoot /tmp/[APSTmpString]
    APSAddToTmpFileList -ID imageCapture -fileList $tmpRoot.sdds
    if [catch {exec sddsprocess $muxFile -pipe=out -nowarnings \
                   -match=par,Monitor=$monitor -match=par,System=$system0 \
                   "-match=col,Flag=$flag,Label=$flag,|" \
                   | sddscombine -pipe=in -merge $tmpRoot.sdds } result] {
        return -code error "APSSwitchMux: $result"
    }
    set fileList $tmpRoot.sdds
    set rows [exec sdds2stream -rows=bar $tmpRoot.sdds]
    if !$rows {
        return -code error "No entry found in the mux switch file for $location, $system - $flag with $monitor $monitor!"
    }
    if $trackMV200 {
        if [catch {exec sddsprocess $mv200File -pipe=out -nowarnings \
                       -match=par,System=$system0 \
                       "-match=col,Flag=$flag,Label=$flag,|" \
                       | sddscombine -pipe=in -merge $tmpRoot.sdds.mv200 } result] {
            return -code error "APSSwitchMux: $result"
        }
        set rows1 [exec sdds2stream -rows=bar $tmpRoot.sdds.mv200]
        if !$rows1 {
            return -code error "APSSwitchMux: No entry found in $mv200File for $system $flag!"
        }
        lappend fileList $tmpRoot.sdds.mv200
    }
    foreach file $fileList {
        if [catch {sdds load $file tmpData} result] {
            return -code error "APSSwitchMux: $result"
        }
        if [lsearch $tmpData(ParameterNames) EpicsPV]<0 {
            set epicsPV [lindex [lindex $tmpData(Column.EpicsPV) 0] 0]
        } else {
            set epicsPV [lindex $tmpData(Parameter.EpicsPV) 0]
        }
        if [lsearch $tmpData(ParameterNames) MuxPV1]<0 {
            set muxPV1 [lindex [lindex $tmpData(Column.MuxPV1) 0] 0]
        } else {
            set muxPV1  [lindex $tmpData(Parameter.MuxPV1) 0]
        }
        set epicsValue [lindex [lindex $tmpData(Column.EpicsPVValue) 0] 0]
        set satMuxPV [lindex [lindex $tmpData(Column.SatMuxPV) 0] 0]
        set satMuxValue [lindex [lindex $tmpData(Column.SatMuxPVValue) 0]  0]
        set muxValue1 [lindex [lindex $tmpData(Column.MuxPV1Value) 0] 0]
        #now witch the mux
        if [catch {APSSetMuxPVs -epicsPV $epicsPV -epicsValue $epicsValue \
                       -satMuxPV "$satMuxPV" -satMuxValue "$satMuxValue" \
                       -muxPVList "$muxPV1" -muxValueList "$muxValue1" \
                       -statusCallback "$statusCallback"} result] {
            return -code error "APSSwitchMux: $result"
        }
        unset tmpData
    } 
}

proc APSSetMuxPVs {args} {
    set epicsPV ""
    set epicsValue ""
    set satMuxPV ""
    set satMuxValue ""
    set muxPVList ""
    set muxValueList ""
    set statusCallback ""
    APSStrictParseArguments {epicsPV epicsValue satMuxPV satMuxValue \
                           muxPVList muxValueList trackMV200 statusCallback}
    
    if ![string length $epicsPV] {
        return -code error "APSSetMuxPVs: The mux pv name can not be emptry string."
    }
    if {$satMuxPV =="LI:VD1:MUX:mcr1SelectC" && $satMuxValue == 29} { 
        if [string length $statusCallback] {
            eval $statusCallback {"Filtered out mcr1 to mcr1"}
        }
    } elseif { $epicsPV=="VID:ICR:muxOut1C" && $epicsValue == 75} {
        # Screen out request for sending MV200 Output to MV200
        if [string length $statusCallback] {
            eval $statusCallback {"Filtered out mv200 to mv200"}
        }
    } elseif { $epicsPV=="VID:ICR:muxOut67C" && $epicsValue == 84} {
        # Screen out request for sending LFG1 Output to LFG1
        if [string length $statusCallback] {
            eval $statusCallback {"Filtered out LFG1 to LFG1"}
        }
    } else {
        if [string length $statusCallback] {
            eval $statusCallback {"set $epicsPV to $epicsValue"}
        }
        if [catch {APScavput -list=$epicsPV=$epicsValue} result] {
            return -code error "APSSetMuxPVs: $result"
        }
        if [string length $satMuxPV] {
            if [string length $statusCallback] {
                eval $statusCallback {"set $satMuxPV to $satMuxValue"}
            } 
            if [catch {APScavput -list=$satMuxPV=$satMuxValue} result] {
                return -code error "APSSetMuxPVs: $result"
            }
        }
    }
    foreach pv $muxPVList val $muxValueList {
        if [string length $pv] {
            if [string length $statusCallback] {
                eval $statusCallback {"set $pv to $val"}
            }
            if [catch {APScavput -list=$pv=$val} result] {
                return -code error "APSSetMuxPVs: $result"
            }
        } 
    }
}

proc APSConfigureCameraPVs {args} {
    set flagIn 0
    set lampOn 0
    set flag ""
    set actuatorNumber 1
    set system ""
    set statusCallback APSNoOp
    set ignoreFlagReadback 0
    set cameraType CID
    APSStrictParseArguments {flagIn lampOn flag system statusCallback actuatorNumber ignoreFlagReadback cameraType}
    if {![string length $flag] || ![string length $system]} {
        return -code error "APSConfigureCameraPVs: flag or system is null string" }

    if [catch {exec cavput "-list=LI:SelectCamModeC=VMUX only"} result] {
        return -code error "APSConfigureCameraPVs: $result" }
    
    switch $system {
        Linac -
        LEUTL {
            set tmpList [split $flag -]
            set flag [lindex $tmpList 0]
            set type [lindex $tmpList 1]
            if [regexp {Lo} $type] {
                set cameraType CCDH
            } elseif [regexp {Hi} $type] {
                set cameraType CCDL
            }
	    #always use YAG laser
	    set actuatorNumber 1
	    if {$flag=="LI:FL:S1C2"} {
		set actuatorNumber 2
	    }
	    set actuator $flag:Act${actuatorNumber}InC
	    set actuatorValue 1
	    if {$flag=="L3:FS1"} {
		#state 0 "Full Out" state 1 "OTR" state 2 "YAG" state 3 "CAL" 
		set actuator L3:FS1:ActPosC
		set actuatorValue 2
	    }
            if $flagIn {
                eval $statusCallback {"Inserting flag $flag."} 
                if {$cameraType=="CCDH" || $cameraType=="CCDL"} {
                    # this is a kludge to get the camera to work 
                    if [catch {exec cavput -list=$flag:CCDL:SelectCamC=1
                        after 1000
                        exec cavput -list=$flag:CCDH:SelectCamC=1} result] {
                        return -code error "APSConfigureCameraPVs: $result"
                    }
                }
                if [catch \
                        {exec cavput \
                             -list=$flag:$cameraType:SelectCamC=1,$flag:LampOnC=$lampOn,$actuator=$actuatorValue,LI:VD1:cameraTrigDelayPD.GATE=1,$flag:CameraOnC=1} result] {
                    return -code error "APSConfigureCameraPVs: $result"
                }
                set flagReadback $flag:Act${actuatorNumber}InM
            } else {
                eval $statusCallback {"Removing flag $flag."}
                if [catch \
                        {exec cavput \
                             -list=$flag:$cameraType:SelectCamC=0,$flag:LampOnC=0,$actuator=0,$flag:CameraOnC=0,LI:VD1:cameraTrigDelayPD.GATE=1} result] {
                    return -code error "APSConfigureCameraPVs: $result"
                }
            }
        }
        LTP {
            set command "exec cavput -list="
            set flagNumber [string index $flag 6]
            if $flagIn {
                eval $statusCallback {"Inserting flag and setting up camera."}
                append command $flag:act_cont_bo.VAL=1,\
                    $flag:LampOn=$lampOn,\
                  LI:VD1:cameraTrigDelayPD.GATE=1
            } else {
                eval $statusCallback {"Removing flag and turning off camera."}
                append command $flag:act_cont_bo.VAL=0,\
                    LI:VD1:cameraTrigDelayPD.GATE=1
            }
            if [catch {eval $command} result] {
                return -code error "APSConfigureCameraPVs: $result"
            }
            set flagReadback $flag:act_status_mbbi
        }
        PAR  {
            set command "exec cavput -list="
            set flagNumber [string index $flag 6]
            if $flagIn {
                eval $statusCallback {"Inserting flag."}
                append command $flag:act_cont_bo.VAL=1,\
                  $flag:LampOn=$lampOn,\
                     PTB:FLN:SelSeq${flagNumber}.PROC=1
            } else {
                eval $statusCallback {"Removing flag."}
                append command $flag:act_cont_bo.VAL=0,\
                  $flag:LampOn=0,\
                  PTB:FLN:SelSeq${flagNumber}.PROC=0
            }
            if [catch {eval $command} result] {
                return -code error "APSConfigureCameraPVs: $result"
            }
            set flagReadback $flag:act_status_mbbi
        }
        PTB -
        PAR {
            set command "exec cavput -list="
            set flagNumber [string index $flag 6]
            if $flagIn {
                eval $statusCallback {"Inserting flag."}
                append command $flag:act_cont_bo.VAL=1,\
                    $flag:LampOn=$lampOn,\
                    PTB:FLN:SelSeq${flagNumber}.PROC=1
            } else {
                eval $statusCallback {"Removing flag."}
                append command $flag:act_cont_bo.VAL=0,\
                    $flag:LampOn=0,\
                    PTB:FLN:SelSeq${flagNumber}.PROC=0
            }
            if [catch {eval $command} result] {
                return -code error "APSConfigureCameraPVs: $result"
            }
            set flagReadback $flag:act_status_mbbi
        }
        Booster {
            set commandFlag "exec cavput -list=" 
            if $flagIn {
                eval $statusCallback {"Inserting flag."}
                append commandFlag $flag:LampOn=$lampOn,\
                    $flag:act_cont_bo.VAL=1,
                append commandFlag $flag:SelSeq.PROC=1 
            } else {
                eval $statusCallback {"Removing flag."}
                append commandFlag $flag:act_cont_bo.VAL=0,$flag:SelSeq.PROC=0,$flag:LampOn=0
            }
            if [catch {eval $commandFlag} result] {
                return -code error "APSConfigureCameraPVs: $result"}
            
            set flagReadback $flag:act_status_mbbi
        }
	BTS {
	    set commandFlag "exec cavput -list=" 
            if $flagIn {
                eval $statusCallback {"Inserting flag."}
                append commandFlag $flag:LampOnBo=$lampOn,\
                    $flag:act_cont_bo.VAL=1,
                append commandFlag $flag:SelSeq.PROC=1 
            } else {
                eval $statusCallback {"Removing flag."}
                append commandFlag $flag:act_cont_bo.VAL=0,$flag:SelSeq.PROC=0,$flag:LampOnBo=0
            }
            if [catch {eval $commandFlag} result] {
                return -code error "APSConfigureCameraPVs: $result"}
            
            set flagReadback $flag:act_status_mbbi
	}
        default {
            return -code error "APSConfigureCameraPVs: unknown system: $system"
        }
    }
    if {$flagIn && !$ignoreFlagReadback} {
        if {[catch {exec cawait \
                        -waitFor=$flagReadback,equal=1 -timeLimit=30} result]} {
            return -code error "APSConfigureCameraPVs: screen not moving: $result"
        }
    }
}

