;+
; Project     : SOHO - CDS     
;                   
; Name        : CFITSLIST
;               
; Purpose     : Create/update the lfitslist.txt file.
;               
; Explanation : CDS fits file names don't tell you much about their 
;               content. This program creates/updates a file
;               called lfitslist.txt in the fits file directory, with
;               various information on the content of the files.
;               This file is used by PICKFITS in order to search
;               the list of files for those files that the user wants.
;
;               NOTE! Creating a new and complete listing of all files
;               may take a *long* time, from half an hour (for ~3000 files)
;               and up, depending heavily on hardware/network/OS setup.
;
; Use         : CFITSLIST [,FITSDIR [,LISTDIR]]
;    
; Inputs      : None required.
;               
; Opt. Inputs : FITSDIR : The directory with the fits files to be in the
;               list. Default "$CDS_FITS_DATA". Multiple paths are possible
;               through comma or colon !path-like notation.
;
;               LISTDIR : The directory to place the list in. This is also the
;                         directory where the lfitslist.txt file is
;                         created/updated. The default is "$CDS_FITS_DATA_W".
;               
; Outputs     : None.
;               
; Opt. Outputs: None.
;               
; Keywords    : None.
;
; Calls       : ANYTIM2UTC(), BREAK_FILE, CONCAT_DIR(), DEFAULT, FILE_EXIST(),
;               FIND_FILES(), FXBCLOSE, FXBOPEN, FXBTDIM(), FXPAR(), PARCHECK,
;               RD_ASCII(), STRPAD(), TRIM(), TYP()
;
; Common      : None.
;               
; Restrictions: Expects to find fits files in the specified directory.
;               If there is already a lfitslist.txt file in the destination
;               directory, it has to have one or more entries.
;               
; Side effects: Creates/updates the file "lfitslist.txt" in the
;               specified directory.
;               
; Category    : CDS Utility
;               
; Prev. Hist. :
;
; Written     : Stein Vidar H. Haugan, UiO, 22 March 1996
;               
; Modified    : Version 2, SVHH, 18 April 1996
;                          Changed format of fitslist.txt -> lfitslist.txt
;                          Generic format.
;               Version 3, SVHH, 19 April 1996
;                          Added check for errors after FXBOPEN call.
;               Version 4, SVHH, 22 April 1996
;                          TITLE expanded to 80 chars max
;               Version 5, SVHH, 23 April 1996
;                          Using find_files for multi-path CDS_FITS_DATA.
;                          Allowing both FITSDIR and LISTDIR to be 
;                          specified.
;                          For updates the new list is collected before
;                          it's written -- direct overwrite, no spawns.
;               Version 6, SVHH, 29 April 1996
;                          Wrote fitslist_add, fitslist_addtx to shorten
;                          cfitslist_prop. These are (should be) identical 
;                          in sfitslist (the SUMER version). Added a few
;                          error tests (to catch corrupt fits files etc).
;
; Version     : 6, 29 April 1996
;-            


;
; Standard procedures for adding entries to the line
;

PRO fitslist_add,entry,name,text,length,form,line
  ON_ERROR,0
  IF N_PARAMS() NE 6 THEN MESSAGE,"Wrong number of parameters"
  line = line + strpad(STRMID(entry,0,length-1),length,/after)
  IF N_elements(form) GT 0 THEN BEGIN
     IF STRLEN(text) GT length-1 THEN MESSAGE,"Text longer than entry"
     new = name+'='+text+'='+trim(length)
     IF datatype(form) NE 'STR' THEN form = [new] $
     ELSE                            form = [form,new]
  END
END

PRO fitslist_addtx,header,name,text,length,form,line
  ON_ERROR,0
  IF N_PARAMS() NE 6 THEN MESSAGE,"Wrong number of parameters"
  entry = fxpar(header,name)
  fitslist_add,entry,name,text,length,form,line
END

;
; Make one line of text out of one fits file name.
; Calculate form when CALCFORM is set present
;

