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

# $Log: not supported by cvs2svn $
# Revision 1.13  2010/06/03 19:23:06  soliday
# It was moving the files correctly but the listbox was incorrect after moving
# many files because the index number used was no longer correct after previous
# files were moved. To fix this I changed it to remove the files from the bottom
# of the listbox first.
#
# Revision 1.12  2010/06/03 16:53:30  soliday
# Added a features to select all the SCR files that have never been restored.
# This should make it easier to identify which files can be moved to the Attic.
#
# Revision 1.11  2009/08/17 20:56:40  soliday
# Updated list of allowed users because emery is now lemery.
#
# Revision 1.10  2008/04/21 19:33:03  soliday
# Added sjones and schroedr to the allowed users.
#
# Revision 1.9  2008/02/05 22:37:26  soliday
# Removed calls to setfacl because it is no longer needed.
#
# Revision 1.8  2007/02/27 18:04:15  soliday
# Fixed small bug and also added oag to the list of allowed users.
#
# Revision 1.7  2005/10/06 22:55:30  borland
# Added "Yes to all" option for moving snapshots in bulk.
#
# Revision 1.6  2004/08/10 18:01:12  shang
# added tranferring waveform files
#
# Revision 1.5  2004/04/20 19:42:04  shang
# fixed a bug in RemoveSingleSnapshotInAttic which deleted the attic directory when
# the snapshots were deleted
#
# Revision 1.4  2004/03/17 18:05:47  shang
# fixed a typo (replace wasterBasket by wasteBasket)
#
# Revision 1.3  2004/03/17 18:02:32  shang
# added setfacl to allowedUsers for creating attic/wasteBasket directory
#
# Revision 1.2  2004/03/17 17:06:44  shang
# removed -nocase option in lsearch command which is invalid
#
# Revision 1.1  2004/03/16 20:02:33  shang
# first version, for transfering snapshots between normal and attic SCR directory
#

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 confirmMove 0

APSStandardSetup
#define global variables
APSSCRDefineVariables -topDirectory "" -inhibitLogging 0

set CVSRevisionAuthor "\$Revision: 1.14 $ \$Author: soliday $"

proc setStatusText { text } {
    global statusText
    set statusText "$text ([exec date +%H:%M:%S])"
    update
}

proc MakeSnapshotSearchFrame {widget args} {
    
    global apsSCRSystem apsSCRConfigStartYear apsSCRConfigStartMonth apsSCRConfigStartDay
    global apsSCRConfigEndYear apsSCRConfigEndMonth apsSCRConfigEndDay searchString 

    set parent ""
    set noPack 0
    set label ""
    APSStrictParseArguments {parent noPack label}

    APSFrame $widget -parent $parent -label $label -relief flat \
      -packOption "-side top -expand 1 -fill both"
    set w $parent$widget.frame

    APSFrame .search -parent $w -label "Snapshot search"
    APSSCRDateTimeEntryWidget .date -parent $w.search.frame

    APSLabeledEntry .descript -parent $w.search.frame -label "Description search string: " \
      -textVariable searchString  -packOption "-side top" -width 40 \
      -contextHelp "Enter a string to use in searching for files by matching the description given by the operator who saved the snapshot."

    
    APSFrame .ops -parent $w -label ""
    APSButton .search -parent $w.ops.frame -text "SEARCH NORMAL" -size small \
      -command "runAPSListSCRMatch -parent $w -callback MoveSingleSnapshot -listWidgetVariable searchSnapListWidget" \
      -contextHelp \
      "Performs a search in the snapshots directory based on the beamline selection, the date search string, and the description search string." 
    APSButton .selectUnRestored -parent $w.ops.frame -text "SELECT FILES NEVER RESTORED" -size small \
      -command "SelectUnRestored -listWidgetVariable searchSnapListWidget" \
      -contextHelp \
      "Select all the files that have never been restored before. These are good candidates for moving to the attic." 
    APSButton .searchattic -parent $w.ops.frame -text "SEARCH ATTIC" -size small \
      -command "runAPSListSCRMatch -parent $w -attic 1 -callback MoveSingleSnapshot -listWidgetVariable searchSnapListWidget" \
      -contextHelp \
      "Performs a search in the attic directory based on the beamline selection, the date search string, and the description search string." 
    APSButton .clear -parent $w.ops.frame -size small \
      -text "CLEAR" \
      -command {set searchString ""} \
      -contextHelp "clear search string."
    
    global moveToAtticButton moveToNormalButton removeAtticButton
    APSButton .move -parent $w.ops.frame -size small \
      -text "MOVE TO ATTIC" -command "MoveSnapshots" \
      -contextHelp "move the selected snapshots to attic."
    APSButton .moveback -parent $w.ops.frame -size small \
      -text "MOVE TO NORMAL" -command "MoveSnapshots" \
      -contextHelp "move the selected snapshots in attic back to normal snapshot directory."
    APSButton .remove -parent $w.ops.frame -size small \
      -text "REMOVE ATTIC SNAPSHOT" -command "RemoveAtticSnapshots" \
      -contextHelp "remove the selected snapshots in attic directory."
    set moveToAtticButton $w.ops.frame.move.button
    set moveToNormalButton $w.ops.frame.moveback.button
    set removeAtticButton $w.ops.frame.remove.button
}


