
proc APSMpSRTuneUpInjectionInfo {} {
    return "This procedure helps with tuning up injection into the storage ring.  Execute it if you are having trouble accumulating well.  It will dump any stored beam you already have!"
}

set apsMpSRTuneUpInjection(IK1) 0
set apsMpSRTuneUpInjection(IK2) 0
set apsMpSRTuneUpInjection(IK3) 0
set apsMpSRTuneUpInjection(IK4) 0

#This procedure has been placed in the attic
proc APSMpSRTuneUpInjection {} {
    global status mpInterface execMode
    APSMpStep init -promptDialog APSMpPromptInitDialog
    APSSetVarAndUpdate status "Disabling SR pulsed PS."
    APSMpStep "Disabling SR pulsed PS" -desc "Disable SR pulsed PS" -proc "APSSRPulsedPSDischargeEnable"
    if [catch {APSSRPulsedPSDischargeEnable -PSList {IS1 IS2 IK} -disable 1} result] {
        APSMpReturn error "Problem disabling pulsed PS discharge: $result"
    }

    set oldExecMode $execMode
    set execMode Automatic

    APSSetVarAndUpdate status "Checking BTS state."
    APSMpStep "Checking BTS state" -desc "Check BTS state" -desc "APSMpBTSCheckInjection"
    if [catch {APSMpBTSCheckInjection -desiredState toRing} result] { 
        set execMode $oldExecMode
        APSMpReturn error "BTS is not sending beam to ring: $result"
    }

    # force into manual mode so instructions can be responded to
    set execMode Manual
    APSSetVarAndUpdate status "Checking BTS controllaw"
    APSMpStep "Checking BTS controllaw" -desc "Check BTS controllaw"
    if [catch {exec cavget -list=BTS:ControlLawXRC.RUN -pend=10} running] {
        set execMode $oldExecMode
        APSMpReturn error "Error getting status of BTS controllaw: $result"
    }

    if {!$running && \
          ![APSQueryToProceed -message "Ensure that BTS x controllaw is running."]} {
        set execMode $oldExecMode
        APSMpStep Instructions -desc "Ensure that BTS x controllaw is running"
    }

    APSSetVarAndUpdate status "Setting up to view beam on BTS:FS5"
    APSMpStep "Setting up to view beam on BTS:FS5" -desc "Set up to view beam on BTS:FS5"
    if {[catch {APSViewFlag -flag BTS:FS5} result] && \
          ![APSQueryToProceed -message \
              "Unable to insert/verify BTS:FS5.  Please insert it yourself to proceed."]} {
        set execMode $oldExecMode
    }
    APSSetVarAndUpdate status "View the beam on the flag FS5 (just inserted)."
    APSSetVarAndUpdate status "Verify it is well centered."
    APSSetVarAndUpdate status "If not, try Booster Ext Septum \#1"
    APSMpStep CheckBTSFS5 -desc "Check BTS FS5 is centered"
    if {[catch {APSViewFlag -flag BTS:FS5 -stop 1} result] && \
          ![APSQueryToProceed -message \
              "Unable to remove/verify BTS:FS5. Please remove it yourself to proceed."]} {
        set execMode $oldExecMode
        APSMpReturn error "Problem removing flag BTS:FS5: $result"
    }

    APSSetVarAndUpdate status "Setting up to view beam on BTS:FS6"
    APSMpStep "Setting up to view beam on BTS:FS6" -desc "Set up to view beam on BTS:FS6"
    if {[catch {APSSRPulsedPSDischargeEnable -PSList IS1} result] && \
          ![APSQueryToProceed -message \
              "Unable to enable/verify IS1.  Enable it yourself to proceed."]} {
        set execMode $oldExecMode
        APSMpReturn error "Problem enabling charge on IS1: $result"
    }
    if {[catch {APSViewFlag -flag BTS:FS6} result] && \
          ![APSQueryToProceed -message \
              "Unable to insert/verify BTS:FS6. Please insert it yourself to proceed."]} {
        set execMode $oldExecMode
        APSMpReturn error "Problem setting up to view BTS:FS6 flag: $result"
    }
    APSSetVarAndUpdate status "View the beam on the flag FS6 (just inserted)."
    APSSetVarAndUpdate status "Verify it is in the proper position."
    APSSetVarAndUpdate status "If not, try the last two BTS correctors."
    APSMpStep CheckBTSFS6 -desc "Check BTS FS6 is in the proper position"
    if {[catch {APSViewFlag -flag BTS:FS6 -stop 1} result] && \
          ![APSQueryToProceed -message \
              "Unable to remove/verify BTS:FS6. Please remove it yourself to proceed."]} {
        set execMode $oldExecMode
        APSMpReturn error "Problem removing flag BTS:FS6: $result"
    }

    APSSetVarAndUpdate status "Setting up to store beam w/o accumulation"
    APSMpStep "Setting up to store beam w/o accumulation" -desc "Set up to store beam w/o accumulation" -proc "APSSRStoreWithoutAccumulation"
    if [catch {APSSRStoreWithoutAccumulation} result] {
        if [catch {APSSRStoreWithoutAccumulation -stop 1} result] {
            APSAlertBox [APSUniqueName .] -errorMessage \
              "Error trying to restore kicker setpoints.  You probably want to use SCR to do this."
        }
        set execMode $oldExecMode
        if {[catch {APSSRPulsedPSDischargeEnable -PSList {IS1 IS2 IK} -disable 1} result1]} {
            APSAlertBox [APSUniqueName .] -errorMessage \
              "Error setting up for storing beam without accumulation.  Unable to disable pulsed magnets!  Do this yourself to avoid a rad monitor trip."
        }
        APSMpReturn error "Error setting up for storing beam without accumulation: $result."
    }
    APSSetVarAndUpdate status "Now set up for storing beam without accumulation."
    APSSetVarAndUpdate status "Checking storage ring..."
    APSMpStep "Checking storage ring" -desc "Check storage ring" -proc "APSMpSRCheckInjection"
    set execMode Automatic
    if {[catch {APSMpSRCheckInjection -includeBTS 0} result] && \
          ![APSQueryToProceed -message \
              "Problems detected with storage ring.  If these are acceptable, press Proceed."]} {
        if {[catch {APSSRPulsedPSDischargeEnable -PSList {IS1 IS2 IK} -disable 1} result1]} {
            APSAlertBox [APSUniqueName .] -errorMessage \
              "Problems detected with storage ring and unable to disable pulsed magnets!  Do this \
yourself to avoid a rad monitor trip."
        }
        if [catch {APSSRStoreWithoutAccumulation -stop 1} result] {
            APSAlertBox [APSUniqueName .] -errorMessage \
              "Error trying to restore kicker setpoints.  You probably want to you SCR to do this."
        }
        set execMode $oldExecMode
        APSMpReturn error "Problems detected with storage ring."
    }
    set execMode Manual

    APSSetVarAndUpdate status "Setting up to view beam on S39BFL."
    APSMpStep "Setting up to view beam on S39BFL" -desc "Set up to view beam on S39BFL"
    if {[catch {APSViewFlag -flag S39BFL} result] && \
          ![APSQueryToProceed -message \
              "Unable to insert/verify S39BFL.  Please insert it yourself to proceed."]} {
        set execMode $oldExecMode
        if [catch {APSSRStoreWithoutAccumulation -stop 1} result] {
            APSAlertBox [APSUniqueName .] -errorMessage \
              "Error trying to restore kicker setpoints.  You probably want to you SCR to do this."
        }
        APSMpReturn error "Problem setting up to view S39BFL flag: $result"
    }

    APSSetVarAndUpdate status "View the beam on the flag S39BFL."
    APSSetVarAndUpdate status "Verify it is in the center of the dark spot."
    APSSetVarAndUpdate status "If not, try the last two BTS correctors."
    APSMpStep CheckS39BFL -desc "Check S39BFL and verify it is in the center of the dark spot"
    if {[catch {APSViewFlag -flag S39BFL -stop 1} result] && \
          ![APSQueryToProceed -message \
              "Unable to remove/verify S39BFL.  Please remove it yourself to proceed."]} {
        set execMode $oldExecMode
        if {[catch {APSSRPulsedPSDischargeEnable -PSList {IS1 IS2 IK} -disable 1} result1]} {
            APSAlertBox [APSUniqueName .] -errorMessage \
              "Error removing S39BFL and unable to disable pulsed magnets!  Do this \
yourself to avoid a rad monitor trip."
        }
        if [catch {APSSRStoreWithoutAccumulation -stop 1} result] {
            APSAlertBox [APSUniqueName .] -errorMessage \
              "Error trying to restore kicker setpoints.  You probably want to you SCR to do this."
        }
        APSMpReturn error "Problem removing flag S39BFL: $result"
    }

    catch {exec medm -x -attach -macro "UNIT=S33B:P5" beamHchanWF.adl &} medmPID
    if 0 {
        if {[catch \
               {exec cavput -pend=10 -list=S33B:P5: \
                  "-list=bh.FIM0=Stop on Full,bh.FIR0=Enable,bh.BRDE=Enable,bh.BRDM=Continuous,bh.SSEN=Disable,bh:wfDisable_bo=Enable"} result] || \
              [catch {exec cavput -pend=10 -list=S:bpm33:time.P0CT=1} result]} {
            APSAlertBox [APSUniqueName .] -errorMessage \
              "Error trying to set up S35B:P5 beam history to view synchrotron oscillations.  You may continue without this."
        }
    }

    APSSetVarAndUpdate status "Recall configuration 2 on the scope."
    APSSetVarAndUpdate status "Adjust inter-ring rf phase and BTS:CH1 and BTS:BH1"
    APSSetVarAndUpdate status "to maximize the amount of beam captured."
    APSSetVarAndUpdate status "Also, use the S33B:P5 beam history and minimize"
    APSSetVarAndUpdate status "the oscillations using the inter-ring rf phase"
    APSSetVarAndUpdate status "and booster extraction turns counter."
    APSSetVarAndUpdate status "Hit continue when optimized."
    APSMpStep Instructions -desc "Recall configuration 2 on the scope. Adjust inter-ring rf phase and BTS:CH1 and BTS:BH1 to maximize the amount of beam captured. Also, use the S33B:P5 beam history and minimize the oscillations using the inter-ring rf phase and booster extraction turns counter."

    catch {exec kill $medmPID}
    if 0 {
        if {[catch \
               {exec cavput -pend=10 -list=S33B:P5: \
                  "-list=bh.FIM0=Continuous Fill,bh.FIR0=Disable,bh:wfDisable_bo=Disable"} result] || \
              [catch {exec cavput -pend=10 -list=S:bpm33:time.P0CT=1} result]} {
            APSAlertBox [APSUniqueName .] -errorMessage \
              "Error trying to set up S35B:P5 beam history to view synchrotron oscillations.  You may continue without this."
        }
    }

    APSSetVarAndUpdate status "Setting up to store beam with accumulation."
    APSMpStep "Setting up to store beam with accumulation" -desc "Set up to store beam with accumulation"
    if {[catch {APSSRPulsedPSDischargeEnable -PSList {IS1 IS2 IK} -disable 1} result]} {
        APSAlertBox [APSUniqueName .] -errorMessage \
              "Unable to disable pulsed magnets!  Do this yourself to avoid a rad monitor trip."
        if [catch {APSSRStoreWithoutAccumulation -stop 1} result] {
            APSAlertBox [APSUniqueName .] -errorMessage \
              "Error trying to restore kicker setpoints.  You probably want to you SCR to do this."
        }
        APSMpReturn error "Unable to disable pulsed magnets."
    }

    if [catch {APSSRStoreWithoutAccumulation -stop 1} result] {
        set execMode $oldExecMode
        if {[catch {APSSRPulsedPSDischargeEnable -PSList {IS1 IS2 IK} -disable 1} result1]} {
            APSAlertBox [APSUniqueName .] -errorMessage \
              "Error reverting to previous kicker settings and unable to disable pulsed magnets. Do this \
yourself to avoid a rad monitor trip."
        }
        APSMpReturn error "Problem reverting to previous kicker settings."
    }

    APSSetVarAndUpdate status "Set up to store beam, with pulsed magnets disabled."
    APSMpStep Instructions -desc "Set up to store beam, with pulsed magnets disabled"

    set execMode $oldExecMode
    APSMpReturn ok
}

