
proc APSSRApplySteeringSetpoints {args} {
    set sector ""
    set source ""
    set plane ""
    set bpmList ""
    set deltaList ""
    set stepSizeLimit 2
    set stepInterval 1
    set review 0
    set statusCallback ""
    set dryRun 0
    set xp ""
    set yp ""
    APSStrictParseArguments {sector source plane bpmList deltaList review stepSizeLimit statusCallback dryRun xp yp stepInterval}
    
    if {![string length $sector] || ![string length $plane] || ![string length $bpmList] \
          || ![string length $deltaList] || ![string length $sector] } {
        return -code error "APSSRApplySteeringSetpoints(2): sector - $sector, plane - $plane, bpmList - $bpmList, deltaList - $deltaList have to be provided!"
    }
    switch $source {
        BM -
        ID -
        CUDSP0 -
        CUUSP0 {

        }
        default {
            return -code error "APSSRApplySteeringSetpoints(1): unknown source - $source provided!"
        }
    }
    set controllawDir /home/helios/oagData/sr/localSteering/lattices/default/${source}s/[format %02ld ${sector}]$source
    set waveformDir /home/helios/oagData/sr/orbitControllaw/waveforms
    set twissFile /home/helios/oagData/sr/lattices/default/aps.twi 
    switch $plane {
        h -
        x {
            set coord x
            set pl h
            set Coord X
        }
        v -
        y {
            set coord y
            set Coord Y
            set pl v
        }
        default {
            return -code error "APSSRApplySteeringSetpoints2a - invalid plane - $plane provided."
        }
    }
    
    if [string length $statusCallback] {
        eval $statusCallback {"Computing $source $sector setpoint changes for $plane plane ..."}
    }
   
    set tmpRoot /tmp/[APSTmpString]
    
    # for sector 27 since FF uses xray setpoint, have to remove ID27 from FF and restart FF
    set runControlPV S:ID:GapFeedForwardRC
    set runControlDESC GapFeedforward
    set FFdir /home/helios/oagData/feedForwardFiles/IDgap
    if {$sector==27} {
        if [catch {exec sddsprocess $FFdir/FF \
                     "-match=par,ReadbackName=ID27:Gap,!" $FFdir/FF.other } result] {
            return -code error "Error filtering ID27:Gap from FF table: $result"
        } else {
            #restart FF
            if [string length $statusCallback] {
                eval $statusCallback {"Restart gap FF without ID27 ..."}
            }
            if [catch {exec cavput -list=$runControlPV.ABRT=1 \
                     } result ] {
                return -code error "APSSRApplySteeringSetpoints(3): error aborting ID FF: $result"
            }
            after 1000
            #restart ID FF
            exec sddsfeedforward $FFdir/FF.other \
              -interval=1 \
              -infinite \
              -runcontrolPV=string=$runControlPV,pingTimeout=12 \
              -runcontrolDescription=$runControlDESC &
        }
    }

    if {$dryRun || $review} {
        if !$review {
            set dryRunOpt " -dryRun"
        } else {
            set dryRunOpt " -review"
        }
    } else {
        set dryRunOpt ""
    }
    if {$source=="BM" && $plane=="h"} {
        set rfOpt " -changeRF"
    } else {
        set rfOpt ""
    }
    if [catch {exec logMessage -sourceId=steeringAudit -tag=Instance $source${sector} -tag=Action Start \
             } result ] {
        APSAlertBox .alert -errorMessage "APSSRApplySteeringSetpoints15a: Error with logMessage: $result"
        return
    }
    if [catch {eval exec makesrbump $controllawDir/irm.$coord $tmpRoot.setpoint.$plane $dryRunOpt $rfOpt \
                 -referenceMatrix=$controllawDir/$plane.steering.rm -deltaLimit=$stepSizeLimit \
                 -bpmList=[join $bpmList ,] -deltaList=[join $deltaList ,] -rampInterval=$stepInterval \
                 -corrSuffix=:CurrentAO -bpmSuffix=:ms:$coord:SetpointAO \
                 -waveform=$waveformDir/deltaWaveform.$plane -twissFile=$twissFile -verbose} result] {
        return -code error "APSSRApplySteeringSetpoints(4 - makesrbump): $result"
    }
    if $review {
        exec sddsplot -grap=sym,conn,scale=2,fill -axes=x \
          -col=BPMName,delta "-title=Sector $sector $plane plane expected bpm setpoint changes" $tmpRoot.setpoint.$plane \
          "-device=motif,(-newzoom true -geometry -0-00)" &
        after 1000
        set files [glob $tmpRoot.*]
        APSAddToTmpFileList -ID steering -fileList $files
        return
    }
    
    if [string length $statusCallback] {
        eval $statusCallback {"$result"}
    }
    if !$dryRun {
        #update the accumulator
        switch $source {
            ID -
            BM 
            {
                set PVprefix ${source}[format %02ld $sector]
            }
            CUUSP0 {
                set PVprefix ID[format %02ld $sector]us
            }
            CUDSP0 {
                set PVprefix ID[format %02ld $sector]ds
            }
            default {
                set PVprefix ${source}[format %02ld $sector]
            }
        }
        switch $plane {
            h {
                set delta $xp
                set pvs [list $PVprefix:XpActualAccum $PVprefix:XpRunAccum]
            }
            v {
                set delta $yp
                set pvs [list $PVprefix:YpActualAccum $PVprefix:YpRunAccum]
            }
        }
        if [string length $delta] {
            if [catch {exec cavput -list=[lindex $pvs 0]=$delta,[lindex $pvs 1]=$delta -deltaMode -pend=20} result] {
                return -code error "APSSRApplySteeringSetpoints14: Error updating the steering accumulator: $result"
            }
        }
        if [catch {exec cavput -list=${PVprefix}:SteeringCount=1 -deltaMode -pend=20} result] {
            return -code error "APSSRApplySteeringSetpoints14a: Error increasing steering count: $result"
        }
    }
    if [string length $statusCallback] {
        eval $statusCallback {"Apply $plane corrector and bpm setpoints done."}
    }
    set files [glob $tmpRoot.*]
    #APSAddToTmpFileList -ID steering -fileList $files
    if [catch {exec logMessage -sourceId=steeringAudit -tag=Instance $source${sector} -tag=Action Done \
               } result ] {
        APSAlertBox .alert -errorMessage "APSSRApplySteeringSetpoints15: Error with logMessage: $result"
        return
    }
    #update GRID XBPM FF table
    if {$sector==27} {
        if [string length $statusCallback] {
            eval $statusCallback {"Updating gap FF table for ID 27."}
        }
        if [catch {exec cavget -list=S27ID:P1:ms: -list=x,y -list=:SetpointAO -pend=20} setpointList] {
            return -code error "APSSRApplySteeringSetpoints16: Error reading $sector xray bpm setpoints: $setpointList"
        }
        set xsetpoint [lindex $setpointList 0]
        set ysetpoint [lindex $setpointList 1]
        set removeX 0
        set FFdir /home/helios/oagData/feedForwardFiles/IDgap
        set newFile [APSNextGenerationedName -directory $FFdir -name FF.0001 -separator . -newFile 1]
        if {[expr abs($xsetpoint)]>0.2} {
            set removeX 1
            #do not use the new setpoint for x
            if [catch {exec sddsprocess $FFdir/FF $FFdir/$newFile \
                         "-redefine=col,ActuatorValue,ActuatorName \"S27ID:P1:ms:y:SetpointAO\" streq ReadbackValue 30.01 < && ? $ysetpoint : ActuatorValue $ " } result] {
                return -code error "APSSRApplySteeringSetpoints17: error generating new FF table for ID27 y bpm: $result"
            }
        } else {
            if [catch {exec sddsprocess $FFdir/FF $FFdir/$newFile \
                         "-redefine=col,ActuatorValue,ActuatorName \"S27ID:P1:ms:y:SetpointAO\" streq ReadbackValue 30.01 < && ? $ysetpoint : ActuatorValue $ " \
                         "-redefine=col,ActuatorValue,ActuatorName \"S27ID:P1:ms:x:SetpointAO\" streq ReadbackValue 30.01 < && ? $xsetpoint : ActuatorValue $ " } result] {
                return -code error "APSSRApplySteeringSetpoints18: error generating new FF table for ID27: $result"
            }
        }
        cd /home/helios/oagData/feedForwardFiles/IDgap
        exec rm FF
        exec ln -s $newFile FF
        #restart ID FF
        set dataDir /home/helios/oagData/feedForwardFiles/IDgap
        set runControlPV S:ID:GapFeedForwardRC
        set runControlDESC GapFeedforward
        if [catch {exec cavput -list=$runControlPV.ABRT=1 \
                 } result ] {
            return -code error "APSSRApplySteeringSetpoints18: error aborting ID FF: $result"
        }
        after 1000
        #restart ID FFp@22
         exec sddsfeedforward $dataDir/FF \
          -interval=1 \
          -infinite \
          -runcontrolPV=string=$runControlPV,pingTimeout=12 \
          -runcontrolDescription=$runControlDESC &
        
        if $removeX {
            #check if S27ID:P1 x in h.defaultXRDP first
            if [catch {exec sddsprocess /home/helios/oagData/sr/orbitControllaw/lattices/default/h.defaultXRDP/config \
                         -match=par,NameType=MonitorNames -match=col,Name=S27ID:P1 -pipe=out -nowarnings \
                     | sdds2stream -pipe=in -rows=bar } rows] {
                return
                #S27ID:P1 does not exist in h.defaultXRDP, do nothing
            }
            if !$rows {
                return
            }
            if [string length $statusCallback] {
                eval $statusCallback {"remove S27ID:P1 x from h.defaultXRDP ..."}
            }
            if [catch {exec removeDeviceFromConfig -configList h.defaultXRDP -deviceList S27ID:P1 -install 1} result] {
                return -code error "APSSRApplySteeringSetpoints21( removeDeviceFromConfig): $result"
            }
            if [catch {APSCheckControllawRunning -config h.defaultXRDP} running] {
                return -code error "APSSRApplySteeringSetpoints21:APSCheckControllawRunning $plane plane): $running"
            }
            #transfer the rf bpms in S27/28 
            set statusFile /home/helios/oagData/sr/BPMStatus/config.sdds
            set putcomm ""
            if [catch {exec sddsprocess $statusFile -pipe=out \
                         -filter=col,NonexistentH,0,0 \
                         "-match=col,DeviceName=*ID*,!" \
                         "-match=col,DeviceName=*BM*,!" \
                         "-match=col,DeviceName=S27*,DeviceName=S28*,|" \
                         | sdds2stream -pipe -col=DeviceName } pvList] {
                return -code error "APSSRApplySteeringSetpoints21a: $pvList"
            }
            if [catch {exec cavget -list=[join $pvList ,] -list=:msAve:x:ErrorCC -pend=120} valList] {
                return -code error "APSSRApplySteeringSetpoints21b: $valList"
            }
            foreach pv $pvList val $valList {
                lappend putcomm ${pv}:ms:x:SetpointAO=$val
            }
            if [string length $statusCallback] {
                eval $statusCallback {"transfer S27/S28 rf bpm setpoints ..."}
            }
            if [catch {exec cavput -list=[join $putcomm ,] -deltaMode -pend=120} result] {
                return -code error "APSSRApplySteeringSetpoints21c: $result"
            }
            
            if $running {
                #abort and restart orbit correction
                 #abort controllaw
                catch {exec logMessage -sourceId=steeringAudit \
                         -tag=Instance DP:S:OrbitControlLawXSDDS -tag=Action Abort}
                if [catch {exec cavput -list=DP:S:OrbitControlLawXSDDS.ABRT=1 -pend=30 } result] {
                    return -code error "APSSRApplySteeringSetpoints22: error aborting $plane XRDP orbit correction: $result"
                }
                after 2000
                #restart controllaw
                catch {exec logMessage -sourceId=steeringAudit \
                         -tag=Instance DP:S:OrbitControlLawXSDDS -tag=Action Start}
                if [catch {exec cavput -list=DP:S:OrbitControlLawXSDDS.CMND=1 -pend=30} result] {
                    return -code error "APSSRApplySteeringSetpoints23: error starting $plane XRDP orbit correction."
                }
                if [catch {exec cavput -list=S27ID:P1:ms:x:InUseBO=0 -pend=30} result] {
                    return -code error "APSSRApplySteeringSetpoints24: error un-setting inUse PVs: $result"
                }
            }
        }
    }
    return
}

