#!/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 CVSRevisionAuthor "\$Revision: 1.9 $ \$Author: borland $"

APSStandardSetup

set singleAccel ""
set args $argv
APSStrictParseArguments {singleAccel}

APSApplication . -name SnapshotSequenceRecorder -version $CVSRevisionAuthor \
  -overview {This application allows saving sequences of snapshots for later restoration in order and at specified time intervals.}

APSSCRDefineVariables
set apsSCRSystemDescription(Custom) "Custom request file"
set apsSCRGroupMembers(Custom) Custom
set apsSCRAccelManagerAccount(Custom) [exec whoami]
set apsSCRGroupDescription(Custom) "Custom request file"
lappend apsSCRGroupMenuOrder Custom
lappend apsSCRSystemList Custom

set statusText ""
proc setStatusText { text } {
    global statusText
    set statusText $text
    update
}

proc systemChangeCallback {} {
    global apsSCRSystemDescription apsSCRSystem
    setStatusText "System changed to $apsSCRSystemDescription($apsSCRSystem)"
    if [string compare $apsSCRSystem Custom]==0 {
        .userFrame.customReq.entry configure -state normal \
          -foreground black -takefocus 1
    } else {
        .userFrame.customReq.entry configure -state disabled \
          -foreground grey -takefocus 0   
    }
}

proc AddDataToSeqFile {args} {
    global seqFID sequenceStep stepDescription sequenceFileOpen preStepPause postStepPause apsSCRSystem
    APSStrictParseArguments {Type Snapshot}
    if [string length $Snapshot] {
        set Snapshot [file tail $Snapshot]
    }
    puts -nonewline $seqFID "$sequenceStep $Type \"$stepDescription\" \"$Snapshot\" "
    puts $seqFID " \"$apsSCRSystem\" $preStepPause $postStepPause [exec timeconvert -breakdown=now]"
    flush $seqFID
    incr sequenceStep
}

proc addSequenceBreakpoint {} {
    global sequenceFileOpen
    if !$sequenceFileOpen {
        setStatusText "Can't add snapshot---sequence not open."
        return
    }
    setActionButtons 0
    AddDataToSeqFile -Type breakpoint -Snapshot "" 
    setStatusText "Breakpoint added."
    setActionButtons 1
}

proc addSnapshot {} {
    global sequenceFileOpen sequenceStep workingDir sequenceFile
    global customRequestFile apsSCRSystem apsSCRSystemDescription
    global apsSCRRequestDir stepDescription
    if !$sequenceFileOpen {
        setStatusText "Can't add snapshot---sequence not open."
        return
    }
    if [string length $workingDir] {
        set snapshot $workingDir/$sequenceFile-[exec date +%Y-%j-%m%d-%H%M%S]
    } else {
        set snapshot $sequenceFile-[exec date +%Y-%j-%m%d-%H%M%S]
    }
    if [string compare $apsSCRSystem Custom]==0 {
        set requestFile $customRequestFile
        if [string length $requestFile]==0 {
            setStatusText "Request file not given for custom system."
            return
        }
    } else {
        set requestFile $apsSCRRequestDir/$apsSCRSystem.req
    }
    if ![file exists $requestFile] {
        setStatusText "Request file $requestFile not found."
        return
    }
    setActionButtons 0
    setStatusText "Taking snapshot..."
    set logFile /tmp/[APSTmpString]
    catch {exec timeconvert -now} timeList 
    set time0 [format %.0lf [lindex $timeList 8]]
    set description [APSMakeSafeQualifierString $stepDescription]
    if [catch \
          {exec burtrb -f $requestFile -sdds -l $logFile \
             | sddsconvert -binary -pipe \
             | sddsxref -pipe $requestFile -take=* -nowarning \
             | sddsprocess -pipe=in $snapshot \
             "-define=parameter,Time,$time0,units=s,type=long" \
             "-print=parameter,SnapshotDescription,$apsSCRSystemDescription($apsSCRSystem): $description" \
             "-print=parameter,RequestFile,$requestFile" \
             "-print=parameter,SnapshotFilename,${snapshot}"} result] {
        setStatusText "Error taking snapshot: $result"
        setActionButtons 1
        if ![file exists $logFile] return
    } 

    if {[file exists $logFile] && ![file size $logFile]} {
        exec rm $logFile
    }
    if [file exists $logFile] {
        setStatusText "Snapshot taken, but errors found."
        set tmpWidget [APSUniqueName .] 
        APSFileDisplayWindow $tmpWidget -fileName $logFile \
          -comment "Error log from step $sequenceStep in sequence $sequenceFile" \
          -contextHelp \
          "This widget displays an error log from an attempt to create a snapshot.  Press Continue or Cancel to proceed." \
          -width 120 
        pack forget $tmpWidget.buttonRow.close
        global snapshotErrorCancel
        APSDialogBoxAddButton .continue -parent $tmpWidget -text Continue \
          -contextHelp "Continue addition of snapshot to the sequence, in spite of errors." \
          -command "set snapshotErrorCancel 0"
        APSDialogBoxAddButton .cancel -parent $tmpWidget -text Cancel \
          -contextHelp "Cancel addition of snapshot to the sequence." \
          -command "set snapshotErrorCancel 1"
        tkwait variable snapshotErrorCancel
        catch {exec rm $logFile}
        destroy $tmpWidget
        if $snapshotErrorCancel {
            setStatusText "Step aborted."
            setActionButtons 1
            return
        }
    }
    AddDataToSeqFile -Type snapshot -Snapshot $snapshot
    setActionButtons 1
    setStatusText "Snapshot added."
}

