;+
;
; Project   : s3drs reconstruction software
;                   
; Name      : pop
;               
; Purpose   : general utility
;               
; Explanation: given any type of array 'stack', pops off and returns
; the lead element and if given /trim, removes it as well from the stack.
; Can also give /reverse to return (and, with /trim, remove) the last element
; Returns empty if array is empty
; Only works for stacks of 1, 2 and 3-dimensions so far.
; Item returns is of size NDIM-1, thus an array returns a single
; element, an array of images returns an image, etc
;               
; Use       : var=pop(stack,/trim,/reverse)
;    
; Inputs    : stack
;               
; Outputs   : the lead element is returned
;
; Keywords  : trim (remove element as well as returning it)
;             reverse (pop back, not front)
;               
; Common    : none
;               
; Restrictions: none
;               
; Side effects: also modifies the stack if /trim is given
;               
; Category    : utils, i/o
;               
; Prev. Hist. : None.
;
; Written     : Sandy Antunes, NRC, March-April 2009
;               
;-            
; given any type of array 'stack', pops off and returns the lead element and
; if given /trim, removes it as well from the stack.
; Can also give /reverse to return (and, with /trim, remove) the last element
; Returns empty if array is empty
;
; Only works for stacks of 1, 2 and 3-dimensions so far.
; Item returns is of size NDIM-1, thus an array returns a single
; element, an array of images returns an image, etc
;
; example:

PRO pop_UNDEFINE, varname  
   tempvar = SIZE(TEMPORARY(varname))
END

FUNCTION test_pop

     dates=['Mon','Tues','Wed','Thurs','Fri']
     help,dates
     print,pop(dates); "Mon"
     help,dates
     print,dates; "Mon Tues Wed Thurs Fri"
     print,pop(dates,/reverse); "Fri"
     help,dates
     print,dates; "Mon Tues Wed Thurs Fri"
     print,pop(dates,/reverse,/trim); "Fri"
     help,dates
     print,dates; "Mon Tues Wed Thurs"
     print,pop(dates,/trim); "Mon"
     help,dates
     print,dates; "Tues Wed Thurs"
     ; now pop everything off to see what happens
     print,pop(dates,/trim); "Tues"
     help,dates
     print,dates; "Wed Thurs"
     print,pop(dates,/trim); "Wed"
     help,dates
     print,dates; "Thurs"
     print,pop(dates,/trim); "Thurs"
     help,dates; should be *Undefined*
     print,dates; should fail
     ; should be empty now...
     print,pop(dates,/trim)
     help,dates
     print,dates; check current array status

     im1=fltarr(6,6)+1.0
     im1[0:3,*]=0.0; set up a nice half-filled image
     im2=im1+2
     im3=im2+2

     imstack=[[[im1]],[[im2]],[[im3]]]
     tv_multi,imstack,title='full set'
     tv_multi,pop(imstack),'lead image'
     tv_multi,pop(imstack,/reverse),'last image'
     ignore=pop(imstack,/trim)
     tv_multi,imstack,title='reduced set'
     ignore=pop(imstack,/trim,/reverse)
     tv_multi,imstack,title='middle element only one left'

END

FUNCTION pop,stack,trim=trim,reverse=reverse

     if (n_elements(stack) eq 0) then return,0; bad in = bad out
     reverseme=KEYWORD_SET(reverse)
     trim=KEYWORD_SET(trim)

     nn=size(stack,/n_dimensions)
     dd=size(stack,/dimensions)
     if (reverseme) then getme=dd[nn-1]-1 else getme=0

     case nn of
         1: begin
             ele=stack[getme]
             nele=n_elements(stack[*])
             if (trim) then begin
                 if (nele eq 1) then pop_undefine,stack else $
                   if (reverseme) then stack=stack[0:getme-1] else $
                   stack=stack[1:*]
             end
             ; preserve 'array of arrays' nature of stack even if solo element
             if (nele eq 1 and trim eq 0) then stack=[stack]
         end
         2: begin
             ele=stack[*,getme]
             nele=n_elements(stack[0,*])
             if (trim) then begin
                 if (nele eq 1) then pop_undefine,stack else $
                   if (reverseme) then stack=stack[*,0:getme-1] else $
                   stack=stack[*,1:*]
             end
             ; preserve 'array of arrays' nature of stack even if solo element
             if (nele eq 1 and trim eq 0) then stack=[[stack]]
         end
         3: begin
             ele=stack[*,*,getme]
             nele=n_elements(stack[0,0,*])
             if (trim) then begin
                 if (nele eq 1) then pop_undefine,stack else $
                 if (reverseme) then stack=stack[*,*,0:getme-1] else $
                   stack=stack[*,*,1:*]
             end
             ; preserve 'array of arrays' nature of stack even if solo element
             if (nele eq 1 and trim eq 0) then stack=[[[stack]]]
         end
         else: return,TEMPORARY(0); return an undefined
     end

     return,ele

END
