#!/bin/sh  
# \
exec oagtclsh "$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)]
APSStandardSetup

# Typically the order file, if supplied, is one of /home/helios/oagData/sr/balancedFillOrders/*.putMe

set usage {usage: mbaSetUpFillWithGaps -nSlots <number>(324) -nGaps <number> -gapLength <slots> -guardBunches {0|1} -rootname <string> [-order <filename>]}
set nGaps -1
set gapLength -1
set guardBunches -1
set nSlots 324
set rootname ""
set order ""
set args $argv
if {[APSStrictParseArguments {nSlots nGaps gapLength guardBunches rootname order}] || \
      [expr $nSlots<0] || [expr $nGaps<0] || [expr $gapLength<0] || [expr $guardBunches<0] || [expr $guardBunches>1] || [string length $rootname]==0} {
    puts stderr $usage
    exit 1
}
if [expr $gapLength%2==1] {
    puts stderr "gapLength must be even"
    exit 1
}

if {[file exists $rootname.pattern] || [file exists $rootname.putMe]} {
    puts stderr "In use: $rootname"
    exit
}

if [expr $nSlots%$nGaps!=0] {
   puts stderr "nGaps=$nGaps does not divide evenly into $nSlots"
   exit 1
}

if {[string length $order]} {
    if {![file exists $order]} {
        puts stderr "not found: $order"
        exit 1
    }
    
}

for {set n 0} {$n<$nSlots} {incr n} {
    set multiplier($n) 1
}

for {set gap 0} {$gap<$nGaps} {incr gap} {
    set limit1 [expr ($gap+1)*$nSlots/$nGaps]
    set limit0 [expr $limit1-$gapLength]
    #puts stderr "Blank out: $limit0 -> [expr $limit1-1]"
    for {set slot $limit0} {$slot<$limit1} {incr slot} {
        set multiplier([expr $slot%$nSlots]) 0
    }
    set limit1 $limit0
    set limit0 [expr $limit1-$gapLength/2*$guardBunches]
    #puts stderr "Double: $limit0 -> [expr $limit1-1]"
    for {set slot $limit0} {$slot<$limit1} {incr slot} {
        set multiplier([expr $slot%$nSlots]) 2
    }
    set limit0 [expr ($gap+1)*$nSlots/$nGaps]
    set limit1 [expr $limit0+$gapLength/2*$guardBunches]
    #puts stderr "Double: $limit0 -> [expr $limit1-1]"
    for {set slot $limit0} {$slot<$limit1} {incr slot} {
        set multiplier([expr $slot%$nSlots]) 2
    }
}

set bucketList ""
set multList ""
set count 0
for {set slot 0} {$slot<$nSlots} {incr slot} {
    lappend bucketList [expr 1296/$nSlots*$slot]
    lappend multList $multiplier($slot)
    incr count
}

exec sddsmakedataset $rootname.pattern \
  -column=Bucket,type=long -data=[join $bucketList ,] \
  -column=Multiplier,type=long -data=[join $multList ,] 

set pvList S-INJ:FillQueueNumberOfBunchesC
set valueList $count
set offset 0
for {set slot 0} {$slot<$nSlots} {incr slot} {
    lappend pvList S-INJ:BucketFillQueue[format %03d $offset]C.VAL
    lappend valueList [expr $slot*1296/$nSlots]
    
    lappend pvList S-INJ:ChargeFillQueue[format %03d $offset]C.VAL
    lappend valueList $multiplier($slot)
    
    incr offset
}

# To immediately load this into the "active" fill pattern
lappend pvList S-INJ:LoadNewActiveFillPatternC
lappend valueList 1

# To scale the multipliers to a given charge 
lappend pvList S-INJ:ActiveChargeFillQueueScaleC
lappend valueList 2

exec sddsmakedataset $rootname.putMe \
  -column=ControlName,type=string -data=[join $pvList ,] \
  -column=ValueString,type=string -data=[join $valueList ,]

if [string length $order] {
    # Change the order of the fill according to the provided file
    set newFile $rootname.putMe.new

    set tmpRoot /tmp/[APSTmpString]

    # Extract just the (ControlName,ValueString) pairs from the balanced fill file, giving the order of filling
    exec sddsprocess $order $tmpRoot.desiredOrder -match=col,ControlName=S-INJ:BucketFillQueue*

    # Find any bucket assignments that are missing from the balanced order file. There should be none.
    exec sddsprocess $rootname.putMe -pipe=out -match=col,ControlName=S-INJ:BucketFillQueue* \
      | sddsselect -pipe=in $tmpRoot.desiredOrder -match=ControlName  -invert $tmpRoot.missingOrder
    if [catch {exec sdds2stream -rows=bare $tmpRoot.missingOrder} missingRows] {
        puts stderr "$missingRows"
        exit 1
    }
    if $missingRows {
        puts stderr "Error: the balanced fill file is missing some bucket assignments for the chosen pattern file."
        puts stderr [exec sddsprintout -col $tmpRoot.missingOrder]
        exit 1
    }
    file delete $tmpRoot.missingOrder

    # Cross reference the old bucket number and charge values so we can transfer the charge values
    # to the right positions in the fill queue.
    # - First, extract the charge values, labeling them by QueuePosition
    exec sddsprocess $rootname.putMe $tmpRoot.charge -match=col,ControlName=S-INJ:ChargeFillQueue* \
      -edit=column,QueuePosition,ControlName,%/S-INJ:Charge//
    # - Second, extract the bucket values labeled by QueuePosition and cross-reference with the charge values.
    #   After this xref.sdds has (QueuePosition, TargetBucketString, ChargeString)
    exec sddsprocess $rootname.putMe -pipe=out -match=col,ControlName=S-INJ:BucketFillQueue* \
      -edit=column,QueuePosition,ControlName,%/S-INJ:Bucket// \
      | sddsconvert -pipe -rename=column,ValueString=TargetBucketString \
      | sddsxref -pipe=in $tmpRoot.charge $tmpRoot.xref -match=QueuePosition -take=ValueString -rename=col,ValueString=ChargeString
    file delete $tmpRoot.charge

    # Use the bucket number to get the charge for each bucket from the cross-reference file.
    # - $tmpRoot.charge will have (ControlName, ValueString) giving the charge values at the new queue positions.
    exec sddsxref $tmpRoot.desiredOrder $tmpRoot.xref -pipe=out -match=ValueString=TargetBucketString -take=ChargeString \
      | sddsprocess -pipe -reedit=column,ControlName,%/Bucket/Charge/ \
      | sddsconvert -pipe=in $tmpRoot.charge -delete=column,ValueString -rename=column,ChargeString=ValueString
    
    # Find other PVs from the original bucket assignment file
    exec sddsprocess $rootname.putMe $tmpRoot.other -match=col,ControlName=S-INJ:BucketFillQueue*,!,ControlName=S-INJ:ChargeFillQueue*,!,&

    # Combine everything
    exec sddscombine $tmpRoot.desiredOrder $tmpRoot.charge $tmpRoot.other -merge -overwrite $newFile
    file rename -force $newFile $rootname.putMe

    # Clean up
    file delete $tmpRoot.charge $tmpRoot.other $tmpRoot.xref $tmpRoot.desiredOrder
}


