#!/bin/sh
# \
exec oagwish "$0" "$@"

set auto_path [linsert $auto_path 0 /usr/local/oag/apps/lib/$env(HOST_ARCH)]
set auto_path [linsert $auto_path 0 /usr/local/oag/lib_patch/$env(HOST_ARCH)]
APSDebugPath

set bpmHList {LTP:PH1 LTP:PH2 LTP:PH3 LTP:PH4}
set bpmVList {LTP:PV1 LTP:PV2 LTP:PV3 LTP:PV4}
set bpmHVarList {LTPPH1 LTPPH2 LTPPH3 LTPPH4}
set bpmVVarList {LTPPV1 LTPPV2 LTPPV3 LTPPV4}

# Set LTP BPM setpoints to the current BPM readback values.  Used in conjunction with controlLaw to steer
# to an arbitrary trajectory.

set ControlStatus "Ready."

proc MakeLTPBPMSetpointConfigMenuAndStatus {} {

        APSApplication . -name "LTPBPMSetpointConfig" -version "1.0" \
                         -overview "This is an application to set the LTP BPM setpoints to the current BPM readbacks"

        APSMenubarAddMenu .controlLaw -parent .menu -text "ControlLaw"

                .menu.controlLaw.menu add command -label "LTP ControlLaw" \
                        -command {exec controllaw -controlList "ltp" &}

        APSScrolledStatus .status -parent .userFrame -textVariable ControlStatus \
                          -height 8 -width 65 -packOption {-side top}
}

# Make checkbuttons for LTP BPMs and execution button.

proc MakeLTPBPMCheckbuttonAndExecuteFrame {widget args} {

        global bpmHList bpmVList bpmHVarList bpmVVarList

        set parent ""
        APSParseArguments {parent}

        APSFrame $widget -parent $parent -label "LTP BPM Selection" \
                   -packOption {-side left -expand 1 -fill x} \
                   -contextHelp "Selection panel for LTP BPMs."

        set w $parent$widget.frame

        APSCheckButtonFrame .bpmHButtons -parent $w \
                   -label "Horizontal\nLTP BPMs" -buttonList $bpmHList \
                   -variableList "$bpmHVarList" -allNone 1 -toggle 1 \
                   -packOption {-side left -expand 1} \
                   -contextHelp "Horizontal LTP BPM selection panel."

        APSButton .transferButton -parent $w \
                   -text "Transfer LTP Readbacks To\nControlLaw Setpoints" \
                   -command {SetLTPBPMSetpoints -statusCallback SetStatus} \
                   -packOption {-side left -expand 1} \
                   -contextHelp "This button transfers current LTP BPM readbacks to controllaw setpoints"

        APSCheckButtonFrame .bpmVButtons -parent $w \
                                -label "Vertical\nLTP BPMs" -buttonList $bpmVList \
                                -variableList "$bpmVVarList" -allNone 1 -toggle 1 \
                                -packOption {-side left -expand 1} \
                                -contextHelp "Vertical LTP BPM selection panel."
}

# Status line update procedure

proc SetStatus {text} {
        global ControlStatus
        set ControlStatus $text     
        update
}

# procedure to set LTP bpm steering setpoints to bpm readback values.

proc SetLTPBPMSetpoints {args} {

        global bpmHList bpmVList bpmHVarList bpmVVarList HValList VValList
        global LTPPH1 LTPPH2 LTPPH3 LTPPH4
        global LTPPV1 LTPPV2 LTPPV3 LTPPV4

        APSParseArguments {statusCallback}

        if {$statusCallback!=""} {
                $statusCallback "Getting 10 BPM readbacks for selected BPMs and averaging..."
        }

        set listindex 0 
        set HBPMSelectList ""
        set HCavgetCommandList ""
        set HCavputCommandList ""
        set VBPMSelectList ""
        set VCavgetCommandList ""
        set VCavputCommandList ""
        
        foreach hbpm $bpmHList {

                set HBPMChoice [subst $[lindex $bpmHVarList $listindex]]
                set VBPMChoice [subst $[lindex $bpmVVarList $listindex]]

                if {$HBPMChoice==1} {
                        lappend HBPMSelectList $hbpm
                        lappend HCavgetCommandList "$hbpm:x"
                }
                if {$VBPMChoice==1} {
                        set vbpm [lindex $bpmVList $listindex]
                        lappend VBPMSelectList $vbpm
                        lappend VCavgetCommandList "$vbpm:y"
                }
        incr listindex
        }
        if {$HBPMSelectList!="" && $VBPMSelectList!=""} {
                set HBPMCavgetCommand [cavputcavgetMakeCommand cavget $HCavgetCommandList]
                set VBPMCavgetCommand [cavputcavgetMakeCommand cavget $VCavgetCommandList]
                set HValList [eval exec $HBPMCavgetCommand]   
                ConvertListToArray $HValList $HBPMSelectList HBPMValueArray
                set VValList [eval exec $VBPMCavgetCommand]
                ConvertListToArray $VValList $VBPMSelectList VBPMValueArray
                set HCavputCommandList [ComposeCavputCommandList H HBPMValueArray]
                set VCavputCommandList [ComposeCavputCommandList V VBPMValueArray]
                set HBPMCavputCommand [cavputcavgetMakeCommand cavput $HCavputCommandList]
                set VBPMCavputCommand [cavputcavgetMakeCommand cavput $VCavputCommandList]
                eval exec $HBPMCavputCommand
                eval exec $VBPMCavputCommand
                if {$statusCallback!=""} {
                        $statusCallback "Horizontal average BPM readbacks transferred to controllaw setpoints for:\n$HBPMSelectList"
                        $statusCallback "Vertical average BPM readbacks transferred to controllaw setpoints for:\n$VBPMSelectList."
                }
                bell
        } elseif {$HBPMSelectList!="" && $VBPMSelectList==""} {
                set HBPMCavgetCommand [cavputcavgetMakeCommand cavget $HCavgetCommandList]
                set HValList [eval exec $HBPMCavgetCommand]
                ConvertListToArray $HValList $HBPMSelectList HBPMValueArray
                set HCavputCommandList [ComposeCavputCommandList H HBPMValueArray]
                set HBPMCavputCommand [cavputcavgetMakeCommand cavput $HCavputCommandList]
                eval exec $HBPMCavputCommand   
                if {$statusCallback!=""} {
                        $statusCallback "Horizontal average BPM readbacks transferred to controllaw setpoints for:\n$HBPMSelectList"
                }
                bell
        } elseif {$HBPMSelectList=="" && $VBPMSelectList!=""} {
                set VBPMCavgetCommand [cavputcavgetMakeCommand cavget $VCavgetCommandList]
                set VValList [eval exec $VBPMCavgetCommand]
                ConvertListToArray $VValList $VBPMSelectList VBPMValueArray
                set VCavputCommandList [ComposeCavputCommandList V VBPMValueArray]
                set VBPMCavputCommand [cavputcavgetMakeCommand cavput $VCavputCommandList]
                eval exec $VBPMCavputCommand
                if {$statusCallback!=""} {
                        $statusCallback "Vertical average BPM readbacks transferred to controllaw setpoints for:\n$VBPMSelectList"
                }
                bell
        } else {
                if {$statusCallback!=""} {
                        $statusCallback "No BPMs selected."
                }
                bell
        }
}

