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

# $Log: not supported by cvs2svn $
#

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)]

APSApplication . -name "Shutter Cycle History"


proc MakeDateTimeFrame {frame} {
    global StartTextDay StartDay StartTextMonth StartYear 
    global StartHour StartMinute StartSecond StartTime
    global EndTextDay EndDay EndTextMonth EndYear 
    global EndHour EndMinute EndSecond EndTime

    set s [clock seconds]

    frame $frame
    pack $frame

    frame $frame.from
    pack $frame.from
    set f $frame.from

    label $f.label -text "From:"
    spinbox $f.textday -values "Mon Tue Wed Thu Fri Sat Sun" \
      -width 3 -wrap true -textvariable StartTextDay \
      -command {TimeAdjusted Start %W %s %d} -bg white
    spinbox $f.day -from 1 -to 31 -width 2 -wrap true \
      -textvariable StartDay \
      -validate key -vcmd {string is integer %P} \
      -command {TimeAdjusted Start %W %s %d} -bg white
    spinbox $f.month \
      -values "Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec" \
      -width 3 -wrap true -textvariable StartTextMonth \
      -command {TimeAdjusted Start %W %s %d} -bg white
    spinbox $f.year -from 1900 -to 2100 -width 4 -wrap true \
      -textvariable StartYear \
      -validate key -vcmd {string is integer %P} \
      -command {TimeAdjusted Start %W %s %d} -bg white
    label $f.space -text " "
    spinbox $f.hour -from 0 -to 23 -width 2 -wrap true \
      -format %02.0f -textvariable StartHour \
      -validate key -vcmd {string is integer %P} \
      -command {TimeAdjusted Start %W %s %d} -bg white -bg white
    label $f.colon1 -text ":" -padx 0 -bd 0
    spinbox $f.minute -from 0 -to 59 -width 2 -wrap true \
      -format %02.0f -textvariable StartMinute \
      -validate key -vcmd {string is integer %P} \
      -command {TimeAdjusted Start %W %s %d} -bg white -bg white
    label $f.colon2 -text ":" -padx 0 -bd 0
    spinbox $f.second -from 0 -to 59 -width 2 -wrap true \
      -format %02.0f -textvariable StartSecond \
      -validate key -vcmd {string is integer %P} \
      -command {TimeAdjusted Start %W %s %d} -bg white -bg white

    bind $f.textday <Return> "TimeAdjustedManually"
    bind $f.day <Return> "TimeAdjustedManually"
    bind $f.month <Return> "TimeAdjustedManually"
    bind $f.year <Return> "TimeAdjustedManually"
    bind $f.hour <Return> "TimeAdjustedManually"
    bind $f.minute <Return> "TimeAdjustedManually"
    bind $f.second <Return> "TimeAdjustedManually"

    set StartTextDay [clock format $s -format %a]
    set StartDay [clock format $s -format %d]
    set StartTextMonth [clock format $s -format %b]
    set StartYear [clock format $s -format %Y]
    set StartHour 00
    set StartMinute 00
    set StartSecond 00

    set StartTime [clock scan "$StartTextDay $StartTextMonth $StartDay ${StartHour}:${StartMinute}:${StartSecond} $StartYear"]

    button $f.reset -text "Reset" -pady 0 -command "set StartTextDay $StartTextDay ; set StartDay $StartDay ; set StartTextMonth $StartTextMonth ; set StartYear $StartYear ; set StartHour $StartHour ; set StartMinute $StartMinute ; set StartSecond $StartSecond ; set StartTime $StartTime"

    pack $f.label $f.textday $f.day $f.month \
      $f.year $f.space $f.hour $f.colon1 \
      $f.minute $f.colon2 $f.second $f.reset -side left

    button $f.15min -text "last 15min" -pady 0 -command "TimePreset -minutes 15"
    pack $f.15min -side left
    button $f.30min -text "last 30min" -pady 0 -command "TimePreset -minutes 30"
    pack $f.30min -side left


    frame $frame.to
    pack $frame.to
    set f $frame.to

    label $f.label -text "  To:"
    spinbox $f.textday -values "Mon Tue Wed Thu Fri Sat Sun" \
      -width 3 -wrap true -textvariable EndTextDay \
      -command {TimeAdjusted End %W %s %d} -bg white
    spinbox $f.day -from 1 -to 31 -width 2 -wrap true \
      -textvariable EndDay \
      -validate key -vcmd {string is integer %P} \
      -command {TimeAdjusted End %W %s %d} -bg white
    spinbox $f.month \
      -values "Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec" \
      -width 3 -wrap true -textvariable EndTextMonth \
      -command {TimeAdjusted End %W %s %d} -bg white
    spinbox $f.year -from 1900 -to 2100 -width 4 -wrap true \
      -textvariable EndYear \
      -validate key -vcmd {string is integer %P} \
      -command {TimeAdjusted End %W %s %d} -bg white
    label $f.space -text " "
    spinbox $f.hour -from 0 -to 23 -width 2 -wrap true \
      -format %02.0f -textvariable EndHour \
      -validate key -vcmd {string is integer %P} \
      -command {TimeAdjusted End %W %s %d} -bg white -bg white
    label $f.colon1 -text ":" -padx 0 -bd 0
    spinbox $f.minute -from 0 -to 59 -width 2 -wrap true \
      -format %02.0f -textvariable EndMinute \
      -validate key -vcmd {string is integer %P} \
      -command {TimeAdjusted End %W %s %d} -bg white -bg white
    label $f.colon2 -text ":" -padx 0 -bd 0
    spinbox $f.second -from 0 -to 59 -width 2 -wrap true \
      -format %02.0f -textvariable EndSecond \
      -validate key -vcmd {string is integer %P} \
      -command {TimeAdjusted End %W %s %d} -bg white -bg white

    bind $f.textday <Return> "TimeAdjustedManually"
    bind $f.day <Return> "TimeAdjustedManually"
    bind $f.month <Return> "TimeAdjustedManually"
    bind $f.year <Return> "TimeAdjustedManually"
    bind $f.hour <Return> "TimeAdjustedManually"
    bind $f.minute <Return> "TimeAdjustedManually"
    bind $f.second <Return> "TimeAdjustedManually"

    set EndTextDay [clock format $s -format %a]
    set EndDay [clock format $s -format %d]
    set EndTextMonth [clock format $s -format %b]
    set EndYear [clock format $s -format %Y]
    set EndHour 23
    set EndMinute 59
    set EndSecond 59

    set EndTime [clock scan "$EndTextDay $EndTextMonth $EndDay ${EndHour}:${EndMinute}:${EndSecond} $EndYear"]

    button $f.reset -text "Reset" -pady 0 -command "set EndTextDay $EndTextDay ; set EndDay $EndDay ; set EndTextMonth $EndTextMonth ; set EndYear $EndYear ; set EndHour $EndHour ; set EndMinute $EndMinute ; set EndSecond $EndSecond ; set EndTime $EndTime"

    pack $f.label $f.textday $f.day $f.month \
      $f.year $f.space $f.hour $f.colon1 \
      $f.minute $f.colon2 $f.second $f.reset -side left

    button $f.45min -text "last 45min" -pady 0 -command "TimePreset -minutes 45"
    pack $f.45min -side left
    button $f.60min -text "last 60min" -pady 0 -command "TimePreset -minutes 60"
    pack $f.60min -side left

}

