#!/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)]

APSStandardSetup

set sectorList ""
set varList ""
for {set i 1} {$i<40} {incr i 2} {
    set sector [format %02d $i]
    lappend sectorList S[format %02d $i]
    set BPLD(S$sector) 0
    lappend varList BPLD(S$sector)
}
set BPLD(sectorList) $sectorList
set BPLD(sectorVarList) $varList


proc GetBadList {args} {
    global BPLD
    set statusFile /home/helios/oagData/sr/BPMStatus/config.sdds
    set tmpRoot /tmp/[APSTmpString]
    if [catch {exec sddsxref $BPLD(configDir)/config.sdds $statusFile -match=DeviceName -take=Nonexist*,OkForBMBPLD* -pipe=out \
		   | tee $tmpRoot.0 \
		   | sddsprocess  -pipe=in $tmpRoot.1 -nowarn  \
		   "-filter=col,NonexistentH,1,1,NonexistentV,1,1,|" }  result] {
	return -code error "Error obtaining nonExistList: $result"
    }
    if [catch {exec sddsprocess $tmpRoot.0 $tmpRoot.2 -nowarn \
		   "-filter=col,OkForBMBPLDH,0,0,OkForBMBPLDV,0,0,|" } result] {
	return -code error "Error obtaining notOkList: $result"
    }
    
    
    if [catch {exec sddscombine $tmpRoot.1 $tmpRoot.2 $tmpRoot.3 -merge -over } result] {
	return -code error "Error combining bad list: $result"
    }
    
    APSAddToTmpFileList -ID bpld -fileList "$tmpRoot.0 $tmpRoot.1 $tmpRoot.2 $tmpRoot.3"
    global itemList sectorList
    set badList [exec sdds2stream -col=DeviceName $tmpRoot.3]
    set badSectors [exec sdds2stream -col=BPLDSector $tmpRoot.3]
    set indexList [exec sdds2stream -col=BPLDIndex $tmpRoot.3]
    
    set missingList ""
    foreach device $badList sector $badSectors index $indexList {
	set item [lindex $itemList [expr $index -1]]
	lappend missingList S[format %02d $sector]$item
    }
    return $missingList
}

proc GetSelectedSectors {args} {
    global BPLD itemList
    set sectors ""
    foreach sector $BPLD(sectorList) {
	set indexList ""
	set bpmTypeList ""
	for {set i 1} {$i<=28} {incr i} {
	    set item [lindex $itemList [expr $i-1]]
	    set name bmBPM$sector$item
	    global $name
	    
	    if [set $name] {
		lappend indexList $i
		if [regexp "P0" $name] {
		    lappend bpmTypeList P0
		} else {
		    lappend bpmTypeList other
		}
	    }
	    
	}
	if [llength $indexList] {
	    lappend sectors $sector
	}
	set BPLD($sector.indexList) $indexList
	set BPLD($sector.bpmTypeList) $bpmTypeList
    }
    return $sectors
}

proc SetLimits {args} {
    global BPLD
    set sectorList [GetSelectedSectors]
    if ![llength $sectorList] {
	SetStatus "No sectors chosen!"
	return
    }
    SetStatus "Set limits..."
    foreach sector $sectorList {
	foreach index $BPLD($sector.indexList) type $BPLD($sector.bpmTypeList) {
	    switch $type {
		P0 {
		    set limit [expr $BPLD(P0Limit)*1000.0]
		}
		default {
		    set limit [expr $BPLD(BPMLimit)*1000.0]
		}
	    }
	    if [catch {APScavput -list=S${sector} -list=-LMPS:BM_ -list=X,Y -list=$index \
			   -list=_TH-SP=$limit -pend=20} result] {
		return -code error "Error setting BM P0 BPLD limit: $result"
	    }
	}
    }
    SetStatus "done."
}

proc ClearFaults {args} {
    global BPLD
    set sectorList [GetSelectedSectors]
    if ![llength $sectorList] {
	SetStatus "No sectors chosen!"
	return
    }
    SetStatus "Clear faults..."
    if [catch {APScavput -list=S -list=[join $sectorList ,] \
		   -list=-LMPS:BPLD:ID -list=1,2 -list=:AIOR- \
		   -list=H,V -list=1,2 -list=-SP=0 -pend=60} result] {
	return -code error "Error set ID bpm offsts to zero: $result"
    }
    
    if [catch {APScavput -list=S -list=[join $sectorList ,] \
		   -list=-LMPS:BM_ -list=X,Y -range=begin=1,end=28 -list=_Offset-SP=0 -pend=60} result] {
	return -code error "Error set BM bpm offsets to zero: $result"
    }
    #clear External inputs faults
    if [catch {APScavput -list=S -list=[join $sectorList ,] -list=-LMPS:CtrlReg0-Cmd=0 -pend=30 } result] {
	return -code error "Error clear ext inputs: $result"
    }
    after 5000
    if [catch {APScavput -list=S -list=[join $sectorList ,]  -list=-LMPS:UsrReset-SP=1 -pend=30 } result] {
	return -code error "Error reset to clear faults: $result"
    }
    SetStatus "done."
}