proc runAPSListSCRMatch {args} {
    global apsSCRSystem apsSCRConfigStartYear apsSCRConfigStartMonth apsSCRConfigStartDay
    global apsSCRConfigEndYear apsSCRConfigEndMonth apsSCRConfigEndDay searchString 
    global apsSCRAtticDir atticWidget moveToAtticButton moveToNormalButton removeAtticButton

    set parent ""
    set routine 0
    set callback ""
    set listWidgetVariable ""
    set categoryWidgetVariable ""
    set attic 0
    APSStrictParseArguments {parent routine callback listWidgetVariable categoryWidgetVariable attic}

    if ![string length $apsSCRSystem] {
        setStatusText "No System was chosen for searching snapshots!"
        return
    }
    if $attic {
        if ![file exist $apsSCRAtticDir] {
            setStatusText "The attic directory of $apsSCRSystem system does not exist yet!"
            return
        }
    }
    if {[string length $categoryWidgetVariable]} {
        global $categoryWidgetVariable
        if [winfo exists [subst \$$categoryWidgetVariable]] {
            destroy [subst \$$categoryWidgetVariable]
            set $categoryWidgetVariable ""
        }
    }
    set labelFont "-adobe-courier-bold-r-normal-*-*-120-75-75-*-*-*-*"
    if $attic {
        set label ATTIC
    } else {
        set label NORMAL
    }
    APSListSCRMatch -machine $apsSCRSystem -height 20 -listOrder decreasing -selectMode extended \
      -startYear $apsSCRConfigStartYear -startMonth $apsSCRConfigStartMonth \
      -startDay $apsSCRConfigStartDay \
      -endYear $apsSCRConfigEndYear -endMonth $apsSCRConfigEndMonth \
      -endDay $apsSCRConfigEndDay \
      -descriptionFragment $searchString -parent $parent \
      -statusCallback setStatusText -callback $callback -routine $routine \
      -attic $attic -label $label -labelFont $labelFont
    if [string length $listWidgetVariable] {
        global $listWidgetVariable
        set $listWidgetVariable $parent.apsSCRlist
    }
    set atticWidget $attic
    if !{$attic} {
        #current widget is normal, can only move snapshots from normal to attic
        APSDisableButton $moveToNormalButton
        APSEnableButton $moveToAtticButton
        APSDisableButton $removeAtticButton
    } else {
        #current widget is attic, can only move snapshots from attic to normal or delete attic snapshots
        APSEnableButton $moveToNormalButton
        APSDisableButton $moveToAtticButton
        APSEnableButton $removeAtticButton
    }
}

proc SelectUnRestored {args} {
    APSStrictParseArguments listWidgetVariable
    global $listWidgetVariable descriptionArray apsSCRSystem
    if {[info exists $listWidgetVariable] && ![winfo exists [set $listWidgetVariable]]} {
        setStatusText "Search files first."
        bell
        return
    }

    [set ${listWidgetVariable}].frame.list.lbox selection clear 0 end

    setStatusText "Searching all SCR restores for last 3 years."

    set startYear [expr [clock format [clock seconds] -format %Y] - 3]
    set startMonth [clock format [clock seconds] -format %m]
    set startDay [clock format [clock seconds] -format %d]
    set stopYear [clock format [clock seconds] -format %Y]
    set stopMonth [clock format [clock seconds] -format %m]
    set stopDay [clock format [clock seconds] -format %d]

    set logDir /home/helios/oagData/logDaemonData/SCRAudit
    
    set fileList [APSFindFilesBetweenDates -tailsOnly 0 -extensionList {"*"}\
         -directory $logDir \
         -startDateList [APSFormatDate -year $startYear -month $startMonth \
                           -day $startDay -dateFormat list] \
         -endDateList [APSFormatDate -year $stopYear -month $stopMonth \
                         -day $stopDay -dateFormat list] ]
    
    if {[catch {eval exec sddscombine $fileList -pipe=out -merge -retain=column,Action,File | sddsprocess -nowarn -pipe "-match=column,Action=restore-start,File=$apsSCRSystem\\\[12\\\]*,&" | sddssort -pipe -col=File -unique | sdds2stream -pipe=in -col=File} scrfiles]} {
        puts "Error: $scrfiles"
        exit
    }
    set index 0
    foreach scr $descriptionArray(SnapshotFilename) {
        if {[lsearch -exact $scrfiles ${scr}.gz] == -1} {
            [set ${listWidgetVariable}].frame.list.lbox selection set $index
        }
        incr index
    }
    setStatusText "Done"
}