proc resetEntryFields {} {
    global stepDescription preStepPause postStepPause
    set stepDescription None
    set preStepPause 0
    set postStepPause 0
}

proc setActionButtons {state} {
    if $state {
        APSEnableButton .userFrame.addSnap.button
        APSEnableButton .userFrame.resetFields.button
    } else {
        APSDisableButton .userFrame.addSnap.button
        APSDisableButton .userFrame.resetFields.button
    }
}

proc setOpenCloseButtons {state} {
    if $state {
        APSDisableButton .userFrame.close.button
        APSEnableButton .userFrame.open.button
    } else {
        APSEnableButton .userFrame.close.button
        APSDisableButton .userFrame.open.button
    } 
}

proc closeSequence {} {
    global sequenceFileOpen seqFID sequenceStep
    if !$sequenceFileOpen {
        setStatusText "No sequence is open."
        return
    }
    close $seqFID
    set sequenceFileOpen 0
    set sequenceStep ?
    allowSequenceEntry 1
    setStatusText "Sequence closed."
    setOpenCloseButtons 1
}

proc allowSequenceEntry {state} {
    if $state {
        .userFrame.workDir.entry configure -state normal -foreground black -takefocus 1
        .userFrame.seqFile.entry configure -state normal -foreground black -takefocus 1
        .userFrame.seqDescrip.entry configure -state normal -foreground black -takefocus 1
    } else {
        .userFrame.workDir.entry configure -state disabled -foreground grey -takefocus 0
        .userFrame.seqFile.entry configure -state disabled -foreground grey -takefocus 0
        .userFrame.seqDescrip.entry configure -state disabled -foreground grey -takefocus 0
    }
}

proc openSequence {} {
    global sequenceFileOpen workingDir sequenceFile seqFID sequenceStep sequenceDescription
    if $sequenceFileOpen {
        setStatusText "Close the existing sequence before starting a new one."
        return
    }

    set workingDir [string trim $workingDir]
    set sequenceFile [string trim $sequenceFile]
    if [string length $sequenceFile]==0 {
        setStatusText "No filename given"
        return
    }
    if [string length $workingDir]==0 {
        set file $sequenceFile
    } else {
        set file $workingDir/$sequenceFile
    }

    setStatusText "Opening sequence..."
    set choice Overwrite
    if [file exists $file] {
        catch {APSMultipleChoice [APSUniqueName .] \
                 -question "File $sequenceFile exists in $workingDir. What do you want to do?" \
                 -labelList {Append Overwrite Cancel} \
                 -returnList  {Append Overwrite Cancel}} choice
        }
    switch $choice {
        Overwrite {
            catch {exec cp $file $file.bck}
            set seqFID [open $file w]
            set append 0
        }
        Append {
            catch {exec cp $file $file.bck}
            set seqFID [open $file a]
            set append 1
        }
        Cancel {
            setStatusText "New sequence aborted."
            return
        }
        default {
            setStatusText "Unknown return value: $choice"
            return
        }
    }
    set sequenceFileOpen 1
    allowSequenceEntry 0
    setOpenCloseButtons 0
    if !$append {
        puts $seqFID "SDDS1"
        puts $seqFID "&parameter name=SequenceDescription type=string fixed_value=\"$sequenceDescription\" &end"
        puts $seqFID "&column name=Step type=long &end"
        puts $seqFID "&column name=Type type=string &end"
        puts $seqFID "&column name=Description type=string &end"
        puts $seqFID "&column name=Snapshot type=string &end"
        puts $seqFID "&column name=System type=string &end"
        puts $seqFID "&column name=PreStepPause type=double &end"
        puts $seqFID "&column name=PostStepPause type=double &end"
        puts $seqFID "&column name=Time type=double units=s &end"
        puts $seqFID "&data mode=ascii no_row_counts=1 &end"
        flush $seqFID
        set sequenceStep 1
    } else {
        set sequenceStep ?
        set expectedColumnList [list Step Type Description Snapshot System PreStepPause PostStepPause Time]
        set columnList [APSGetSDDSNames -fileName $file -class column]
        set sequenceDescription [APSGetSDDSParameter -fileName $file -parameter SequenceDescription]
        if [llength $expectedColumnList]!=[llength $columnList] {
            setStatusText "Mismatch of existing file with expected columns:"
            setStatusText "Existing: $columnList"
            setStatusText "Expected: $expectedColumnList"
            close $seqFID
            set sequenceFileOpen 0
            allowSequenceEntry 1
            setOpenCloseButtons 1
            return
        }
        foreach elem $columnList {
            if [lsearch -exact $columnList $elem]!=[lsearch -exact $expectedColumnList $elem] {
                setStatusText "Mismatch of existing file with expected columns:"
                setStatusText "Existing: $columnList"
                setStatusText "Expected: $expectedColumnList"
                close $seqFID
                set sequenceFileOpen 0
                allowSequenceEntry 1
                setOpenCloseButtons 1
                return
            }
        }
        set stepList [APSGetSDDSColumn -fileName $file -column Step -page 1]
        set sequenceStep [expr [lindex $stepList end]+1]
    }
    setStatusText "Sequence being recorded in $file"
}