proc TimePreset {args} {
    APSStrictParseArguments {minutes}
    foreach var "Start End" {
        global ${var}TextDay ${var}Day ${var}TextMonth ${var}Year 
        global ${var}Hour ${var}Minute ${var}Second ${var}Time
    }
    set s [clock seconds]
    
    set EndTextDay [clock format $s -format %a]
    set EndDay [clock format $s -format %d]
    set EndTextMonth [clock format $s -format %b]
    set EndYear [clock format $s -format %Y]
    set EndHour 23
    set EndMinute 59
    set EndSecond 59
    set EndTime [clock scan "$EndTextDay $EndTextMonth $EndDay ${EndHour}:${EndMinute}:${EndSecond} $EndYear"]

    set s [expr $s - ($minutes * 60)]
    set StartTextDay [clock format $s -format %a]
    set StartDay [clock format $s -format %d]
    set StartTextMonth [clock format $s -format %b]
    set StartYear [clock format $s -format %Y]
    set StartHour [clock format $s -format %H]
    set StartMinute [clock format $s -format %M]
    set StartSecond [clock format $s -format %S]
    set StartTime [clock scan "$StartTextDay $StartTextMonth $StartDay ${StartHour}:${StartMinute}:${StartSecond} $StartYear"]


}

proc TimeAdjustedManually {args} {
    foreach var "Start End" {
        global ${var}TextDay ${var}Day ${var}TextMonth ${var}Year 
        global ${var}Hour ${var}Minute ${var}Second ${var}Time
        
        set ${var}Time [clock scan "[set ${var}TextMonth] [set ${var}Day] [set ${var}Hour]:[set ${var}Minute]:[set ${var}Second] [set ${var}Year]"]
        set ${var}Minute [clock format [set ${var}Time] -format %M]
        set ${var}Hour [clock format [set ${var}Time] -format %H]
        set ${var}TextDay [clock format [set ${var}Time] -format %a]
        set ${var}Day [clock format [set ${var}Time] -format %d]
        set ${var}TextMonth [clock format [set ${var}Time] -format %b]
        set ${var}Year [clock format [set ${var}Time] -format %Y]
    }
}