proc MoveSingleSnapshot {index} {
    global descriptionArray apsSCRSnapDir errorInfo apsSCRSystem searchSnapListWidget
    global atticWidget apsSCRAtticDir allowedUsers errorInfo
    global confirmMove
    
    if [catch {CheckUserPermission} result] {
        setStatusText "$result"
        return
    }
    set snapshot [lindex $descriptionArray(SnapshotFilename) $index]
    set description [lindex $descriptionArray(SnapshotDescription) $index]
    
    if !{$atticWidget} {
        set snapDir $apsSCRSnapDir/$apsSCRSystem
        set moveToDir $apsSCRAtticDir/$apsSCRSystem
        set desc "from normal snapshot directory to attic"
    } else {
        set snapDir $apsSCRAtticDir/$apsSCRSystem
        set moveToDir $apsSCRSnapDir/$apsSCRSystem
        set desc "from attic directory to normal snapshot directory"
    }
    if ![file exist $snapDir/$snapshot] {
        set snapshot ${snapshot}.gz
    }
    set waveformFiles [glob -nocomplain $snapDir/${snapshot}.*]
    if {!$atticWidget} {
        if [catch {APSSCRGetPreferredDataLists -system $apsSCRSystem} dataLists] {
            return -code error $dataLists
        }
        set suffixList [lindex $dataLists 1]
        foreach suffix $suffixList {
            set refFile $snapDir/$apsSCRSystem-$suffix.gz
            if [file exists $refFile] {
                set refName [file tail [file readlink $refFile]]
                if [string compare [file rootname $refName] [file rootname $snapshot]]==0 {
                    APSAlertBox [APSUniqueName .] -errorMessage "You can't remove a preferred file ('$suffix')"
                    setStatusText "Move $snapshot cancelled."
                    return
                }
            }
        }
    }
    if $confirmMove {
        set choice [APSMultipleChoice .choice \
                      -question "You are asking to move snapshot $snapshot $desc, '$description'.  Do you really want to do this?" \
                      -labelList [list No Yes "Yes for all"] \
                      -returnList [list 0 1 2]]
        if $choice==2 {
            set confirmMove 0
        }
        if $choice==0 {
            setStatusText "Move cancelled."
            return
        }
    }
    if {!$atticWidget} {
        #move to attic directory
        if ![file exist $moveToDir] {
            set oldDir [pwd]
            cd $apsSCRAtticDir
            if [catch {exec mkdir -p $apsSCRSystem} result] {
                cd $oldDir
                return -code error "Error in creating directory: $result"
            }
#            if [catch {eval exec /home/helios/OAG/bin/setFACL-oagPlus $allowedUsers $apsSCRSystem} result] {
#                cd $oldDir
#                return -code error "Error in setting facl: $result"
#            }
            cd $oldDir
        }
    }
    setStatusText "Moving $snapshot ..."
    set filename0 [APSRemoveGzipExtension $snapshot]
    if {[catch {exec mv $snapDir/$snapshot $moveToDir}]} {
        setStatusText "Problem moving snapshot to $moveToDir."
        return
    }
    foreach prefix {categ beam c u} subdirectory {categories beamlines collapsed .} expected {1 1 1 0} {
        if ![file exists $snapDir/${subdirectory}/${prefix}$filename0] {
            if ![file exists $snapDir/${prefix}$filename0] {
                if $expected {
                    setStatusText "not found: $snapDir/${prefix}$filename0"
                }
            } elseif {[catch {exec mv $snapDir/${prefix}$filename0 $moveToDir} result]} {
                setStatusText "can't move: $snapDir/${prefix}$filename0"
            }
        } elseif {[catch {exec mv $snapDir/${subdirectory}/${prefix}$filename0 $moveToDir/$subdirectory } result]} {
            setStatusText "can't move: $snapDir/${subdirectory}/${prefix}$filename0"     
        }
    }
    foreach file $waveformFiles {
	if [regexp {.gz} $file a b] {
	    continue
	}
	if [catch {exec mv $file $moveToDir} result] {
	    APSAlertBox [APSUniqueName .] -errorMessage "$result"
	    setStatusText "Problem moving $file to $moveToDir."
	    return
	}
    }
    #remove it from the listbox
    ${searchSnapListWidget}.frame.list.lbox delete $index
    setStatusText "Moved $snapshot to $desc"
    if [catch {APSSCRLogAction -action move -file $snapshot} result] {
        setStatusText "$result"
    }
}

