;+
; NAME:
;	FF_SUMMARY
;
;
; PURPOSE:
;	Get a 1-line summary of a FITS file (SMEI)
;
;
; CATEGORY:
;	UTILS
;
;
; CALLING SEQUENCE:
;	desc = ff_summary(file)
;
;
; INPUTS:
;	file	string	The file to summarize (if the path key is set,
;			then it can be a wildcard).
;
;
; KEYWORD_PARAMETERS:
;	/template	Return a title bar for a summary
;	path	string	A directory to search for the files. (If this
;			is given then file is optional and defaults to
;			the current directory.
;	filelist str	If this is a named variable, then it will
;			return the list of filenames (only really
;			useful when path is given).
;	startlist dbl	If this is a named variable then it will
;			contain the JD's of the image start times.
;	count	long	If this is a named variable, on return it will
;			contain the number of files found.
;	/no_file	If set then actually open each file rather
;			than using the img_hdr.txt file to get the info.
;	/norecurse	If set, then do not look in subdirectories.
;	projections str	A named variable to hold the list of
;			projections of the images.
;	/no_progress	If set, then do not create a progress bar to
;			show progress through files and directories
;			(mainly for running over a slow network).
;	/update		If set, then force a reprocessing just as if
;			the directory has been changed
;	callid	long	The widget ID of a calling widget.
;	/noverify	If set, then trust the image header lists.		
;
;
; MODIFICATION HISTORY:
;	Original: 13/12/02; SJT
;	Modify for degenerate Aitoff files: 7/3/03; SJT
;	Modify to allow use of a tree to store files: 1/7/03; SJT
;	Add fold_case keyword to file_search calls: 23/7/03; SJT
;	Fix crash in single plane images: 2/10/03; SJT
;	Deal with possibility of files called .fts: 20/11/03; SJT
;	Add projection information, and projections keyword, and save
;	list: 16/2/04; SJT
;	Do recursion explicitly to allow symlinked subdirs to work:
;	12/8/04; SJT
;	Major efficiency changes: 11/11/04; SJT
;	Add list of mal-indexed directories: 31/5/05; SJT
;	Support compressed fits files: 24/5/05; SJT
;	Add no_progress keyword: 25/8/05; SJT
;	Several major speedups (removed an N^2 operation) & handle
;	Pipe 2 processing flags: Oct-Nov 07; SJT
;	Don't convert headers to structures (fails randomly &
;	intermittently): 4/8/09; SJT
;	Major rewrite, mainly to only scan modified directories on
;	call with /UPDATE: 20/4/10; SJT
;	Add callid key: 20/7/10; SJT
;	Add noverify keyword: 11/12/12; SJT
;	Handle case where no images found: 8/9/14; SJT
;-

function ff_summary, file, template = template, path = path, $
                     filelist = filelist, startlist = startlist, count $
                     = count, no_file = no_file, projections = $
                     projections, norecurse = norecurse, $
                     no_progress = no_progress, update = update, $
                     callid = callid, noverify = noverify

  common ff_summary_lastpath, lastpath, laststr, lastdesc, lastepoch

  if keyword_set(template) then return, $
     ' Year Day Start Length Cols Rows Flags'

  if keyword_set(noverify) and keyword_set(no_file) then message, $
     /continue, "NOVERIFY & NO_FILE should not both be set, ignoring " + $
     "NOVERIFY"

  now = systime(1)              ; Unix epoch
  sep = '/'

  if n_elements(lastepoch) eq 0 then lastepoch = 0.d0
  if n_elements(lastpath) eq 0 or keyword_set(no_file) then $
     lastpath = ''
  if ~keyword_set(path) then path = '.'

  chdir = lastpath eq '' || ~file_same(lastpath, path)
  iupdate = chdir || keyword_set(update) || now - lastepoch gt 5.4d3

; If we are up-to-date, then just return the stored lists.
  
  if (~iupdate) then begin
     desc = lastdesc
     filelist = transpose([[laststr.dir], [laststr.fname]])
     startlist = laststr.stime
     projections = laststr.project
     count = n_elements(desc)
     if (n_params() eq 1) then begin
        locs = where(strmatch(laststr.fname, file,  /fold), nm)
        if nm eq 0 then begin
           desc = ''
           filelist = strarr(2)
           startlist = 0.d0
           projections = ''
           count = 0l
        endif else begin
           desc = desc[locs]
           filelist = filelist[*, locs]
           startlist = startlist[locs]
           projections = projections[locs]
           count = nm
        endelse
     endif
     return, desc
  endif

; If we are scanning a new base directory, then clear the old file
; lists.

  if chdir then begin
     if n_elements(laststr) ne 0 then begin
        junk = temporary(laststr)
        junk = 0
     endif
     lastepoch = 0.d0
  endif