proc APSViewFlag {args} {
    set stop 0
    set flag ""
    APSStrictParseArguments {stop flag} 

    for {set try 0} {$try<3} {incr try} {
        if $stop {
            # remove the flag and turn off the light
            if [catch {exec cavput -pend=10 -list=$flag=0 -list=:act_cont_bo,:LampOnBo} result] {
                return -code error "Unable to remove flag $flag"
            }
            set resultWanted "0 0"
        } else {
            # insert the flag and turn on the light
            if [catch {exec cavput -pend=10 -list=$flag=1 \
                         -list=:act_cont_bo,:LampOnBo,:SelSeq.PROC} result] {
                return -code error "Unable to remove flag $flag"
            }
            set resultWanted "1 1"
        }
        after 2000
        if [catch {exec cavget -list=$flag -list=:act_cont_bo,:LampOnBo -numerical -pend=10} result] {
            return -code error "Unable to get flag status: $result"
        }
        if [string compare [join $result] $resultWanted]==0 {
            return -code ok
        }
    }
    return -code error "Unable to change $flag state."
}


proc APSSRStoreWithoutAccumulation {args} {
    global IK1Voltage IK2Voltage IK3Voltage IK4Voltage KickerDischarge
    global apsMpSRTuneUpInjection
    set stop 0
    APSStrictParseArguments {stop}

    if [catch {APSSRPulsedPSDischargeEnable -PSList {IS1 IS2 IK} -disable 1} result] {
        return -code error "Problem disabling pulsed PS discharge: $result"
    }
    if $stop {
        # set kickers back to previous values
        set putList ""
        foreach kicker {IK1 IK2 IK3 IK4} {
            append putList ${kicker}=$apsMpSRTuneUpInjection($kicker)
        }
        for {set try 0} {$try<3} {incr try} {
            # need to repeat since it often fails.
            if [catch {exec cavput -pend=10 -list=S: -list=[join $putList] -list=:VoltageSetSendAO} result] {
                return -code error "Problem changing kicker voltages."
            }
            after 1000
        }
    } else {
        # record kicker setpoints
        # set IK1 to 14kV
        if [catch {exec cavget -pend=10 -list=S:IK -list=1,2,3,4 -list=:VoltageSetSendAO} result] {
            return -code error "Problem reading kicker voltages."
        }
        for {set index 0} {$index<4} {incr index} {        
            set apsMpSRTuneUpInjection(IK[expr $index+1]) [lindex $result $index]
        }
        for {set try 0} {$try<3} {incr try} {
            # need to repeat since it often fails.
            if [catch {exec cavput -pend=10 -list=S:IK1:VoltageSetSendAO=14} result] {
                return -code error "Problem changing IK1 voltage."
            }
            after 1000
        }
        # turn on kicker and septum discharge
        if [catch {APSSRPulsedPSDischargeEnable -PSList {IS1 IS2 IK} -disable 0} result] {
            return -code error "Problem enabling pulsed PS discharge: $result"
        }
    }
    return -code ok
}

