;+
; NAME:
;     Build_Schedule
; PURPOSE:
;     Given an optional date (system date used if not specified), a
;     schedule file (solar.scd) will be created from the tmp file
;     (solar.tmp).  The program finds and replaces the day of the year,
;     the time (based on the calibrator's times returned from the check_cals
;     function) and/or the calibrator's name (again based on the calibrator's
;     names returned from the check_cals function).  Then it outputs the
;     modified lines to the schedule file.
; CATEGORY:
;     OVRO APC DATA CALIBRATION
; CALLING SEQUENCE
;     build_schedule,[date]
; OPTIONAL (KEYWORD) INPUT PARAMETERS:
;     date       the date in the format : YYYY-MON-DD where MON is the first
;                3 letters of the month
; ROUTINES CALLED:
;     External: check_cals, msec2str, anytim, dayofyr, caldat, read_sched
; OUTPUTS:
;     The output is the schedule file solar.scd
; COMMENTS:
; SIDE EFFECTS:
; RESTRICTIONS:
; MODIFICATION HISTORY:
;     Written 13-Mar-2002 by Garrett Smith
;     20-Mar-2002  DG
;       Heavily rewritten to be more general and also to take advantage of
;       some other code.
;     30-Dec-2003  DG
;       Changed name of STRPLIT to SSW_STRSPLIT to account for change in SSW
;     22-Jun-2007  DG
;       Added 0.5 to JD since without it the date was 1 day early.  Also added
;       code to fix some end-of-day anomalies (but not all).  This should result
;       in fewer schedules needing "fixing."
;-

pro build_schedule,date
    if(not keyword_set(date)) then begin
        mon = '' & day = 0 & yr = 0
        reads,systime(),mon,day,yr,format='(4x,A3,1x,I2,10x,I4)'
        doy = dayofyr(yr,mon,day)
        date = string(yr,mon,day,format='(I4,"-",A3,"-",I2.2)')
    endif else begin
        jd = (anytim(date,/mjd)).mjd + 2400000.5D
        caldat,jd,mon,day,yr
        doy = dayofyr(yr,mon,day)
    endelse
    cals_struct = check_cals(date)          ; get the calibrators for the schedule
    if(size(cals_struct,/type) eq 8) then begin     ;If it is not a struct then it is out of date range
        if (n_elements(cals_struct.name) eq 5 ) then begin  ; if there are 5 or more cals then the schedule can be built
            filename = !defaults.workdir+'solar_template.scd'
            openr,lun, /get_lun, filename
            result = read_sched(lun,sched,defs)
            free_lun,lun
            if (result ne "Success") then begin
               print,'BUILD_SCHEDULE: Error reading schedule file'
               free_lun,lun
               return
            endif

            nlines = n_elements(sched)
            cals = where(strpos(defs[*,0],'DO-CAL') ne -1, ncals)
            time = sched.hh*60. + sched.mm
            negtime = where(time gt 720.,nneg)
            if (nneg gt 0) then time[negtime] = time[negtime] - 1440.
            orig_time = time
            time[0] = time[0] + fix(cals_struct.time[0]/60.)
            thiscal = 0

            for i = 1, nlines-1 do begin
               if (time[i]-orig_time[i-1] lt 0) then begin
                    thiscal = thiscal + 1
               endif
               time[i] = time[i] + fix(cals_struct.time[thiscal]/60.) + cals_struct.tadj[thiscal]
            endfor
            time = fix(time) mod 1440
            ; Update the calibrator hours, minutes, and day
            sched.hh = time/60
            sched.mm = time mod 60
            sched.day = sched.day + doy
            ; Update the calibrator names
            sched[cals].src = strtrim(cals_struct.name[0:ncals-1])

            ; All the main lines are updated.  Now update the defs with the names
            for i = 0, ncals-1 do begin
               k = cals[i]
               first = ssw_strsplit(defs[k,0],' ')
               defs[k,0] = sched[k].src+strmid(defs[k,0],strlen(first))
            endfor

            ; Schedule is done, but do a sanity check and fix schedule for those with
            ; wrong day (typically happens when there are really only 4 calibrator scans
            ; and the software forces 5).
            tord = sched.day+(sched.hh*100+sched.mm)/2400.
            bad = where(tord-tord[0] lt 0,nbad)
            if (nbad ne 0) then begin
               sched[bad].day = sched[bad].day + 1  ; Fix the day numbers
               if (nbad eq 1) then begin
                  ; One bad day number means there were only 4 calibrator periods, so
                  ; the fifth one defauls to 3C84.  Often it could really be just a
                  ; repeat of the previous calibrator
                  sched[bad].src = cals_struct.name[ncals-2]
                  first = ssw_strsplit(defs[bad,0],' ')
                  defs[bad,0] = sched[bad].src+strmid(defs[bad,0],strlen(first))
               ; Set start time to setting time of the Sun
                  ; Convert date string to JD
                  jd = (anytim(date,/mjd)).mjd + 2400000.5D
                  ; Read the calibrators that are used for OVSA
                  cals = uptime(7,JD=jd)
                  isun = where(strmid(cals.info.name,0,3) eq 'SUN')
                  hhmm = strmid(cals.info[isun].set,1,2)+strmid(cals.info[isun].set,4,2)
                  if (hhmm gt '0030') then begin
                     ; Time refers to previous day
                     sched[bad].day = sched[bad].day -1
                     sched[bad].hh = hhmm/100
                     sched[bad].mm = hhmm mod 100
                  endif
               endif else if (nbad eq 2) then begin
                  ; Two bad lines is harder.  It means an extra SUN and calibrator line
                  ; were inserted.  Simply delete them (this is not entirely correct, but
                  ; it should be closer than keeping them)
                  sched[bad[0]:nlines-3]=sched[bad[1]+1:nlines-1]
                  defs[bad[0]:nlines-3,*] = defs[bad[1]+1:nlines-1,*]
                  nlines=nlines-2
               endif
            endif

            ; Now see if the stated source is really up for these bad times, and
            ; eliminate lines if the source is not up.

            outfile = !defaults.workdir+'solar.scd'
            openw,lun,/get_lun,outfile

            line = ''
            maxdefs=3
            for i = 0, nlines-1 do begin
               line = string(sched(i).day,sched(i).hh,sched(i).mm,sched(i).src,$
                                       format='(I3.3,1X,I2.2,":",I2.2,1X,A)')
               printf,lun,line
               for j = 0, maxdefs-1 do begin
                  if (defs[i,j] ne '') then printf,lun,'               ' + defs[i,j]
               endfor
            endfor
            free_lun,lun

            print,'The schedule file for ', date, ' was created successfully.'
            return
        endif else begin
            print,'WARNING: Too few calibrators are available for the date, ', date, ','
            print,'         to allow for the creation of the schedule.'
            return
        endelse
    endif else begin
        print,'WARNING: The requested date, ', date, ', does not exist in hessi.obj!'
        Print,'         Please try another date or update the hessi.obj file.'
        return
    endelse
end

