;+
; Project     : SOHO - CDS
;
; Name        : RD_CDS_POINT
;
; Purpose     : Read CDS pointings for specified times
;
; Category    : planning
;
; Explanation : Read planned or ASRUN database
;
; Syntax      : IDL> plans=rd_cds_point(tstart,tend)
;
; Inputs      : TSTART = plot start time [def=current date]
;
; Opt. Inputs : TEND = plot end time [def = 24 hour window]
;
; Outputs     : PLANS = plan structures stored as MAPS
;
; Keywords    : ASRUN = plot actual pointing based on CATALOG
;               QUIET = switch off message outputs
;               EXCLUDE = study acronyms to exclude, e.g [SYNOP, FULLCCD]
;               DEF_EXCLUDE = exclude default studies (engineering, SYNOP)
;               NOENG = exclude engineering studies
;               ROTATE = solar rotate pointings to TIME
;               TIME = time to rotate pointings to
;               COUNT = # of plans found
;               NEAREST = if set and only TSTART is given, return closest
;               STUDY = study program (e.g. s22906r04)
;                                                                        
; History     : Written,  20-May-1998,  D.M. Zarro.  
;               Modified, 30-Nov-1999, Zarro (SM&A/GSFC) - added /NEAREST
;               Modified, 23-Jul-2001,  D.M. Zarro (EITI/GSFC) - added STUDY
;
; Contact     : DZARRO@SOLAR.STANFORD.EDU
;-

function rd_cds_point,tstart,tend,err=err,exclude=exclude,_extra=extra,$
     def_exclude=def_exclude,rotate=rotate,nearest=nearest,$
     asrun=asrun,time=time,noeng=noeng,quiet=quiet,count=count,study=study

common rd_cds_point,last_tstart,last_tend,$
            db_checked,last_db,last_planned,last_asrun

;-- default studies to exclude

def_prog=['synop','eng','fullccd','nimcp','gimcp','fsun','usun']
count=0
quiet=keyword_set(quiet)
loud=1-quiet
asrun=keyword_set(asrun)
planned=1-asrun
rplans=-1

;-- check if and which DB's are loaded

if not exist(db_checked) then db_checked=0b
db_changed=1b & cur_db=getenv('ZDBASE')
if exist(last_db) then begin
 db_changed=(cur_db ne last_db)
 db_checked=(not db_changed)
endif

new_db=cur_db
if not db_checked then begin 
 message,'checking ZDBASE...',/cont
 set_cds_sdb,/cds
 find_zdbase,db,/off,/daily,/cat,/def,/verb,err=err
 new_db=trim(getenv('ZDBASE'))
 if exist(last_db) then db_changed=(new_db ne last_db)
 if new_db eq '' then begin
  err='could not locate ZDBASE'
  message,err,/cont
  goto,done
 endif
endif
dprint,'% db_changed:',db_changed

;-- entry point if study id (e.g. s22906) entered

if exist(study) then begin
 cds_asrun_point,tplans,study=study,count=count,_extra=extra
 if count eq 0 then begin
  message,'no CDS plans for study '+trim(string(study)),/cont
  goto,done
 endif
 goto,next
endif


;-- check time inputs

t1=get_def_times(tstart,tend,dend=t2)
dprint,'% TSTART,TEND: ',anytim2utc(t1,/vms)+', '+anytim2utc(t2,/vms)

;-- only re-read if time or DB changed, nothing was read before

new_tstart=anytim2tai(t1) & new_tend=anytim2tai(t2)
time_changed=1b
if exist(last_tstart) and exist(last_tend) then $
 time_changed=(new_tstart lt last_tstart) or $
             (new_tstart gt last_tend) or $
             (new_tend lt last_tstart) or $
             (new_tend gt last_tend) 


do_read=time_changed or db_changed or $
        (planned and (not exist(last_planned))) or $
        (asrun and (not exist(last_asrun)))

if do_read then begin
 if planned then begin
  cds_plan_point,plans,t1,t2,count=count
  if count gt 0 then last_planned=plans else delvarx,last_planned
 endif else begin
  cds_asrun_point,plans,t1,t2,count=count
  if count gt 0 then last_asrun=plans else delvarx,last_asrun
 endelse
endif else begin
 if planned then plans=last_planned else plans=last_asrun
 count=n_elements(plans)
endelse

;-- save state

last_db=new_db & last_tstart=new_tstart & last_tend=new_tend
if (count eq 0) then goto,done

;-- select plans falling within specified times

tplans=plans
stimes=anytim2tai(plans.time)
etimes=anytim2tai(plans.tend)
index=where( ((stimes ge new_tstart) and (stimes le new_tend)) or $
             ((etimes ge new_tstart) and (etimes le new_tend)), count)
if count gt 0 then tplans=tplans(index) else begin
 err='No CDS plans found for input times'
 message,err,/cont 
 goto,done
endelse

;-- check what studies to exclude

if (datatype(exclude) eq 'STR') or keyword_set(def_exclude) then begin
 if datatype(exclude) ne 'STR' then exclude=def_prog
 for i=0,n_elements(exclude)-1 do begin
  d=grep(exclude(i),tplans.id,/exclude,index=index)
  if min(index) eq -1 then begin
   err='warning, all studies excluded from plot'
   message,err,/cont
   count=0
   goto,done
  endif
  tplans=tplans(index)
 endfor
endif

;-- solar rotate to input time (only deferred pointing studies)

next:

rplans=tplans
if exist(time) and keyword_set(rotate) then begin
 have_fixed=tag_exist(tplans,'fixed')
 if have_fixed then begin
  no_rotate=where(tplans.fixed,are_fixed)
  do_rotate=where(tplans.fixed eq 0,not_fixed)
  if are_fixed gt 0 then fixed_plans=tplans(no_rotate)
  if not_fixed gt 0 then $
   rot_plans=drot_map_fast(tplans(do_rotate),time=time,/no_rtime)
  rplans=merge_struct(fixed_plans,rot_plans)
 endif
endif

;-- find nearest entry to TSTART (if requested)

if keyword_set(nearest) and (not exist(tend)) and exist(tstart) then begin
 times=anytim2tai(rplans.time)
 diff=abs(times-anytim2tai(t1))
 ok=where(diff eq min(diff))
 rplans=rplans(ok)
endif

count=n_elements(rplans)
                                          
done:

if cur_db ne '' then mklog,'ZDBASE',cur_db

return,rplans & end