proc RemoveSingleSnapshotInAttic {index} {
    global descriptionArray apsSCRSnapDir errorInfo apsSCRSystem searchSnapListWidget
    global atticWidget apsSCRAtticDir allowedUsers
    
    if [catch {CheckUserPermission} result] {
        setStatusText "$result"
        return
    }
    set snapshot [lindex $descriptionArray(SnapshotFilename) $index]
    set description [lindex $descriptionArray(SnapshotDescription) $index]
    
    if !$atticWidget {
        setStatusText "You can remove a snapshot in the snapshot directory!"
        return
    }
    set atticDir $apsSCRAtticDir/$apsSCRSystem
    if ![file exist $atticDir/$snapshot] {
        set snapshot ${snapshot}.gz
    }
    set waveformFiles [glob -nocomplain $atticDir/${snapshot}.*]
    if ![APSYesNoPopUp "You are asking to remove snapshot $snapshot in attic directory, '$description'.  Do you really want to do this?"] {
        setStatusText "Move cancelled."
        return
    }
    setStatusText "Removing $snapshot in attic directory..."
    if ![file exist $atticDir/wasteBasket] {
        set oldDir [pwd]
        cd $atticDir
        if [catch {exec mkdir -p wasteBasket} result] {
            cd $oldDir
            return -code error "Error in making directory $atticDr/wasteBasket: $result!"
        }
#        if [catch {eval exec /home/helios/OAG/bin/setFACL-oagPlus $allowedUsers wasteBasket} result] {
#            cd $oldDir
#            return -code error "Error in setting facl: $result"
#        }
        cd $oldDir
    }
    set filename0 [APSRemoveGzipExtension $snapshot]
    if {[catch {file copy -force $atticDir/$snapshot $atticDir/wasteBasket}] || \
          ([file exists $atticDir/categ$filename0] && \
             [catch {file copy -force $atticDir/categ$filename0 $atticDir/wasteBasket}]) || \
          ([file exists $atticDir/categories/categ$filename0] && \
             [catch {file copy -force $atticDir/categories/categ$filename0 $atticDir/wasteBasket}]) || \
          ([file exists $atticDir/beam$filename0] && \
             [catch {file copy -force $atticDir/beam$filename0 $atticDir/wasteBasket}]) || \
          ([file exists $atticDir/beamlines/beam$filename0] && \
             [catch {file copy -force $atticDir/beamlines/beam$filename0 $atticDir/wasteBasket}]) || \
          ([file exists $atticDir/c$filename0] && \
             [catch {file copy -force $atticDir/c$filename0 $atticDir/wasteBasket}]) || \
          ([file exists $atticDir/collapsed/c$filename0] && \
             [catch {file copy -force $atticDir/collapsed/c$filename0 $atticDir/wasteBasket}]) || \
          ([file exists $atticDir/u$filename0] && \
             [catch {file copy -force $atticDir/u$filename0 $atticDir/wasteBasket}]) } {
        setStatusText "Problem copying snapshot to wastebasket."
        APSAlertBox [APSUniqueName .] -errorMessage "$errorInfo"
        return 
    }
    if {[catch {file delete -force $atticDir/$snapshot \
                  $atticDir/categ$filename0 \
                  $atticDir/categories/categ$filename0 \
                  $atticDir/beam$filename0 \
                  $atticDir/beamlines/beam$filename0 \
                  $atticDir/c$filename0 \
                  $atticDir/collapsed/c$filename0 \
                  $atticDir/u$filename0}]} {
        APSAlertBox [APSUniqueName .] -errorMessage "$errorInfo"
        setStatusText "Problem moving snapshot to attic."
        return
    }
    foreach file $waveformFiles {
	if [regexp {.gz} $file a b] {
	    continue
	}
	if [catch {file copy -force $file $atticDir/wasteBasket} result] {
	    setStatusText "Problem copying waveform snapshot to wastebasket."
	    APSAlertBox [APSUniqueName .] -errorMessage "$result"
	    return 
	}
	if [catch {file delete -force $file } result] {
	    setStatusText "Problem removing waveform snapshot."
	    APSAlertBox [APSUniqueName .] -errorMessage "$result"
	    return 
	}
    }
    #remove it from the listbox
    ${searchSnapListWidget}.frame.list.lbox delete $index
    setStatusText "Removed $snapshot in attic"
    if [catch {APSSCRLogAction -action remove -file $snapshot} result] {
        setStatusText "$result"
    }
}

