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

set apsttk 1

proc CreateGUI {args} {
    APSApplication . -name "Check IOC Status"
    
    frame .userFrame.f1
    frame .userFrame.f2
    pack .userFrame.f1 -side left -fill y -expand false
    pack .userFrame.f2 -side left -fill both -expand true

    global status
    set status "Ready..."
    APSScrolledStatus .scroll -parent .userFrame.f2 -packOption "-side top -fill both -expand true" -textVariable status -width 100 -height 50
    .userFrame.f2.scroll.frame.fg.top.text tag configure red -foreground red

    global iocNameListFull iocNameList
    set f /home/helios/oagData/deviceConfig/IOCs.sdds
    if {[catch {exec sdds2stream $f -col=Name} iocNameList]} {
        set status "Unable to read IOC names from $f"
        return
    }
    set iocNameListFull [lrange $iocNameList 0 end]
    set iocNameList $iocNameListFull
    APSScrolledList .list -parent .userFrame.f1 -selectMode extended -listvar iocNameList
    
    global filter
    set filter "*"
    ttk::entry .userFrame.f1.entry -textvariable filter
    pack .userFrame.f1.entry -side top -fill x
    bindtags .userFrame.f1.entry "TEntry . all .userFrame.f1.entry"
    bind .userFrame.f1.entry <Return> "FilterIOCs"

    APSButton .b1 -parent .userFrame.f1 -text "Check IOC Status" -command CheckIOCStatus -width ""
    APSButton .b2 -parent .userFrame.f1 -text "Check PV Status" -command CheckPVStatus -width ""
    APSButton .b3 -parent .userFrame.f1 -text "List All PVs" -command "CheckPVStatus -all 1" -width ""
}

proc FilterIOCs {args} {
    global iocNameListFull iocNameList filter
    set iocNameList ""
    foreach name $iocNameListFull {
        catch {
            if {[lsearch -glob $name $filter] != -1} {
                lappend iocNameList $name
            }            
        }        
    }
}

proc CheckIOCStatus {args} {
    global status iocNameList
    set status "-----------------\nChecking the IOC status..."
    update
    set iocIndex [.userFrame.f1.list.listbox curselection]
    set nameList ""
    foreach index $iocIndex {
        lappend nameList [lindex $iocNameList $index]
    }
    set numOff 0
    set numOn 0
    if {[llength $nameList]} {
        if {[catch {APScavget -pend=5 -list=[join $nameList ,] -list=:status} results]} {
            .userFrame.f2.scroll.frame.fg.top.text insert end "${results}\n" red
            return
        }
        foreach name $nameList stat $results {
            if {$stat == 1} {
                incr numOn
                set status "$name is On"
            } else {
                incr numOff
                .userFrame.f2.scroll.frame.fg.top.text insert end "$name is Off\n" red
            }
            update
        }
        if {$numOff == 0} {
            set status "All the selected IOCs are on"
            update
        }
    } else {
        .userFrame.f2.scroll.frame.fg.top.text insert end "No IOCs selected\n" red
        update
    }
}

proc CheckPVStatus {args} {
    set all 0
    APSStrictParseArguments {all}
    global status iocNameList
    set status "-----------------\nChecking the PV status..."
    update
    set iocIndex [.userFrame.f1.list.listbox curselection]
    set nameList ""
    foreach index $iocIndex {
        lappend nameList [lindex $iocNameList $index]
    }
    set numOff 0
    set numOn 0
    if {[llength $nameList]} {
        foreach name $nameList {
            set status "-------- $name ---------"
            update
            if {$name == "iocmtime"} {
                .userFrame.f2.scroll.frame.fg.top.text insert end "Skipping because this IOC is unstable.\n" red
                continue
            }
            if {[file exists /home/helios/iocinfo/pvdata/$name]} {
                if {[catch {exec plaindata2sdds /home/helios/iocinfo/pvdata/$name -pipe=out \
                              -noRowCount -col=Name,string | sdds2stream -pipe=in -col=Name} PVnames]} {
                    .userFrame.f2.scroll.frame.fg.top.text insert end "Error reading /home/helios/iocinfo/pvdata/${name}\n" red
                    update
                    continue
                }
                if {[catch {APScavget -pend=2 -list=${name}:status} results]} {
                    .userFrame.f2.scroll.frame.fg.top.text insert end "${results}\n" red
                    return
                }
                if {$results != 1} {
                    .userFrame.f2.scroll.frame.fg.top.text insert end "$name is off\n" red
                    update
                    continue
                }

                if {[llength $PVnames] > 20000} {
                    set status "Please be patient. There are [llength $PVnames] PVs on this IOC."
                    update
                }

                set i 0
                set errorSeen 0
                set nanErrorSeen 0
                while {$i < [llength $PVnames]} {
                    set nameList [join [lrange $PVnames $i [expr $i + 5000]] ,]
                    if {$all} {
                        set status [join [lrange $PVnames $i [expr $i + 5000]] \n]
                        update
                    }
                    incr i 5000
                    if {[catch {APScavget -pend=10 -list=$nameList -printError} results]} {
                        set errorSeen 1
                        foreach line [split $results \n] {
                            if {[lindex $line 0] == "Error:"} {
                                .userFrame.f2.scroll.frame.fg.top.text insert end "${line}\n" red
                            } elseif {[string trim $line] == "floating point value is Not a Number"} {
                                set nanErrorSeen 1
                            } elseif {[string trim $line] == "unmatched open quote in list"} {
                                #Probably a value with a pathname ending in a directory slash before the closing quote
                                #.userFrame.f2.scroll.frame.fg.top.text insert end "directory slash issue\n" red
                            }
                        }
                        update
                    }
                }
                if {$nanErrorSeen} {
                    set i 0
                    while {$i < [llength $PVnames]} {
                        set nameList [join [lrange $PVnames $i [expr $i + 1000]] ,]
                        incr i 1000
                        if {[catch {exec cavget -pend=5 -list=$nameList -labeled} results]} {
                        }
                        foreach line [split $results \n] {
                            if {[catch {lrange $line 1 end} value]} {
                                continue
                            }
                            if {([string compare $value "nan"] == 0) || ([string compare $value "-nan"] == 0)} {
                                .userFrame.f2.scroll.frame.fg.top.text insert end "[lindex $line 0] == $value\n" red 
                            }
                            if {([string compare $value "inf"] == 0) || ([string compare $value "-inf"] == 0)} {
                                .userFrame.f2.scroll.frame.fg.top.text insert end "[lindex $line 0] == $value\n" red 
                            }
                        }
                    }
                    update
                }
                if {$errorSeen == 0} {
                    set status "All PVs connected"
                    update
                }
            } else {
                .userFrame.f2.scroll.frame.fg.top.text insert end "/home/helios/iocinfo/pvdata/$name does not exist\n" red
                update
            }
        }
        set status "-----------------\nDONE"
    } else {
        .userFrame.f2.scroll.frame.fg.top.text insert end "No IOCs selected\n" red
        update
    }
}

CreateGUI
pv toggleErrorMode