proc TimeAdjusted {var widget value direction} {
    global ${var}TextDay ${var}Day ${var}TextMonth ${var}Year 
    global ${var}Hour ${var}Minute ${var}Second ${var}Time

    if {[lindex [split $widget .] end] == "second"} {
        if {$direction == "up"} {
            set direction "+"
        } else {
            set direction "-"
        }
        set ${var}Time [expr "[set ${var}Time] $direction (1)"]
        set ${var}Second [clock format [set ${var}Time] -format %S]
        set ${var}Minute [clock format [set ${var}Time] -format %M]
        set ${var}Hour [clock format [set ${var}Time] -format %H]
        set ${var}TextDay [clock format [set ${var}Time] -format %a]
        set ${var}Day [clock format [set ${var}Time] -format %d]
        set ${var}TextMonth [clock format [set ${var}Time] -format %b]
        set ${var}Year [clock format [set ${var}Time] -format %Y]
    } elseif {[lindex [split $widget .] end] == "minute"} {
        if {$direction == "up"} {
            set direction "+"
        } else {
            set direction "-"
        }
        set ${var}Time [expr "[set ${var}Time] $direction (60)"]
        set ${var}Minute [clock format [set ${var}Time] -format %M]
        set ${var}Hour [clock format [set ${var}Time] -format %H]
        set ${var}TextDay [clock format [set ${var}Time] -format %a]
        set ${var}Day [clock format [set ${var}Time] -format %d]
        set ${var}TextMonth [clock format [set ${var}Time] -format %b]
        set ${var}Year [clock format [set ${var}Time] -format %Y]
    } elseif {[lindex [split $widget .] end] == "hour"} {
        if {$direction == "up"} {
            set direction "+"
        } else {
            set direction "-"
        }
        set ${var}Time [expr "[set ${var}Time] $direction (60 * 60)"]
        set ${var}Hour [clock format [set ${var}Time] -format %H]
        set ${var}TextDay [clock format [set ${var}Time] -format %a]
        set ${var}Day [clock format [set ${var}Time] -format %d]
        set ${var}TextMonth [clock format [set ${var}Time] -format %b]
        set ${var}Year [clock format [set ${var}Time] -format %Y]
    } elseif {[lindex [split $widget .] end] == "textday"} {
        if {$direction == "up"} {
            set direction "+"
        } else {
            set direction "-"
        }
        set ${var}Time [expr "[set ${var}Time] $direction (24 * 60 * 60)"]
        set initTextDay [set ${var}TextDay]
        set ${var}TextDay [clock format [set ${var}Time] -format %a]
        if {$initTextDay != [set ${var}TextDay]} {
            #This is needed for the transition to daylight savings time.
            set ${var}Time [expr "[set ${var}Time] $direction (1 * 60 * 60)"]
            set ${var}TextDay [clock format [set ${var}Time] -format %a]
        }
        set ${var}Day [clock format [set ${var}Time] -format %d]
        set ${var}TextMonth [clock format [set ${var}Time] -format %b]
        set ${var}Year [clock format [set ${var}Time] -format %Y]
    } elseif {[lindex [split $widget .] end] == "day"} {
        if {$direction == "up"} {
            set direction "+"
        } else {
            set direction "-"
        }
        set ${var}Time [expr "[set ${var}Time] $direction (24 * 60 * 60)"]
        set initTextDay [set ${var}TextDay]
        set ${var}TextDay [clock format [set ${var}Time] -format %a]
        if {$initTextDay == [set ${var}TextDay]} {
            #This is needed for the transition to daylight savings time.
            set ${var}Time [expr "[set ${var}Time] $direction (1 * 60 * 60)"]
            set ${var}TextDay [clock format [set ${var}Time] -format %a]
        }
        set ${var}Day [clock format [set ${var}Time] -format %d]
        set ${var}TextMonth [clock format [set ${var}Time] -format %b]
        set ${var}Year [clock format [set ${var}Time] -format %Y]
    } elseif {[lindex [split $widget .] end] == "month"} {
        set month [clock format [set ${var}Time] -format %b]
        set year [clock format [set ${var}Time] -format %Y]
        set s1 [clock scan "$month 01 00:00:00 $year"]
        if {$direction == "up"} {
            if {$month == "Dec"} {
                incr year
            }
        } else {
            if {$month == "Jan"} {
                incr year -1
            }
        }
        set s2 [clock scan "[set ${var}TextMonth] 01 00:00:00 $year"]
        set s [expr {$s2 - $s1 + (60 * 60)}]
        set ${var}Time [expr "[set ${var}Time] + $s"]
        while {[set ${var}TextMonth] != [clock format [set ${var}Time] -format %b]} {
            if {$month == [clock format [set ${var}Time] -format %b]} {
                if {$direction == "up"} {
                    set ${var}Time [expr "[set ${var}Time] + (12 * 60 * 60)"]
                } else {
                    set ${var}Time [expr "[set ${var}Time] - (12 * 60 * 60)"]
                }
            } else {
                if {$direction == "up"} {
                    set ${var}Time [expr "[set ${var}Time] - (12 * 60 * 60)"]
                } else {
                    set ${var}Time [expr "[set ${var}Time] + (12 * 60 * 60)"]
                }
            }
        }
        set ${var}TextDay [clock format [set ${var}Time] -format %a]
        set ${var}Day [clock format [set ${var}Time] -format %d]
        set ${var}TextMonth [clock format [set ${var}Time] -format %b]
        set ${var}Year [clock format [set ${var}Time] -format %Y]
    } elseif {[lindex [split $widget .] end] == "year"} {
        if {([set ${var}Day] == "29") && ([set ${var}TextMonth] == "Feb")} {
            set ${var}Day 28
        }
        set ${var}Time [clock scan "[set ${var}TextMonth] [set ${var}Day] [set ${var}Hour]:[set ${var}Minute]:[set ${var}Second] [set ${var}Year]"]
        set ${var}TextDay [clock format [set ${var}Time] -format %a]
    }
    set ${var}Time [clock scan "[set ${var}TextMonth] [set ${var}Day] [set ${var}Hour]:[set ${var}Minute]:[set ${var}Second] [set ${var}Year]"]

}