proc MoveSnapshots {args} {
    global descriptionArray searchSnapListWidget atticWidget

    if ![winfo exist $searchSnapListWidget] {
        setStatusText "No snapshots for removing!"
        return
    }
    if [catch {CheckUserPermission} result] {
        setStatusText "$result"
        return
    }
    
    set chosenList [lsort -integer -decreasing [${searchSnapListWidget}.frame.list.lbox curselection]]
    if ![llength $chosenList] {
        setStatusText "No files chosen!"
        return
    }
    global confirmMove 
    set confirmMove 1
    foreach index $chosenList {
        if [catch {MoveSingleSnapshot $index} result] {
            setStatusText "$result"
            return
        }
    }
    setStatusText "Done"
}

proc RemoveAtticSnapshots {args} {
    global descriptionArray searchSnapListWidget atticWidget
    
    if ![winfo exist $searchSnapListWidget] {
        setStatusText "No snapshots for removing!"
        return
    }
     if [catch {CheckUserPermission} result] {
        setStatusText "$result"
        return
    }
    if !$atticWidget {
        setStatusText "The listed files are in snapshot direcrtory, can not remove it!"
        return
    }
    set chosenList [${searchSnapListWidget}.frame.list.lbox curselection]
    if ![llength $chosenList] {
        setStatusText "No files chosen!"
        return
    }
    foreach index $chosenList {
        if [catch {RemoveSingleSnapshotInAttic $index} result] {
            setStatusText "$result"
            return
        }
    }
}

proc CheckUserPermission {args} {
    global allowedUsers env
    set user [string tolower $env(USER)]
    set userList [split $allowedUsers ,]
    if [lsearch -exact $userList $user]<0 {
        return -code error "You ($user) are not allowed to perform attic moving/removing actions!"
    }
}

#application starts from here
set allowedUsers "borland,lemery,sereno,shang,soliday,lewellen,sajaev,pasky,cyao,oag,sjones,schroedr"
set apsSCRSystem ""
set statusText "Choose a system and search for SCR snapshots."
set searchString *
set searchSnapListWidget ""
set atticWidget 0

APSApplication . -name TransferSCRSnapsots -version $CVSRevisionAuthor \
  -overview {This utility allows moving obselete SCR snapshots to attic.}

APSScrolledStatus .status  -parent .userFrame  -textVariable statusText -width 100 \
  -height 4 -withButtons 1
APSFrame .system -parent .userFrame -label "System Choice" 
APSFrameGrid .gd -parent .userFrame.system.frame -bd 6 \
  -xList {x1 x2} 
set w1 .userFrame.system.frame.gd.x1
set w2 .userFrame.system.frame.gd.x2

APSRadioButtonFrame .sr -parent $w1 -label "SR Systems:" \
  -variable apsSCRSystem \
  -orientation horizontal -packOption "-side top" \
  -buttonList $apsSCRGroupMembers(SR) -valueList $apsSCRGroupMembers(SR) \
  -limitPerRow 3
APSRadioButtonFrame .special -parent $w2 -label "Special Systems:        " \
  -variable apsSCRSystem \
  -orientation horizontal -packOption "-side top" \
  -buttonList $apsSCRGroupMembers(Special) -valueList $apsSCRGroupMembers(Special)
APSRadioButtonFrame .booster -parent $w2 -label "Booster Systems:        " \
  -variable  apsSCRSystem \
  -orientation horizontal -packOption "-side top" \
  -buttonList $apsSCRGroupMembers(Booster) -valueList $apsSCRGroupMembers(Booster)
APSRadioButtonFrame .lpl -parent $w2 -label "Linac/PAR/LEUTL Systems:" \
  -variable apsSCRSystem \
  -orientation horizontal -packOption "-side top" \
  -buttonList $apsSCRGroupMembers(LPL) -valueList $apsSCRGroupMembers(LPL)
#APSRadioButtonFrame .obsolete -parent $w2 -label "Obsolete Systems:       " \
#  -variable apsSCRSystem \
 # -orientation horizontal -packOption "-side top" \
  #-buttonList $apsSCRGroupMembers(Obsolete) -valueList $apsSCRGroupMembers(Obsolete)



MakeSnapshotSearchFrame .search -parent .userFrame