proc APSSRPulsedPSDischargeEnable {args} {
    set PSList ""
    set disable 0
    APSStrictParseArguments {PSList disable}
    if [llength $PSList]==0 {
        return -code error "Empty PSList to APSSRPulsedPSDischargeEnable."
    }

    # IS1 Mt:Ddg3chan0.GATE
    # IS2 Mt:Ddg3chan1.GATE
    # IK  Mt:Ddg3chan4.GATE
    set numList ""
    foreach elem $PSList {
        switch $elem {
            IS1 { lappend numList 0 }
            IS2 { lappend numList 1 }
            IK  { lappend numList 4 }
            default {
                return -code error "Invalid Pulsed PS: $elem"
            }
        }
    }

    if [catch {exec cavput -pend=10 -list=Mt:Ddg3chan \
                 -list=[join $numList ,] -list=.GATE=[expr !$disable]} result] {
        return -code error "Problem changing state of pulsed PS discharge: $result"
    }
}

proc APSShutterPermitGiven {} {
    if [catch {exec cavget -list=RF-ACIS:LED:Sect1To35IdFesClsdM,RF-ACIS:LED:Sect35BmTo38AmFesClsdM -pend=10 -printErrors} result] {
        return -code error "APSShutterPermitGiven: $result"
    }
    if {([lindex $result 0] == 0) || ([lindex $result 1] == 0)} {
        return 1
    }
    return 0

#    if [catch {exec cavget -list=ACIS:RAI_SHTR_PERMIS,ACIS:FBO_BM35_S_PERM -pend=10} result] {
#        return -code error "APSShutterPermitGiven: $result"
#    }
#    if {[string equal [lindex $result 0] "1"] || [string equal [lindex $result 2] "1"] } {
#        return 1
#    }
#    return 0
}