; If appropriate then, find all subdirectories of the path.

  if keyword_set(norecurse) then begin
     dlist = path 
     ndir = 0
  endif else begin
     dlist = [path, file_search(path, '*', /test_directory, $
                                count = ndir, /nosort)]
     if ndir eq 0 then dlist = path
     ;; spawn, "find "+path, dlist
     ;; locs =  where(file_test(dlist, /dir), ndir)
     ;; ndir = n_elements(dlist)-1
  endelse

; Phase 1 scan for image header files and read them in cases where
; update is needed, copy the existing list if not.

  if widget_info(/active) eq 0 or keyword_set(no_progress) then $
     isprog = 0b $
  else begin
     isprog = 1b
     ismodal = widget_info(callid, /valid)
  endelse

  if isprog then $
     pm = cw_progress(title = 'Scanning headers files', $
                      value = 0., $
                      /column, $
                      xsize = 200, $
                      ysize = 20, $
                      max = ndir+1, $
                      group = callid, $
                      modal = ismodal) $
  else pm = 0l

  allstr = ptrarr(ndir+1)
  inln =  strarr(2)
  for j =  0, ndir do begin
     hdrfile = dlist[j]+sep+'img_hdr.txt'
     if file_exist(hdrfile) then begin
        hinfo = file_info(hdrfile)
        if (hinfo.mtime ge lastepoch) then begin ; File has changed
           nlines = file_lines(hdrfile)
           tmpstr = replicate({ff_data}, nlines)
           openr, ilu, /get, hdrfile
           for k = 0, nlines-1 do begin
              readf, ilu, inln, format = "(A35, A)"
              tmpstr[k] = ff_tostr(inln[1])
              tmpstr[k].fname = strtrim(inln[0])
              tmpstr[k].dir = strtrim(dlist[j])+sep
           endfor
           free_lun, ilu
           allstr[j] = ptr_new(tmpstr)
        endif else begin        ; Unchanged, just copy from the
                                ; existing struct
           locs = where(laststr.dir eq dlist[j] or $
                        laststr.dir eq dlist[j]+sep,  nm)
           if nm ne 0 then begin
              tmpstr = laststr[locs]
              allstr[j] = ptr_new(tmpstr)
           endif
        endelse
     endif
     if widget_info(/valid, pm) then $
        widget_control, pm, set_value = j+1
  endfor

  if widget_info(/valid, pm) then $
     widget_control, pm, /destroy
  
; Phase 2: Check the files in each directory and scan any that are not
; in the header list.

  if (~keyword_set(noverify)) then begin
     
     
     if isprog then $
        pm = cw_progress(title = 'Scanning for missing files', $
                         value = 0., $
                         /column, $
                         xsize = 200, $
                         ysize = 20, $
                         max = ndir+1, $
                         group = callid, $
                         modal = ismodal) $
     else pm = 0l

     file_pattern = '*.f*t*'

     for j = 0l, ndir do begin $
        cfile = file_search(dlist[j]+sep+file_pattern, /fold_case, $
                            count = countd)
        cfbase = get_comp_name(file_basename(cfile), /return_base)
        hflag = 0b
        for k = 0, countd-1 do begin
           locs = where((*allstr[j]).fname eq cfbase[k], nm)
           if nm ne 0 then continue ; Already present
           *allstr[j] = [*allstr[j], ff_extract(cfile[k])]
           hflag = 1b
        endfor

        if hflag then begin
           print, strtrim(dlist[j]), ' has uncatalogued files'
           print, "you should re-run mk_imghdrtxt on this directory:"
        endif
        if widget_info(/valid, pm) then $
           widget_control, pm, set_value = j+1
     endfor
     if widget_info(/valid, pm) then $
        widget_control, pm, /destroy
  endif

  nstr = cat_ptr(allstr, laststr, /free)
  if nstr eq 0 then begin
     count = 0
     return, ''
  endif

  idx = sort(laststr.stime)
  laststr = laststr[idx]
  lastdesc = ff_todesc(laststr)

  if chdir then lastpath = path
  lastepoch = now

  desc = lastdesc
  filelist = transpose([[laststr.dir], [laststr.fname]])
  startlist = laststr.stime
  projections = laststr.project
  count = n_elements(desc)

  if (n_params() eq 1) then begin
     locs = where(strmatch(laststr.fname, file, /fold), nm)
     if nm eq 0 then begin
        desc = ''
        filelist = strarr(2)
        startlist = 0.d0
        projections = ''
        count = 0l
     endif else begin
        desc = desc[locs]
        filelist = filelist[*, locs]
        startlist = startlist[locs]
        projections = projections[locs]
        count = nm
     endelse
  endif
  return, desc

end