proc CalcTime {} {
    foreach var "Start End" {
        global ${var}TextDay ${var}Day ${var}TextMonth ${var}Year 
        global ${var}Hour ${var}Minute ${var}Second ${var}Time
        global dateEntryStyle ${var}Month
        if {$dateEntryStyle == "old"} {
            if [catch {APSConvertTimeToHours [set ${var}Hour]} hour] {
                APSSetVarAndUpdate status "Invalid ${var}ing hour: [set ${var}Hour]"
                return
            }
            set ${var}Time \
              [expr int([exec timeconvert \
                           -breakDown=year=[set ${var}Year],day=[set ${var}Day],month=[set ${var}Month],hour=$hour])]
        } else {
            set ${var}Time [clock scan "[set ${var}TextMonth] [set ${var}Day] [set ${var}Hour]:[set ${var}Minute]:[set ${var}Second] [set ${var}Year]"]
        }
    }
}

proc LoadShutterPVs {args} {
    global timeSeriesSDDS
    set index [lsearch -exact $timeSeriesSDDS(Parameter.GroupName) "Frontend Beamline"]
    set cnList [lindex $timeSeriesSDDS(Column.ControlName) $index]
    foreach cn $cnList {
        if {[string range $cn end-3 end] == ".VAL"} {
            append ControlNameList "[string range $cn 0 end-4] "
        } else {
            append ControlNameList "$cn "
        }
    }
    append ReadbackNameList "[lindex $timeSeriesSDDS(Column.ReadbackName) $index] "
    
    foreach rbn $ReadbackNameList cn $ControlNameList {
        if {[string match -nocase "*shutter*" $rbn]} {
            if {([string match -nocase "*open*" $rbn]) || ([string match -nocase "*closed*" $rbn])} {
                if {!($rbn == "NumberOfShuttersOpen")} {
                    append nameList "{$rbn $cn} "
                }
            }
        }
    }
    set nameList [lsort -dictionary -unique -index 0 $nameList]
    foreach name $nameList {
        set rbn [lindex $name 0]
        set cn [lindex $name 1]
        lappend nl "$rbn / $cn"
    }
    APSScrolledList .pVList -parent .userFrame -name "Shutter List" -itemList $nl -packOption "-fill both"
}