proc APSSRSaveSteeringToOps {args} {
    set description ""
    set statusCallback ""
    set installUBOP 0
    APSStrictParseArguments {description statusCallback installUBOP}
    
    if [string length $statusCallback] {
        eval $statusCallback {"Do SCR save of SROrbitSetPt SRCorSetpts SR ..."}
    }
    foreach system {SROrbitSetPt SRCorSetpts SR} {
        if [catch {APSSaveMachine -machine $system \
                     -description "$description" } result] {
            return -code error "APSSRSaveSteeringToOps1: APSSaveMachine: $result"
        }
        set ${system}snapshot [lindex $result 0]
    }
    if [catch {exec cavget -list=S:DesiredMode -num -pend=10} srMode] {
        return -code error "Error reading SR mode: $srMode"
    }
    
    if {$srMode==1 || $srMode==2} {
        set installUBOP 1
    } else {
        set installUBOP 0
    }
    
    if $installUBOP {
        if [string length $statusCallback] {
            eval $statusCallback {"Make new SR UBOP..."}
        }
        if [catch { APSSCRInstallPreferredFile -system SR -choice "User beam operator preferred" -filename $SRsnapshot } result] {
            return -code error "APSSRSaveSteeringToOps2: error installing $SRsnapshot as UBOP: $result"
        }
    }
    if [string length $statusCallback] {
        eval $statusCallback {"done"}
    }
    return $SRsnapshot
}