proc APSTopupEnabled {} {
    if [catch {exec cavget -list=RF-ACIS:LED:SwapOutModeM -pend=10 -printErrors} result] {
        return -code error "APSTopupEnabled: $result"
    }
    if {$result == 1} {
        return 1
    }
    return 0

#    if [catch {exec cavget -list=ACIS:FAI_TOP_UP_SW,ACIS:FBI_TOPUP_ENA -pend=10} result] {
#        return -code error "APSTopupEnabled: $result"
#    }
#    if {[lindex $result 0] == 1 && [lindex $result 1] == 1 } {
#        return 1
#    }
#    return 0
}

proc APSDoubleStopClosed {} {
    if [catch {exec cavget -list=RF-ACIS:LED:BtSClosedM -pend=10 -printErrors} result] {
        return -code error "APSDoubleStopClosed: $result"
    }
    if {$result == 1} {
        return 1
    }
    return 0

#    if [catch {exec cavget -list=ACIS:S -list=AOI_BS7_CLOSED,AOI_BS8_CLOSED,BOI_BS7_CLS,BOI_BS8_CLS -pend=10} result] {
#        return -code error "APSDoubleStopClosed: $result"
#    }
#    foreach item $result {
#        if [string compare $item 0]!=0 {
#            return 1
#        }
#    }
#    return 0
}