proc LoadDefaultLimits {args} {
    global BPLD lab apsSCRSnapDir apsSCRRequestDir
    if $lab {
	set scrFile /home/oxygen/DIAG/oagData/SCR/snapshots/SRBPLD/SRBPLD-DefaultBetaLimits.gz
	set apsSCRSnapDir /home/oxygen/DIAG/oagData/SCR/snapshots
	set apsSCRRequestDir /home/oxygen/DIAG/oagData/SCR/requestFiles
    } else {
	set scrFile /home/helios/oagData/SCR/snapshots/SRBPLD/SRBPLD-DefaultBetaLimits.gz
	set apsSCRSnapDir /home/helios/oagData/SCR/snapshots
	set apsSCRRequestDir /home/helios/oagData/SCR/requestFiles
    }
	
    set opt ""
    set sectorList [GetSelectedSectors]
    
    if ![llength $sectorList] {
	SetStatus "No sectors selected."
	return
	}
    foreach sector $sectorList {
	if ![string length $opt] {
	    set opt -match=col,Beamline=$sector
	} else {
	    append opt ",Beamline=$sector,|"
	}
    }
    if [catch {eval exec sddsprocess $scrFile -pipe=out -match=col,Category=BM_BPLD_Limit $opt \
		   | sddscasr -pipe=in -restore } result] {
	return -code error "Error loading BM BPLD limits from SCR: $result"
    }
    SetStatus "Default SCR BM BPLD limits for double sector [join $sectorList] loaded."
}

proc SetStatus {text} {
    global bmBPMConfigStatus
    set bmBPMConfigStatus "$text"
    update
}

proc SetArchiveLog {args} {
    global BPLD
    set BPLD(mainDir) $BPLD(archiveDir)
    set BPLD(rootname) [clock format [clock seconds] -format %Y-%m%d:%H%M%S]
}

set BPLD(mainDir) [APSGoToDailyDirectory -subdirectory BMBPLDValidation]
set BPLD(rootname) BMValidation

set bmBPMConfigStatus ""
set lab 0
set args $argv
APSStrictParseArguments {lab}

APSApplication . -name SRBMBPLDValidation  \
  -overview "SRBMBPLDValidation provides convenience controls for BM BPLD trip limit."
APSScrolledStatus .status -parent .userFrame -width 80 \
        -textVariable bmBPMConfigStatus

if $lab {
    set BPLD(configDir) /home/oxygen/DIAG/apsu/BPLD/BPLD_Config
    set archiveDir /home/oxygen/DIAG/oagData/sr/BPLD/Validation/BM
    set BPLD(existSectors) {1 3 5}
} else {
    set BPLD(configDir) /home/helios/oagData/sr/BPLD/BPLD_Config
    set archiveDir  /home/helios/oagData/sr/BPLD/Validation/BM/TestCheckout
    set BPLD(existSectos) [exec sdds2stream -col=Sector /home/helios/oagData/sr/BPLD/doubleSectors.sdds]
}

set BPLD(archiveDir) $archiveDir
SetArchiveLog
set itemLabelList ""
set indexList ""
for {set i 1} {$i<=28} {incr i} {
    lappend indexList $i
}
set itemLabelList {n-1AP5 n-1AP6 n-1BP6 n-1BP5 n-1BP4 n-1BP3 n-1BP2 n-1BP1 n-1BP0 \
		       nAP0 nAP1 nAP2 nAP3 nAP4 nAP5 nAP6 nBP6 nBP5 nBP4 nBP3 nBP2 nBP1 nBP0 \
		       n+1AP0 n+1AP1 n+1AP2 n+1AP3 n+1AP4}

set itemList {n-1A:P5 n-1A:P6 n-1B:P6 n-1B:P5 n-1B:P4 n-1B:P3 n-1B:P2 n-1B:P1 n-1B:P0 \
		       nA:P0 nA:P1 nA:P2 nA:P3 nA:P4 nA:P5 nA:P6 nB:P6 nB:P5 nB:P4 nB:P3 nB:P2 nB:P1 nB:P0 \
		       n+1A:P0 n+1A:P1 n+1A:P2 n+1A:P3 n+1A:P4}
