pro sot_cat, time0, time1, catx, ofiles, search_array=search_array, $
   files=files, urls=urls, refresh=refresh, matchrecs=matchrecs, debug=debug, $
   error=error, xrt=xrt, temp=temp, sirius=sirius, quicklook=quicklook, $
   count=count, tcount=tcount, level0=level0, _extra=_extra, level1=level1, check_files=check_files, use_level1_cat=use_level1_cat
;+
;   Name: sot_cat
;
;   Purpose: read sot (or xrt)  catalog for time/time-range; optionally search
;
;   Input Parameters:
;      time0, time1 - desired time range
;
;   Output Paramters:
;      cat - output catalog records (or implied filenames/urls)
;      files - optionally return filenames or urls
;
;   Keyword Parameters:
;      search - optional search params (per struct_where.pro)
;      _extra - unknown params assumed PARAM=VALUE pairs -> struct_where
;         (include /FOLD_CASE to make string searches case insensitive)
;      refresh - if set, refresh cacche (reread catalog)
;      xrt - if set, apply to XRT dbase (def=SOT dbase)
;      temp - if set, use 'temporary' (offline/inprogress) catalog dbase
;      urls - if set, return urls instead of files (ignored if nparam<4)
;      sirius - if set, use 'sirius' catalog (default is quicklook) 
;      matchrecs (output) - number of records which match optional search params 
;      tcount - (output) - number of catalog entries within time range
;      count - (output) - number of matches returned (time + search params)
;      level0 - synonym for /sirius
;      level1 - does level0->level1 replacement (assumes 1:1 catalog/filenames)
;      check_files - if set, check local file exist
;      use_level1_cat - use parallel level1 catalog, rather than deterministic level0->level1 assumption
;      
;   Calling Sequence:
;      IDL> sot_cat,time0,time1,catout [search=search] [,/XRT])
;      IDL> sot_cat,time0,time1,search=['PARAM=VALUE','PARAM=VALUE',...])
;
;   History:
;      10-Apr-2006 - S.L.Freeland
;      19-jul-2006 - S.L.Freeland - xrt hook - use cache_data.pro 
;                                   instead of explicit common - lookup 
;                                   cache by instrument (sot/xrt)
;      16-oct-2006 - S.L.Freeland - change default (packages/solarb ->
;                                   $SSWDB/hinode based on start time )
;       4-apr-2007 - S.L.Freeland - add /SIRIUS keyword&function
;       5-apr-2007 - S.L.Freeland - define COUNT & TCOUNT output keywords
;      16-jul-2007 - S.L.Freeland - actually enabled the /LEVEL0 keyword(!) to conform
;                                   to the previously added keyword & documentation 
;      16-aug-2007 - S.L.Freeland - add LEVEL0 tag to output to retain memeory
;                                   of Level0(Sirius) vs QuickLook
;      20-aug-2007 - S.L.Freeland - fix 16-aug bug (inadvert changed default
;                                   quick->sirius if FILES supplied)
;      30-aug-2007 - S.L.Freeland - remove needless 'help' line 
;                    Temporarily use struct_where2.pro (until ssw-gen update
;                    privs are recovered...)
;      16-oct-2007 - S.L.Freeland - struct_where2->struct_where
;      20-may-2008 - S.L.Freeeland - per PI team, Level0 is default if /XRT set
;                    (historical default is Quicklook)
;      26-jan-2016 - S.L.Freeland - add LEVEL1 and CHECK_FILES keywords&function
;-

common sot_cat_blk, lsirius
if n_elements(lsirius) eq 0 then lsirius=''  

xrt=keyword_set(xrt)
cname='xxxcat' ; comingle sot&xrt&..??
ctype=(['sot','xrt'])(xrt)
quicklook=keyword_set(quicklook)
xrtl0=(xrt and (1-quicklook))

debug=keyword_set(debug)
use_level1_cat=keyword_set(use_level1_cat)
level1=keyword_set(level1) or use_level1_cat
sirius=(['','_sirius'])(keyword_set(sirius) or keyword_set(level0) or xrtl0 or level1 )

tempx=(['','_temp'])(keyword_set(temp))