PRO cfitslist_prop,f,calcform=calcform,out=out
  catch,error
  IF error NE 0 THEN GOTO,PROCESS_ERROR
  
  errmsg = ''
  fxbopen,unit,f,1,header,errmsg=errmsg
  IF errmsg NE '' THEN GOTO,PROCESS_ERROR
  
  fxbclose,unit
  
  break_file,f,disk,dir,filnam
  
  calcform = KEYWORD_SET(calcform)
  IF calcform THEN form = 0
  
  n = ''
  
  
  fitslist_add,filnam,'FILENAME','Filename',10,form,n
  fitslist_addtx,header,'DETECTOR','det',4,form,n
  
  utc_ecs = STRMID(anytim2utc(fxpar(header,'DATE_OBS'),/ecs),0,16)
  fitslist_add,utc_ecs,'DATE',' date-obs',11,form,n
  fitslist_add,STRMID(utc_ecs,11,5),'TIME',' time',6,form,n
  
  pointing = ("(" + STRING(FIX(fxpar(header,"XCEN")),'(I5)') $
              + ","+STRING(FIX(fxpar(header,"YCEN")),'(I5)') + ") ")
  fitslist_add,pointing,'POINTING','  pointing',14,form,n
  
  sl = FIX(fxpar(header,"SLIT_NUM"))-1
  slit = (['   2x2','   4x4','  8x51',' 2x240',' 4x240','90x240'])(sl) + " "
  fitslist_add,slit,'SLIT','  slit',7,form,n
  
  ;; Add dimension sizes
  i = FIX(fxbtdim(fxpar(header,'TDIM1')))
  ax = fxbtdim(fxpar(header,'TDESC1'))
  FOR axi = 0,3 DO BEGIN
     XIS = (['WAVELNTH','SOLAR_X','SOLAR_Y','DEL_TIME'])(axi)
     ix = WHERE(ax EQ XIS)
     IF ix(0) EQ -1 THEN axsz = 0  $
     ELSE                axsz = i(ix(0))
     IF axi EQ 0 THEN n = n + STRING(axsz,'(i4)') +" " $
     ELSE             n = n + STRING(axsz,'(i3)') +" "
  END
  IF calcform THEN form = [form,'LAMSZ=lamb=5', $
                           'XSZ=xsz=4','YSZ=ysz=4','TSZ=tsz=4']
  
  ;; Binning factors
  binx = FIX(fxpar(header,'TBINX1'))
  n = n + STRING(binx,'(i4)')
  biny = FIX(fxpar(header,'TBINY1'))
  n = n + STRING(biny,'(i4)') + ' '
  IF calcform THEN form = [form,'BINXY=  binx/y=9']
  
  n = n + STRING(fxpar(header,'EXPTIME'),'(f6.1)') + ' '
  IF calcform THEN form = [form,'EXPTIME=Exptim=7']
  
;;; Study texts
  
  ;; OBS_PROG == Name of the study
  fitslist_addtx,header,'OBS_PROG','Obs.prog',9,form,n
  
  ;; Study title
  fitslist_addtx,header,'TITLE','Study title',81,form,n
  
  ;; Study Category
  fitslist_addtx,header,'CATEGORY','Category',12,form,n
  
;;; Plan items
  
  fitslist_addtx,header,'SCI_OBJ','Science objective',51,form,n
  
  fitslist_addtx,header,'SCI_SPEC','Specific science objective',51,form,n
  
  fitslist_addtx,header,'OBJECT','Obj',4,form,n
  
  fitslist_addtx,header,'OBJ_ID','Obj.ID',7,form,n
  
  IF calcform THEN begin
     frm = ''
     FOR ii = 0,N_ELEMENTS(FORM)-2 DO frm = frm + form(ii) + '='
     frm = frm + form(ii)
  END
  
  out = n
  IF calcform THEN out = [frm,out]
  RETURN
  
PROCESS_ERROR:  
  catch,/cancel
  MESSAGE,"File "+f+" could not be processed",/continue
  out = ''
  RETURN
END


FUNCTION cfitslist_srnumber,filename
  ON_ERROR,0
  bfilename = byte(filename)
  bfilename(WHERE(bfilename LT 48b OR bfilename GT 48b+9b)) = 32b
  num = dblarr(2,N_ELEMENTS(filename))
  READS,STRING(bfilename),num
  RETURN, num(0,*) + 0.0001d*num(1,*)
END