#set itemList $itemLabelList
set missingList [GetBadList]
set BPLD(itemList) $itemList

APSSRSectorButtons .bpm -parent .userFrame -rootname bmBPM -allButtons 1 \
    -label "BPLD BM BPM Selection"  -sectorList $sectorList -orientation horizontal \
    -itemList $itemList -itemLabelList $itemList -description "BPLD BM BPM Config" \
    -sectorControl 1 -packOption "-side top" -globalButtons 1 -missingList "$missingList"

APSSetSRSectorButtons -mode all-off -rootname bmBPM  -itemList $itemList -sectorList $sectorList


set BPLD(allowedFaultBPMs) 3
set BPLD(P0Limit) 0.5
#for other BPMs
set BPLD(BPMLimit) 1.25
APSLabeledEntry .nbpm -parent .userFrame -textVariable BPLD(allowedFaultBPMs) -width 30 \
    -label "BM number of BPMs fault allowed"

APSLabeledEntry .dir -parent .userFrame -textVariable BPLD(mainDir) -width 80 \
    -label "Log Dir:"

APSButton .archive -parent .userFrame.dir -packOption "-side right" -text "archive" -size small -command \
    "SetArchiveLog"
APSButton .daily -parent .userFrame.dir -packOption "-side right" -text "daily" -size small \
    -command "set BPLD(mainDir) [APSGoToDailyDirectory -subdirectory BMBPLDValidation];set BPLD(rootname) BMValidation"

APSFrameGrid .grid -parent .userFrame -xList {x1 x2}
set w1 .userFrame.grid.x1
set w2 .userFrame.grid.x2

APSLabeledEntry .root -parent $w1 -textVariable BPLD(rootname) -width 35 \
    -label "Log rootname:"

set BPLD(plane) x
APSRadioButtonFrame .plane -parent $w2 -label "Plane: " -buttonList {x y both} -valueList {x y both} \
		    -orientation horizontal -variable BPLD(plane)
set BPLD(validateType) offset
APSRadioButtonFrame .type -parent $w1 -label "Validate with:" -buttonList {offset synthetic_data} \
    -valueList {offset synthetic} -orientation horizontal -variable BPLD(validateType)
set BPLD(hiLimit) 1
APSRadioButtonFrame .limit -parent $w2 -label "Use high or low limit?" -buttonList {High Low} \
    -orientation horizontal -variable BPLD(hiLimit) -valueList {1 0}

APSFrame .f1 -parent .userFrame 
APSFrame .f2 -parent .userFrame
set w1 .userFrame.f1.frame
set w2 .userFrame.f2.frame
$w1 configure -bd 0
$w2 configure -bd 0
APSButton .read -parent $w1 -text "Read Config" -command ReadConfig
APSButton .start -parent $w1 -text "START" -command StartValidation
APSButton .display -parent $w1 -text "DISPLAY" -command DisplayResult
APSButton .kill -parent $w1 -text "Kill ExecWindows" -command "KillExecWindows"
APSButton .clear -parent $w1  -text "ClearFaults" -command "ClearFaults"

APSButton .load -parent $w2 -text "Load Default Limits" -command LoadDefaultLimits
APSButton .load1 -parent $w2 -text "Load SCR Offsets" -command LoadSCROffsets


APSButton .plot -parent $w2 -text "Display Result" -command PlotArchive


proc GetBPMs {args} {
    global BPLD
    set bpmList ""
    foreach sector $BPLD(sectorList) {
	foreach item $BPLD(itemList) {
	    set name bmBPM$sector$item
	    global $name
	    if [set $name] {
		lappend bpmList $BPLD($sector$item.bpm)
	    }
	}
    }
    return $bpmList
}