APSScrolledStatus .status  -parent .userFrame  -textVariable statusText -width 100 \
        -height 4

if ![string length $singleAccel] {
    APSSCRSystemChoiceWidget .beamline -parent .userFrame \
      -command systemChangeCallback
}

set parent .userFrame

set customRequestFile ""
set workingDir ""
set sequenceFile ""
set sequenceDescription None
set sequenceFileOpen 0
set stepDescription None
set preStepPause 0
set postStepPause 0
set sequenceStep ?
APSLabeledEntry .customReq -parent $parent -label "Request file: " -textVariable customRequestFile \
  -width 70 -contextHelp "Enter the name of a custom request file with which to make a snapshot.  The name may include a directory portion."
$parent.customReq.entry configure -state disabled -foreground grey 
APSLabeledEntry .workDir -parent $parent -label "Working directory: " -textVariable workingDir \
  -width 70 -contextHelp "Enter the name of the directory for keeping snapshots and the sequence file."
APSLabeledEntry .seqFile -parent $parent -label "Sequence file: " -textVariable sequenceFile \
  -width 70 -contextHelp "Enter the name of a file in which the sequence should be recorded.  This name should not include a directory portion."
APSLabeledEntry .seqDescrip -parent $parent -label "Sequence description: " -textVariable sequenceDescription \
  -width 70 -contextHelp "Enter a description for the sequence you are creating."
APSLabeledEntry .stepDescrip -parent $parent -label "Step description: " -textVariable stepDescription \
  -width 70 -contextHelp "Enter a description of the present sequence step."
APSLabeledEntry .preStepPause -parent $parent -label "Pre-step pause (seconds): " \
  -textVariable preStepPause -width 70 -contextHelp "Enter the number of seconds to pause prior to the present step."
APSLabeledEntry .postStepPause -parent $parent -label "Post-step pause (seconds): " \
  -textVariable postStepPause -width 70 -contextHelp "Enter the number of seconds to pause after the present step."
APSLabeledOutput .seqStep -parent $parent -label "Current sequence step: " \
  -textVariable sequenceStep -width 70 -contextHelp "Displays the present step in the sequence."

APSButton .addSnap -parent $parent -text "Add snapshot" \
  -command addSnapshot -contextHelp \
  "Adds a snapshot in the sequence."
APSButton .addBreak -parent $parent -text "Add breakpoint" \
  -command addSequenceBreakpoint -contextHelp \
  "Adds a breakpoint in the sequence. A breakpoint is a null operation that causes a pause during automatic sequencing with SnapshotSequenceRestore."

APSButton .resetFields -parent $parent -text "Reset fields" \
  -command resetEntryFields -contextHelp \
  "Resets the entry fields for a new step to the default values."
APSButton .open -parent $parent -text "Open sequence" \
  -command openSequence -contextHelp \
  "Opens a new snapshot sequence or continues an existing one."
APSButton .close -parent $parent -text "Close sequence" \
  -command closeSequence -contextHelp \
  "Closes out any existing sequence you are working on."
setOpenCloseButtons 1