proc APSSRGetBeamSwitchState {} {
    if [catch {exec cavget -pend=10 -list=ACIS:FAI_BX_GAP_ON,ACIS:FAI_AB_GAP_ON} result] {
        return -code error "APSSRGetBeamSwitchState: $result"
    }
    switch [join $result +] {
        0+1 {
            return ring
        }
        1+0 {
            return dump
        }
        default {
            return undefined
        }
    }
}

proc APSSRChangeBeamSwitchState {args} {
    set SCRpath /home/helios/oagData/SCR/snapshots/Booster
    set goTo dump
    APSStrictParseArguments {goTo}
    package require BLT
    global tk_version

    if [catch {exec cavget -list=BTS:DipoleSwitchingC,BTS:AB:PS:StandardizeDecayC,BTS:BX:PS:StandardizeDecayC -num -printErrors} switchState] {
        return -code error "APSSRChangeBeamSwitchState: Error reading BTS:DipoleSwitchingC $switchState"
    }
    if {[lindex $switchState 0]} {
        return -code error "APSSRChangeBeamSwitchState: Previous BTS Dipole switch is still ongoing"
    }
    if {[lindex $switchState 1]} {
        return -code error "APSSRChangeBeamSwitchState: Previous BTS:AB conditioning is still ongoing"
    }
    if {[lindex $switchState 2]} {
        return -code error "APSSRChangeBeamSwitchState: Previous BTS:BX conditioning is still ongoing"
    }
    switch $goTo {
        ring {
            #turn BTS beam before switch
            if [catch {SetPulsedMagnetEnables -location All -state 0 } result] {
                return -code error "APSSRChangeBeamSwitchState(dump): error turning off BTS beam: $result"
            }
            
            if [catch {APSShutterPermitGiven} permit] {
                return -code error "APSSRChangeBeamSwitchState: $permit"
            }
            if [catch {APSTopupEnabled} topupEnabled] {
                return -code error "APSSRChangeBeamSwitchState: $topupEnabled"
            }
            if [catch {APSDoubleStopClosed} doubleStopClosed] {
                return -code error "APSSRChangeBeamSwitchState: $doubleStopClosed"
            }
            if {$doubleStopClosed} {
                return -code error "APSSRChangeBeamSwitchState: double stop is closed, can't go to ring"
            }
            if {$permit && !$topupEnabled} {
                return -code error "APSSRChangeBeamSwitchState: shutter permit is given and topup not enabled---can't go to ring."
            }
            set tmpfile /tmp/[APSTmpString]

            if [catch {exec sddsprocess $SCRpath/Booster-SRInjection.gz -pipe=out \
                         -match=col,ControlName=BTS:AB:PS:SetCurrentC | sdds2stream -pipe=in \
                         -col=ValueString} abValue] {
                return -code error "APSSRChangeBeamSwitchState: $abValue"
            }
            
            if {[catch {exec cavput -list=BTS:DipoleSwitchingC=1} results]} {
                return -code error "APSSRChangeBeamSwitchState: $results"
            }
            global bg1Status
            global bg2Status
            set bg1Status ""
            set bg2Status ""
            blt::bgexec bg1Status \
              standardizePVwithDecayCL -pv "BTS:AB:PS:SetCurrentC" \
              -lowerLimit 0 -upperLimit $abValue \
              -numSteps 60 -numCycles 0 \
              -finalSetpoint $abValue &
            blt::bgexec bg2Status \
              standardizePVwithDecayCL -pv "BTS:BX:PS:SetCurrentC" \
              -lowerLimit 0 -upperLimit 319 \
              -numSteps 60 -numCycles 0 \
              -finalSetpoint 0 &
            if {$bg1Status == ""} {
                tkwait variable bg1Status
            }
            if {$bg2Status == ""} {
                tkwait variable bg2Status
            }
            if {[catch {exec cavput -list=BTS:DipoleSwitchingC=0} results]} {
                return -code error "APSSRChangeBeamSwitchState: $results"
            }
            if {0} {
                #turn on BTS beam after switch
                if [catch {SetPulsedMagnetEnables -location Gun -state 1 } result] {
                    return -code error "APSSRChangeBeamSwitchState(dump): error turning off BTS beam: $result"
                }
            }
        }
        dump {
            #turn off BTS beam before switch to dump
            if [catch {SetPulsedMagnetEnables -location All -state 0 } result] {
                return -code error "APSSRChangeBeamSwitchState(dump): error turning off BTS beam: $result"
            }
            #check the value state -- has to be open before go to dump to make sure no radiation goe sto stripline kicker
            
            while {1} {
                if [catch {exec cavget -list=VM:BTX:VV01:openBI -pend=10 -num -printErrors} volveState] {
                    return -code error "APSSRChangeBeamSwitchState(dump): error reading volve: $volveState"
                }
                if $volveState {
                    break
                }
                set answer [APSMultipleChoice [APSUniqueName .] -modal 1 \
                              -question "BTX gate volve is not open, please open it before go to dump!" \
                              -returnList {Done Abort} \
                              -labelList {Done Abort} ]
                if {$answer=="Abort"} {
                    return -code error "APSSRChangeBeamSwitchState(dump): aborted."
                }
            }
            if {[catch {exec cavput -list=BTS:DipoleSwitchingC=1} results]} {
                return -code error "APSSRChangeBeamSwitchState: $results"
            }
            global bg1Status
            global bg2Status
            set bg1Status ""
            set bg2Status ""
            blt::bgexec bg1Status \
              standardizePVwithDecayCL -pv "BTS:AB:PS:SetCurrentC" \
              -lowerLimit 0 -upperLimit 319 \
              -numSteps 60 -numCycles 0 \
              -finalSetpoint 0 &
            blt::bgexec bg2Status \
              standardizePVwithDecayCL -pv "BTS:BX:PS:SetCurrentC" \
              -lowerLimit 0 -upperLimit 319 \
              -numSteps 60 -numCycles 0 \
              -finalSetpoint 272 &
            if {$bg1Status == ""} {
                tkwait variable bg1Status
            }
            if {$bg2Status == ""} {
                tkwait variable bg2Status
            }
            if {[catch {exec cavput -list=BTS:DipoleSwitchingC=0} results]} {
                return -code error "APSSRChangeBeamSwitchState: $results"
            }
        }
        - {
            return -code error "APSSRChangeBeamSwitchState: invalid mode: $mode"
        }
    }
}