proc ReadConfig {args} {
    global BPLD itemList bmBPMCBWidget

    set tmpFile /tmp/[APSTmpString]
    APSAddToTmpFileList -ID bmbpld -fileList $tmpFile
    set configFile $BPLD(configDir)/config.sdds
    
    APSSetSRSectorButtons -mode all-off -rootname bmBPM  -itemList $itemList -sectorList $BPLD(sectorList)

    foreach sector $BPLD(sectorList) {
	set sector0 [scan $sector S%d]
	if [catch {exec sddsprocess $configFile $tmpFile -filter=col,BMBPM,0.5,1.5 -filter=col,BPLDSector,$sector0,$sector0 } result] {
	    #no bpms for $sector0
	    continue
	}
	set indexList [exec sdds2stream -col=BPLDIndex $tmpFile]
	set deviceList [exec sdds2stream -col=DeviceName $tmpFile]
#	puts [join $indexList]
	foreach index $indexList device $deviceList {
	    set item [lindex $itemList [expr $index -1]]
	    set name bmBPM$sector$item
	    set BPLD($sector$item.bpm) $device
	    global $name
	    #puts $name
	    #set $name 1
	    $bmBPMCBWidget($sector$item) invoke
	}
    }
}

proc LoadSCROffsets {args} {
    set all 1
    APSParseArguments {all}
    global BPLD lab
    
    set opt ""
    set sectorList [GetSelectedSectors]
    if ![llength $sectorList] {
	SetStatus "No sectors selected."
	return
    }
    set filterOpt ""
    foreach sector $BPLD(existSectors) {
	if ![string length $filterOpt] {
	    set filterOpt -filter=col,BPLDSector,$sector,$sector
	} else {
	    append filterOpt ",BPLDSector,$sector,$sector,|"
	}
    }
    set matchOpt ""
    if !$all {
	set bpmList [GetBPMs]
    }
    foreach sector $sectorList {
	if ![string length $opt] {
	    set opt -match=col,Beamline=$sector
	} else {
	    append opt ",Beamline=$sector,|"
	}
    }
    set scrFile /home/helios/oagData/SCR/snapshots/SR/SR-UserBeamPreferred.gz
    set tmpRoot /tmp/[APSTmpString]
    if [catch {eval exec sddsprocess $BPLD(configDir)/config.sdds $filterOpt  $tmpRoot.bpld  $matchOpt } result] {
	return -code error "Error processing BPLD1: $result"
    }
    foreach coord {x y} {
	if [catch {exec sddsprocess $scrFile -pipe=out \
		       -match=col,ControlName=*$coord:Offset* \
		       | sddsprocess -pipe=in $tmpRoot.$coord \
		       -reedit=col,ControlName,%/S1A/S01A/%/S2A/S02A/%/S3A/S03A/%/S4A/S04A/%/S5A/S05A/%/S6A/S06A/%/S7A/S07A/%/S8A/S08A/%/S9A/S09A/ \
		       -reedit=col,ControlName,%/S1B/S01B/%/S2B/S02B/%/S3B/S03B/%/S4B/S04B/%/S5B/S05B/%/S6B/S06B/%/S7B/S07B/%/S8B/S08B/%/S9B/S09B/ \
		       -edit=col,DeviceName,ControlName,7fD30 } result] {
	    return -code error "Error process SCR offset: $result"
	}
	if [catch {exec sddsxref $tmpRoot.bpld $tmpRoot.$coord -match=DeviceName -take=ValueString -nowarn -pipe=out \
		       | sddsprocess -pipe -scan=col,Value,ValueString,%lf \
		       | sddsprocess -pipe "-redefine=col,Value,Value 1000 *" \
		       | sddsprocess -pipe "-reprint=col,ValueString,%lf,Value" \
		       | sddsconvert -pipe -del=col,ControlName \
		       | sddsprocess -pipe=in $tmpRoot.$coord.set \
		       -print=col,ControlName,S%02d-LMPS:BM_[string toupper $coord]%d_Offset-SP,BPLDSector,BPLDIndex } result] {
	    return -code error "Error process bpld offset: $result"
	}
    }
    if [catch {exec sddscombine $tmpRoot.x.set $tmpRoot.y.set -merge -pipe=out \
		   | sddscasr -pipe=in -restore } result] {
	return -code error "Error loading BPLD offset: $result"
    }
    SetStatus "BPLD offset was loaded from SR UBOP."
}