postlaunch=ssw_deltat(time0,ref='1-oct-2006',/day) gt 0
postlaunch=postlaunch(0)
topdir=concat_dir('$SSWDB','packages/solarb/'+ctype+'_genxcat'+sirius+tempx)
if not file_exist(topdir) or postlaunch then $
    topdir= concat_dir( $  ; ssw client synonyms
   concat_dir(concat_dir('$SSWDB','hinode'),ctype),ctype+'_genxcat'+sirius+tempx)
if not file_exist(topdir) then begin 
   box_message,['Cannot find catalog dbase under...','   '+ topdir(0)]
   return
endif

if use_level1_cat then topdir=str_replace(topdir,'sirius','level1') ; catalog, not deterministic

box_message,'Catalog parent = ' + topdir

lcat='last'+ctype
ltype=ctype
mcat='mission'+ctype
;
; get the approriate cache data
ct0=ctype+'t0'
ct1=ctype+'t1'

cache_data,cname,mcat,mission_cat,/get   ; misson cat -> cache
cache_data,cname,ct0,t0,/get
cache_data,cname,ct1,t1,/get
cache_data,cname,lcat,lastcat,/get
cache_data,cname,ltype,lasttype,/get

if n_elements(time1) eq 0 then time1=reltime(time1,/days)
error=0
refresh=keyword_set(refresh) or (sirius ne lsirius)

;if data_chk(mission_cat,/string)  then begin ; for later...
   if n_elements(t0) eq 0 then t0=reltime(time0,/days)
   if n_elements(t1) eq 0 then t1=reltime(time1,days=-1)
   if ssw_deltat(t0,time0) lt 0 or  ssw_deltat(t1,time1) gt 0 or $
      lasttype ne ctype or refresh then begin
      lsirius=sirius 
if debug then stop,'topdir'
      read_genxcat,time0,time1,catx, topdir=topdir, error=error,_extra=_extra
      ; cache current catalog
      cache_data,cname,lcat,catx
      cache_data,cname,ltype,ctype
      cache_data,cname,ct0,time0
      cache_data,cname,ct1,time1
      if n_elements(catx) ge n_elements(mission_cat) then $
         cache_data,cname,mcat,catx
   endif else catx=lastcat
;endif else catx=mission_cat

sss=where(anytim(time0) le catx.anytim_dobs and $
                  anytim(time1) ge catx.anytim_dobs,sscnt)
count=sscnt
tcount=sscnt

if sscnt le 1 then begin 
   box_message,'No '+strupcase(ctype)+ ' records meet time/search criteria'
   catx=-1
   count=0
   return
endif
catx=catx(sss)

; now perform optional searches...

if data_chk(search_array,/string) then begin 
   sss=struct_where(catx,test=search_array, _extra=_extra, matchrecs)
   count=matchrecs
   if matchrecs eq 0 then begin 
      box_message,['No matches for your search criteria:',search_array]
      return ; !! early exit on no matches
   endif else catx=catx(sss)
endif

matchrecs=n_elements(catx) * (data_chk(catx,/struct))    
catx=add_tag(temporary(catx),sirius ne '','level0')  ; historical source
if matchrecs gt 0 and n_params() gt 3 then begin  
   ofiles=sot_cat2files(catx,urls=urls, sirius=sirius) 
   if level1 then begin 
      ofiles=str_replace(ofiles,'level0','level1')
   endif
endif

if keyword_set(check_files) then begin 
   fexist=file_exist(ofiles)
   ssok=where(fexist,okcnt)
   case 1 of 
      okcnt eq matchrecs: ; all exist NOP
      okcnt eq 0: begin 
         box_message,'catalog records matching, but no local files exist'
      endcase
      else: begin 
         box_message,'Only a subset of local files exist, returning those records/files
         ofiles=ofiles[ssok]
         catx=catx[ssok]
         matchrecs=okcnt
      endcase
   endcase
endif
   

; cat additions
if not required_tags(catx,'cdelt1') then begin 
   if required_tags(catx,'fovx,naxis1') then $    
      catx=add_tag(catx,catx.fovx/catx.naxis1,'cdelt1')
endif

if not required_tags(catx,/naxis) then  catx= $
   add_tag(temporary(catx),2,'naxis')

if debug then stop,'before return'

return
end