# procedure to compose cavput/cavget commands.  Added average option to cavget to average 10
# samples at 1 second intervals.

proc cavputcavgetMakeCommand {action commandList} {

        if {$action=="cavput"} {
                set beforeLastCommaIndex [expr [llength $commandList] - 1]
                set listCommand [lrange $commandList 0 $beforeLastCommaIndex]
                set listCommand [join $listCommand {,}]
                set cavputCommand "-list="
                lappend cavputCommand $listCommand
                set cavputCommand [join $cavputCommand {}]
                set finalcavputCommand "cavput"
                lappend finalcavputCommand $cavputCommand
                return $finalcavputCommand
        } elseif {$action=="cavget"} {
                set beforeLastCommaIndex [expr [llength $commandList] - 1]
                set listCommand [lrange $commandList 0 $beforeLastCommaIndex]
                set listCommand [join $listCommand {,}]
                set cavgetCommand "-list="
                lappend cavgetCommand $listCommand
                set cavgetCommand [join $cavgetCommand {}]
                set finalcavgetCommand "cavget"
                lappend finalcavgetCommand $cavgetCommand "-repeat=number=10,average,pause=1"
                return $finalcavgetCommand
        } else {return 0}
}

# procedure to set LTP BPM setpoint variables to readback values.  Returns a list of cavput commands.  Returns 0
# if no list is created.

proc ComposeCavputCommandList {plane valueArray} {

        global $valueArray
        upvar $valueArray valueArrayName
        global bpmHList bpmVList bpmHVarList bpmVVarList 
        global LTPPH1 LTPPH2 LTPPH3 LTPPH4
        global LTPPV1 LTPPV2 LTPPV3 LTPPV4

        set listindex 0

        foreach hbpm $bpmHList {

                set HBPMChoice [subst $[lindex $bpmHVarList $listindex]]
                set VBPMChoice [subst $[lindex $bpmVVarList $listindex]]

                if {$HBPMChoice==1 && $plane=="H"} {
                        lappend HCavputCommandList "$hbpm:SetpointAO=$valueArrayName($hbpm)"
                }
                if {$VBPMChoice==1 && $plane=="V"} {
                        set vbpm [lindex $bpmVList $listindex]
                        lappend VCavputCommandList "$vbpm:SetpointAO=$valueArrayName($vbpm)"
                }
        incr listindex
        }
        if {$plane=="H"} {
                return $HCavputCommandList
        } elseif {$plane=="V"} {
                return $VCavputCommandList
        } else {return 0}
}

# Converts a list to a 1 dimensional array indexed by an index list of the same number of items as the list or less
# If the index list has more items than the list, the resulting list is padded with zeros at the end
# If both lists are null, the array returned is a one element array containing 0
# N. Sereno

proc ConvertListToArray {list indexlist arrayName} {

        global $arrayName
        upvar $arrayName arrayname
        
        set listlength [llength $list]
        set indexlistlength [llength $indexlist]

        set listindex 0
        foreach item $indexlist {

                set arrayname($item) [lindex $list $listindex]
                if {$listindex >= $listlength} {set arrayname($item) 0}
                incr listindex 1
        }

        if {($listlength == 0) && ($indexlistlength == 0)} {set arrayname(0) 0}
}

# Build Application

MakeLTPBPMSetpointConfigMenuAndStatus
MakeLTPBPMCheckbuttonAndExecuteFrame .bpmFrame -parent .userFrame