;
; Incremental update
;
PRO inccfitslist,fitsdir,file
  
  ;;----------------------------------------------------
  ;; Find the actual file list
  
  a_filelist = find_files("s*r*.fits",fitsdir)
  
  break_file,a_filelist,disk,dir,a_filename
  
  ;; Calculate srnum (study number + 0.0001 * raster number)
  a_srnum = cfitslist_srnumber(a_filename)
  
  ;; Sort actual file list according to snum
  ix = SORT(a_srnum)
  a_filelist = a_filelist(ix)
  a_filename = a_filename(ix)
  a_srnum = a_srnum(ix)
  
  ;;---------------------------------------------------
  ;; Find the original file list (assumed sorted)
  
  IF NOT file_exist(file) THEN  $
     MESSAGE,"There's no lfitslist.txt file here"
  
  o_list = rd_ascii(file)
  
  IF N_ELEMENTS(o_list) LT 2 THEN  $
     MESSAGE,"I need an existing, nonempty cds fitslist"
  
  ;; Chop it's head off and calculate srnum (for identification)
  head = o_list(0)
  o_list = o_list(1:*)
  o_srnum = cfitslist_srnumber(STRMID(o_list,0,10))
  
  ;; Loop variable initialization
  
  changed = 0
  currenti = 0 
  newlist = [head]
  
  ;; Check each existing file if it's in the list
  
  FOR i = 0L,N_ELEMENTS(a_filelist)-1 DO BEGIN
     IF (WHERE(o_srnum EQ a_srnum(i)))(0) EQ -1 THEN BEGIN
        changed = 1
        ;; Find out where to place it to keep list sorted
        ix = (WHERE(o_srnum GT a_srnum(i)))(0)
        IF ix EQ -1 THEN ix = N_ELEMENTS(o_list)
        ;; Create the text entry
        cfitslist_prop,a_filelist(i),out=out
        IF out(0) NE '' THEN begin
           ;; Place it in the new list, along with all higher-ranking 
           ;; existing entries
           IF ix EQ currenti THEN newlist = [newlist,out] $
           ELSE newlist = [newlist,o_list(currenti:ix-1),out]
           ;; These have been accounted for
           currenti = ix
           PRINT,"Added "+a_filelist(i)
        END
     END
  END
  
  IF NOT changed THEN BEGIN
     ;; Njet, nada nothing
     PRINT,"No changes"
     RETURN
  END
  
  ;; Add the rest of the original list that wasn't already copied
  
  IF currenti LT N_ELEMENTS(o_list) THEN  $
     newlist = [newlist,o_list(currenti:*)]
  
  ;; Write new list
  
  PRINT,"Opening "+file
  OPENW,flun,file,/GET_LUN,error = error
  IF error NE 0 THEN BEGIN
     MESSAGE,"Could not open lfitslist.txt file for writing -- aborting", $
        /continue
     RETURN
  END
  ;; The format is necessary to avoid a space in front lines
  PRINTF,flun,newlist,FORMAT='(A)'
  CLOSE,flun
  FREE_LUN,flun
END



PRO cfitslist,fitsdir,listdir
  ON_ERROR,2
  IF !debug GT 0 THEN ON_ERROR,0
  
  default,fitsdir,"$CDS_FITS_DATA"
  default,listdir,"$CDS_FITS_DATA_W"
  
  parcheck,fitsdir,1,typ(/str),0,'FITSDIR'
  parcheck,listdir,2,typ(/str),0,'LISTDIR'
  
  ;; This is where the list should be
  file = concat_dir(listdir,'lfitslist.txt')
  
  ;; Do an incremental update if it's not there.
  IF file_exist(file) THEN BEGIN
     inccfitslist,fitsdir,file
     RETURN
  END
  
  ;; Get the full list
  filelist = find_files("s*r*.fits",fitsdir)
  
  PRINT,"About to create new lfitslist.txt with "+ $
     trim(N_ELEMENTS(filelist))+" elements"
  
  break_file,filelist,disk,path,filename
  
  ;; Calculate srnum and sort accordingly
  n = cfitslist_srnumber(filename)
  filelist = filelist(SORT(n))
  
  ;; Just do it.
  
  OPENW,flun,file,/GET_LUN
  calcform = 1
  FOR i = 0L,N_ELEMENTS(filelist)-1 DO BEGIN
     cfitslist_prop,filelist(i),calcform=calcform,out=out
     IF out(0) NE '' THEN BEGIN
        PRINTF,flun,out,FORMAT='(A)'
        calcform = 0
     END
  END
  
  CLOSE,flun
  FREE_LUN,flun
END