proc CalcCycles {args} {
    global StartTime EndTime
    if {$StartTime >= $EndTime} {
        bell
        APSSetVarAndUpdate status "The date/time range is invalid"
        return
    }
    APSSetVarAndUpdate status "Working..."

    set selection [.userFrame.pVList.listbox curselection]
    foreach sel $selection {
        set rbn [lindex [.userFrame.pVList.listbox get $sel] 0]
        set files [APSFindPVDataFiles -ReadbackName $rbn -StartTime $StartTime -EndTime $EndTime -SampleIntervals 64]
        if {[llength $files] == 0} {
            APSSetVarAndUpdate status "No files for $rbn in this date range"
            continue
        }
        if {[catch {eval exec sddscombine $files -pipe=out -merge | sddsprocess -pipe -filter=column,Time,${StartTime},${EndTime} | sddsbreak -pipe -changeof=$rbn | sdds2stream -pipe=in -npages=bare} results]} {
            bell
            APSSetVarAndUpdate status "$results"
            return
        }
        APSSetVarAndUpdate status "$rbn --> [expr $results * .5] cycles"
    }
    APSSetVarAndUpdate status "Done"
}

set status Ready
APSScrolledStatus .status \
  -parent .userFrame \
  -textVariable status \
  -packOption "-fill both -expand true" \
  -height 20

sdds load /home/helios/oagData/dataLoggerConfig/timeSeries.sdds timeSeriesSDDS
LoadShutterPVs
MakeDateTimeFrame .userFrame.date
APSButton .calc -parent .userFrame -command CalcCycles -text "Calculate Cycles"

