function sot_time2files, t0, t1, observerables=observables, urls=urls, $
   level=level, topdir=topdir, sswdb_cat=sswdb_cat, count=count, $
   _extra=_extra, path_only=path_only, debug=debug, hour_dir=hour_dir, $
   allobs=allobs, xrt=xrt, noct=noct, max_filesperdir=max_filesperdir, $
   level1=level1, level2=level2
;
;+
;   Name: fpp_time2files
;
;   Purpose: return fpp filenames or ursl for input time range & observable
;
;   Input Parameters:
;      t0, t1 - time range
;
;   Keyword Paramters:
;      observable - list of one or more observables (or use keyword inherit)
;      _extra - optional 'observable' as a switch 
;      urls - if set, return urls instead of local nfs name 
;     topdir - optional parent of FPP trees
;     sswdb_cat - if set, use $SSWDB/solarb/fpp/genxcat/ catalog
;     count (output) - number of elements returned
;     hour_dir (output) - name of hourly subdirectory 
;     noct (switch) - if set and /ALL, then do ALL Except CT frames
;     max_filesperdir - only return 1st MAX_FILESPERDIR (per hour)
;     level1 - if set, use level1
;
;   Output:
;      function returns file or url list
;
;   History:
;      15-mar-2006 - S.L.Freeland
;      27-mar-2006 - S.L.Freeland - add /ALLOBS since looks like a moving targ..
;      27-sep-2006 - S.L.Freeland - fpp->sot, little more environmentally friendly
;       1-mar-2007 - S.L.Freeland - add /NOCT keyword and function
;       5-jun-2007 - S.L.Freeland - add MAX_FILESPERDIRECTORY keyword
;       8-oct-2007 - S.L.Freeland - add /LEVEL1 keyword & function
;
;   Restrictions/Comments - this is about 80% fancier (uglier) than it
;   needs to be to keep up with many prelaunch moving targets.
;   I may revisit this after some post launch stability has returned.
;
;-
debug=keyword_set(debug)
count=0

xrt= keyword_set(xrt)
allobs=keyword_set(allobs)
case 1 of
   allobs: obs='*' 
   data_chk(observables,/string): obs=strupcase(observables)
   data_chk(_extra,/struct): obs=tag_names(_extra) ; keyword inherit
   xrt: obs=''
   else: begin
      box_message,'Please supply at least one OBSERVABLE...'
      return,''
   endcase
endcase
 
fpptop=get_logenv('FPP_DATA_DIR')
xrt_data=get_logenv('XRT_DATA')
sot_data=get_logenv('SOT_DATA')
if fpptop eq '' or xrt then fpptop=([sot_data,xrt_data])(xrt)  ; environmental

case 1 of
   keyword_set(topdir): sbtop=topdir ; user supplied via keyword
   fpptop ne '': sbtop=fpptop        ; environmental
   keyword_set(sswdb_cat): begin 
      box_message,'SSWDB_CAT not yet supported...'
      return,'' ; EARLY EXIT....
   endcase
   xrt:sbtop='/net/kokuten/archive/hinode/xrt/level0'
   else:sbtop='/net/kokuten/archive/hinode/sot/level0' 
endcase

l1=keyword_set(level1)
l2=keyword_set(level2)
if l1 or l2 then begin 
   repstr='level'+(['1','2'])(l2)
   sbtop=str_replace(sbtop,'QuickLook',repstr)
   sbtop=str_replace(sbtop,'level0',repstr)
endif

; dbtop=sbtop; +(['','/xrt'])(xrt)
dbtop=sbtop
if not file_exist(sbtop) then begin
   box_message,'Cannot find top of data...>> ' + sbtop
   return,''
endif 

hrgrid=str2cols(timegrid(t0,t1,/hour,out='ecs'),/trim) ; hourly grid
strtab2vect,hrgrid,dd,tt

gtimes=anytim(dd + ' ' + tt)
ssok=where(gtimes ge anytim(t0) and gtimes le anytim(t1))  
if anytim(t1) eq anytim(dd(last_nelem(ssok))) then $ ; 00:00 full day assumed
   ssok=ssok(0:n_elements(ssok)-2)

dd=dd(ssok) & tt=tt(ssok)


findh=1 ; force hourly search until further notice
if allobs then begin 
   udd=dd(uniq(dd))
   nd=n_elements(udd)
   nsub=concat_dir(dbtop,udd)  
   sse=where(file_exist(nsub),ecnt)
   if ecnt eq 0 then begin 
      box_message,'No subdirectories??'
      return,''
   endif
   nsub=nsub(sse) 
   nd=n_elements(nsub)
   for d=0,nd-1 do begin 
      d1=dir_since(nsub(d),-200,/sub,pat='*fits')
      if n_elements(retval) eq 0 then retval=d1 else $
         retval=[temporary(retval),d1]
   endfor
   if keyword_set(noct) then begin ; SLF, 1-mar-2007 - eliminate CT frames
       box_message,'Rejecting CT frames....'
       ssnotct=where(strpos(retval,'/CR/H') eq -1,okcnt)
       if okcnt eq 0 then begin 
          box_message,'All images rejected...!'
          return,''
       endif else retval=retval(ssnotct)
   endif
   return,retval
endif

if findh then hh='' else $ 
hh='H'+strmid(tt,0,2) ; idealized     

obssub=dbtop+'/'+dd+'/'+obs(0)+'/'+hh
for i=1,n_elements(obs)-1 do begin 
   obssub=[temporary(obssub),dbtop+'/'+dd+'/'+obs(i)+'/'+hh]
endfor

if findh then begin 
   sso=obssub(uniq(obssub))
   sso=str_replace(sso,'XRT/','')
   ndd=n_elements(sso)
   retval=''
   for i=0,ndd-1 do begin 
      ff=findfile(sso(i))
      if ff(0) ne '' then retval=[temporary(retval),sso(i)+ff]
   endfor
endif
if n_elements(retval) gt 1 then retval=temporary(retval(1:*)) else begin
   if debug then stop,'sso(i)
   box_message,'No valid directories??'
   return,''
endelse
 
if keyword_set(max_filesperdir) then mfpd=max_filesperdir else mfpd=1000
ffiles=1-keyword_set(path_only)
if ffiles then begin ; now find the files
   ndir=n_elements(retval)
   newret=strarr(ndir*mfpd) ; careful - max per hour<1000???
   dcnt=0
   pnt=0
   i=0
   while ( (pnt lt n_elements(newret)) and (i lt ndir)) do begin 
        ff=findfile(retval(i))
        ssf=where(ff ne '',dcnt)
        ff=ff(0:(dcnt-1)<(mfpd-1))
        if dcnt gt 0 then begin 
           pnt=(where(newret eq ''))(0) ; first null for insertion
           if pnt+dcnt<mfpd gt (n_elements(newret)-1) then begin
              box_message,'limit hit, truncating list'
              ff=ff(0:mfpd-1)
           endif
           newret(pnt)=retval(i)+'/'+ff
           if debug then stop
        endif
        i=i+1
    endwhile
    retval=strarrcompress(temporary(newret))
endif ; else only return pathnames, not files

hour_dir='H'+strextract(retval,'/H','/')

return,retval
end