set execList ""
proc StartValidation {args} {
    global BPLD itemList execList lab

    set doList ""
    set BPLD(rootname) [clock format [clock seconds] -format %Y-%m%d:%H%M%S]
    set logFile $BPLD(mainDir)/$BPLD(rootname).sdds
    set BPLD(logFile) $logFile
    if ![file exist $logFile] {
	set BPLD(logID) [open $BPLD(logFile) a+]
	puts $BPLD(logID) "SDDS1"
	puts $BPLD(logID) "&column name=StartTime, type=string, &end"
	puts $BPLD(logID) "&column name=EndTime, type=string, &end"
	puts $BPLD(logID) "&column name=Sector, type=long, &end"
	puts $BPLD(logID) "&column name=BPM, type=string &end"
	puts $BPLD(logID) "&column name=Plane, type=string, &end"
	puts $BPLD(logID) "&column name=Limit, type=string, &end"
	puts $BPLD(logID) "&column name=Result, type=string, &end"
	puts $BPLD(logID) "&column name=ValidationType, type=string,&end"
	puts $BPLD(logID) "&column name=FaultDesc, type=string, &end"
	puts $BPLD(logID) "&data mode=ascii, no_row_counts=1, &end"
	exec chmod 777 $BPLD(logFile)
	flush $BPLD(logID)
    }
    SetStatus "Set n faults BPMs..."
    if [catch {APScavput -list=APSU:MMPS1:BM:FaultCnt-SP=$BPLD(allowedFaultBPMs) -pend=30} result] {
	return -code error "Error setting allowed n. fault BM bpms: $result"
    }
    if $lab {
	set sectorList {1 3 5} 
    } else {
	set sectorList [exec sdds2stream -col=Sector /home/helios/oagData/sr/BPLD/doubleSectors.sdds]
    }
    foreach sector $sectorList {
	set sector S[format %02d $sector]
	set indexList ""
	for {set i 1} {$i<=28} {incr i} {
	    set item [lindex $itemList [expr $i-1]]
	    set name bmBPM$sector$item
	    global $name
	    if [set $name] {
		lappend indexList $i
	    }
	}
	if ![llength $indexList] {
	    #SetStatus "No bpms chosen for S$sector, skip."
	    continue
	}
	if {[llength $indexList]<=$BPLD(allowedFaultBPMs)} {
	    SetStatus "$sector Warning: the number of BM bpms is less than the allowed BPMs, there will be no main1 and main2 fault!"
	#    continue
	}
	set BPLD($sector.done) 0
	lappend doList $sector
	set command "/home/oxygen/SHANG/oag/apps/src/tcltkapp/oagapp/SRBPLD_BM_Validation -sector [scan $sector S%d] -plane $BPLD(plane) -bpmList \"$indexList\" -logFile $logFile -hiLimit $BPLD(hiLimit) -lab $lab -validateType $BPLD(validateType)"
	APSExecLog .s$sector -width 80 -lineLimit 1048 -name "Test S$sector" \
	    -unixCommand "$command" \
	    -callback "set BPLD($sector.done) done;SetStatus \"$sector done\"" \
	    -abortCallback "set BPLD($sector.done) aborted" \
	    -cancelCallback "set BPLD($sector.done) canceled"
	lappend execList .s$sector
    }
    if [llength $doList] {
	SetStatus "validating [join $doList] ..."
	foreach sector $doList {
	    tkwait variable BPLD($sector.done)
	}
	SetStatus "done."
    } else {
	SetStatus "No sector chosen."
    }
}


proc PlotArchive {args} {
    global BPLD selectFile
    cd $BPLD(archiveDir)
    set files [lsort -decreasing [glob -nocomplain *.sdds]]
    if ![llength $files] {
	SetStatus "No data found."
	return
    }
    set selectFile ""
    APSScrolledListWindow .display -height 10 -name "Select File" -itemList $files  -selectionVar selectFile
    tkwait variable selectFile
    destroy .display
    if ![string length $selectFile] {
	SetStatus "No file is chosen."
	continue
    }
    if [file exist $selectFile] {
	DisplayResult -logFile $BPLD(archiveDir)/$selectFile
    }
	
}
proc DisplayResult {args} {
    set logFile ""
    APSStrictParseArguments {logFile}
    global BPLD
    if ![string length $logFile] {
	set logFile $BPLD(mainDir)/$BPLD(rootname).sdds
    }
    if ![file exist $logFile] {
	SetStatus "log file $logFile does not exist!"
	return
	}
       set printFile /tmp/[APSTmpString].print
    if [catch {exec sddsprintout $logFile $printFile \
		   -col=StartTime,format=%20s -col=Sector,format=%5d  \
		   -col=Plane,format=%5s  -col=Limit,format=%5s -col=ValidationType,format=%10s -col=Result,format=%6s \
		   -col=FaultDesc,format=%30s "-title=BM validation result" } result] {
	return -code error "Error printing result1: $result"
    }
    APSFileDisplayWindow [APSUniqueName .] -fileName $printFile -deleteOnClose 1 -width 140
}

proc KillExecWindows {args} {
    global execList
    
    foreach win $execList {
	if [winfo exist $win] {
	    destroy $win
	}
    }
    set execList ""
}

ReadConfig
