;+
;
; PROJECT:
;       SOHO - CDS/SUMER
;
; NAME:
;       UPDATE_KAP
;
; PURPOSE: 
;       Read in the latest KAP files to keep database updated
;
; CATEGORY:
;       Planning
; 
; EXPLANATION:
;       This routine checks the KAP related database against released
;       KAP files and makes sure that the KAP related database is
;       updated (by calling READ_KAP). It will examine and read, if 
;       necessary, the KAP files from the date DATE to the next 
;       SPAN days. 
;   
; SYNTAX: 
;       update_kap, date
;
; EXAMPLES:
;       update_kap, '1995/11/07', ignore='CDS'
;
; INPUTS:
;       None required. If no input parameter, current date is implied.
;
; OPTIONAL INPUTS: 
;       DATE - The date starting from which the KAP files will be checked.
;              This can be in any of the standard CDS time formats.
;
; OUTPUTS:
;       None.
;
; OPTIONAL OUTPUTS:
;       TSTOP    - stop date for update (inclusive)
;
; KEYWORDS: 
;       IGNORE   - If passed, then contains the name or code value (see
;                  GET_INSTRUMENT) of an instrument to ignore when
;                  reading in SCIPLAN entries.  This is so that one can
;                  avoid overwriting one's own SCIPLAN entries, if
;                  desired.
;       BACKWARD - Number of days backward from which the KAP files
;                  are checked and read.
;       SPAN     - Number of days to span (starting from given DATE)
;       STATUS   - Indicator whether any new KAP file is read. 0 if no
;                  KAP file is read; 1 otherwise
;       FORCE    - Force the routine to read the latest KAP even if it
;                  has been read
;       ERR      - Returned err message; null for no err
;       PURGE    - set to automatically purge the DB's each time
;       CAMP     - set to update CAMPAIGN DB
;       CHECK    - set to check KAP's for valid campaigns
;       SOHO     - force SOHO DB to be updated
;       NORES    - do not update Resource DB
;
; COMMON:
;       None.
;
; RESTRICTIONS: 
;       None.
;
; SIDE EFFECTS:
;       None.
;
; HISTORY:
;       Version 1, August 1, 1995, Liyun Wang, GSFC/ARC. Written
;       Version 2, August 3, 1995, Liyun Wang, GSFC/ARC
;          Added keyword STATUS
;       Version 3, February 27, 1996, Liyun Wang, GSFC/ARC
;          Added NO_X keyword
;       Version 4, March 4, 1996, Liyun Wang, GSFC/ARC
;          Added ERR keyword
;          Made input parameter DATE as an optional one
;       Version 5, June 3, 1996, Zarro, GSFC
;          Added check for KAP file creation date
;       Version 6, Jan 23, 1997, Zarro, GSFC 
;          Added more error checks
;       Version 7, July 17, 1997, Zarro, GSFC 
;          Added TSTOP
;       Modified, April 14, 2007, Zarro (ADNET) 
;        - forced reading and updating of official SOHO/SSW database
;       
; CONTACT:
;       Dominic Zarro, GSFC/ARC (zarro@solar.stanford.edu)
;       Liyun Wang, GSFC/ARC (Liyun.Wang.1@gsfc.nasa.gov)
;-

   pro update_kap, date,tstop, ignore=ignore, span=span,backward=backward,camp=camp, $
               status=status,force=force,err=err,purge=purge,$
               alert=alert,check=check,_extra=extra,soho=soho,$
               forward=forward,nores=nores,expire=expire

   err=''
   status = 0
   defsysv,'!priv',3

;-- defaults

   if exist(forward) then span=long(forward) else begin
    if not exist(span) then span=7
   endelse
   force=keyword_set(force)
   vms=os_family() eq 'vms'
   
   if n_elements(backward) eq 0 then backward = 0L else backward = long(backward)
   if n_elements(date) eq 0 then begin
    get_utc, date, /ecs,/date,/vms
    message,'Updating DB for '+date,/cont
   endif

   sdate = anytim2utc(date, err=err)
   if err ne '' then begin
    message, err, /cont
    return
   endif

;-- SOHO DB?

   sav_db=getenv('ZDBASE')
   err=''
   s=fix_zdbase(/soho,err=err)
   if ~s then begin
    message,err,/cont
    return
   endif

;-- lock database to prevent simultaneous updating by other runs

   if not exist(expire) then expire=3600.
   lock_zdbase,'update_kap_lock',/resource,status=status,expire=expire,$
               lock_file=lock_file,err=err,over=force
   if not status then begin
    print,'--> try again later'
    goto,quit
   endif

;-- update campaigns

   if keyword_set(camp) then update_campaign
 
;-- restore KAP log file

   soho_db='$SSW/soho/gen/data/plan/database'
   if not write_dir(soho_db,out=soho_db) then begin
    message,'No write access to '+soho_db,/cont
    mklog,'ZDBASE',sav_db
    return
   endif

   kap_log_file=concat_dir(soho_db,'update_kap_log.genx')
   klook=loc_file(kap_log_file,count=kcount)
   if kcount gt 0 then begin
    kap_log=0
    restgen,kap_log,file=kap_log_file
    if datatype(kap_log) eq 'STC' then if not tag_exist(kap_log,'KAP_FILE') then kap_log=add_tag(kap_log,'','KAP_FILE')
   endif

;-- determine START/STOP dates

   span=(span > 1)
   start_date=sdate
   stop_date=sdate
   start_date.time=0
   start_date.mjd=start_date.mjd-backward
   stop_date.mjd=stop_date.mjd+span-1
   stop_date.time=0

;-- override with TSTOP value

   err=''
   tstop_date=anytim2utc(tstop,err=err)
   if err eq '' then begin
    stop_date=tstop_date
    stop_date.time=0
    if stop_date.mjd lt start_date.mjd then begin
     temp=stop_date & stop_date=start_date & start_date=temp
    endif
   endif
  
;-- find KAP files within START/STOP times

   cur_date=start_date
   must_save_log=0
   repeat begin
    ymd = date_code(cur_date)
    latest_kap_file=get_latest_kap(cur_date,create=new_create,status=found)
    if found gt 0 then begin

;-- check KAP log if this creation date is newer than last one for this date

     do_update=1 & dcount=0
     if datatype(kap_log) eq 'STC' then begin
      dfind=where(ymd eq kap_log.ymd,dcount)
      if dcount gt 0 then begin
       last_create=kap_log(dfind).last_create
       if anytim2tai(new_create) gt anytim2tai(last_create) then begin
        dprint,'ymd,last_create,new_create:',ymd,last_create,new_create
       endif else begin 
        message,ymd+' already updated',/cont
        do_update=0
       endelse
      endif
     endif 

;-- check what instruments to update

    if datatype(extra) eq 'STC' then begin
     etags=strmid(tag_names(extra),0,3)
     inst=get_soho_inst()
     sinst=strmid(inst,0,3)
     do_inst=where_vector(etags,sinst,rest=rest,rcount=rcount)
     if rcount gt 0 then ignore=inst(rest)
    endif

;-- Update KAP DB if KAP file has new creation date, or /FORCE is set

     if do_update or force then begin
      must_save_log=1
      message,/cont,'reading KAP file for '+anytim2utc(cur_date, /ecs, /date)
      done=read_kap(latest_kap_file,ignore=ignore,/nopurge,/noset,nores=nores)
     
;-- check for valid campaigns

      alert=keyword_set(alert)
      check=keyword_set(check)
      if (check or alert) then check_kap,latest_kap_file,alert=alert,/missing

;-- Update KAP log

      if dcount gt 0 then begin
       kap_log(dfind).last_create=new_create 
       kap_log(dfind).kap_file=latest_kap_file 
      endif else begin
       new_entry={ymd:ymd,last_create:new_create,kap_file:latest_kap_file}
       kap_log=concat_struct(kap_log,new_entry)
      endelse
     endif
    endif

    cur_date.mjd=cur_date.mjd+1L
   endrep until (cur_date.mjd gt stop_date.mjd)

;-- save KAP log file

   if (datatype(kap_log) eq 'STC') and must_save_log then begin
    message,'saving KAP log file',/cont
    savegen,file=kap_log_file,/xdr,kap_log,/notype
    if not vms then espawn,'chmod g+w '+kap_log_file,out,/noshell
   endif

;-- Purge DB's
                            
   if must_save_log and keyword_set(purge) then begin
    dprint,'purging DB...'
    err=''
    s=prg_plan(err=err)
    err=''
    s=prg_soho_det(err=err)
   endif
   status=must_save_log

;-- remove KAP lock file and set things back

   unlock_zdbase,lock_file

quit: mklog,'ZDBASE',sav_db

   return & end