; Nov. 28, 2012 - NBR
; NOTE: This procedure is now superceded by time_correction2.pro, in 
; $SSW/packages/nrl/idl/nrlgen/lascoeit/.
;
; Jul 10, 2002 - AEE
; Note: according th Jeff Newmark, data in TIME_DIFFERENCE_DB before Sep 1, 1997 are invalid
;       and should NOT be used (starts from 1997-04-11). This new routine (unlike the older
;       eit_time_correction modified by DW, returns time-offsets prior to Sep 1997 which 
;       should not be used; But, once C2 data from Jan 1996 to Sep 3, 1997 is added to the
;       TIME_DIFFERENCE_DB, then everything would be fine. 

; TIME_CORRECTION
;+
; Name:
;    TIME_CORRECTION
;
; Purpose:
;    To return the OBE - LOBT time difference that is equal to or right before the
;    the input obe-time from the values in TIME_DIFFERENCE_DB.
;
; Input Parameters:
;    OBE_TIME           -       An input obe_time for which the time offset is to be obtained.
;
; Output:
;    DELTA_ERROR        -       A two element string array.
;
; RETURN VALUE:
;    DT                 -       A two element long array containing the time offset as
;                               delta_mjd and delta_ms.
;
; Keywords:
;    CORRECTION_STRING	-	Used to return an ASCII string with the
;				time difference.
;    VERBOSE            -       If set, print out time selection info.
;
; Calling Sequence:
;    dt = TIME_CORRECTION(obe_time, delta_error, CORRECTION_STRING = CORRECTION_STRING, /VERBOSE)
; 
; Restrictions:
;    If large jumps in the difference occur between realtime contacts, this
;	routine could return inaccurate values.
;
; History:
;    1997 April 17  - D.M. fecit.
;    1997 August 27 - Added CORRECTION_STRING keyword		D.M. fecit.
;    1999 Feb 7     - Added binary search and indexing to speed finding
;                     the right record, created unix version for Solaris -  DW
;    2002 Jul 10    - Added DELTA_ERROR parameter                        -  Ed Esfandiari
;    2002 Jul 10    - Also added a true binary search                    -  Ed Esfandiari
;    2003 Mar 11    - Add REDUCE_HISTORY common block; 
;			change datafile calls; delta_error=N/A for c2_offsets - NRich
;    2004 Sep 15 - Change OS_version check to 'endian-ness' check, since
;			not all unix platforns are necessarily big-endian - GR Lawrence
;    2007 Sep 26 =  Modified to use vms time_diff.dat file, TIME_DIFF.DAT_vms, through
;                   2007-02-08T14:52:52.944 and unix time_diff.dat file, TIME_DIFF.DAT,
;                   after that. The unix version has newer offsets appended to vms records
;                   with no byte-swap.
;   2010.09.16, nbr - renamed c2*.sav files
;   2010.11.04, nbr - Added common las_time_correction (applies only if DATE-OBS before 1997/12/31)
;   	    	    Added file_date_mod for TIME_DIFF.DAT in version=cmnver
;   2010.11.16, nbr - Bug fix
;   2012.03.05, nbr - In late 2011 the endianness of computer where TIME_DIFF.DAT is stored changed, 
;   	    	    thus changing the file. Also discontinued use of TIME_DIFF.DAT_vms for earlier dates.
;
; @(#)time_correction.pro	1.12 11/29/12  NRL IDL LIBRARY
;  W   H
;-
; swap words and bytes 
; VMS data base -> Sun Solaris
; 12345678  -> 7856 3412
function word_swap,long_int
b1 = long_int and 'FF000000'XL
b1 = b1 / '1000000'XL
b1 = b1 and 'FF'XL
b2 = long_int and '00FF0000'XL
b2 = b2 / '100'XL
b3 = long_int and '0000FF00'XL
b3 = b3 * '100'XL
b4 = long_int and '000000FF'XL
b4 = b4 * '1000000'XL
;print,b1,b2,b3,b4,format='(4z10)'
new = b1+b2+b3+b4

return,new
end


pro convert_time,time_unit,rec_num,new_w, newer, VERBOSE=verbose

obe_time ='1998/6/1 10:58:10'
image_time = anytim2utc(obe_time) 
;help,time_unit,rec_num,new_w

;print,'rec_num= ',rec_num

;;  Mods GRL 14/09/2004 to check 'endian-ness' rather than OS family to see
;;  whether word_swap should be run. Solves specific issue with x86/Linux
;;  platforms, which are little-endian - as is VMS, hence use original code)

;endi=''
;j=1 & byteorder, j,/swap_if_big_endian				;; GRL 14/09/2004
;if j EQ 1 THEN endi = 'little' else endi = 'big'			;; GRL 14/09/2004
;
;help,endi
;
;endi = 'little'  ; AEE 06/11/07
;
;help,endi

wl = assoc(time_unit, lonarr(4))
wl_0 = wl(0)

;help,wl,wl_0
;stop

;; if (!VERSION.OS_FAMILY eq 'unix') then rec = word_swap(wl_0(0)) $
;;  else rec = word_swap(wl_0(0))
;if (endi EQ 'big') then rec = word_swap(wl_0(0))  else rec =wl_0(0)	;; GRL 14/09/2004

;rec = swap_endian(wl_0(0),/SWAP_IF_BIG_ENDIAN)

;IF (unix_file) THEN BEGIN 
;  ; unix time_diff.dat file is big_endian. Swap if running on a little_endian machine
;  rec = swap_endian(wl_0(0),/SWAP_IF_LITTLE_ENDIAN)
;ENDIF ELSE BEGIN ; vms time_diff.dat file
;  ; vms time_diff.dat file is litte-endian. Swap if running on a big_endian machine
;  rec = swap_endian(wl_0(0),/SWAP_IF_BIG_ENDIAN)
;ENDELSE

;First part of unix time_diff.dat file is the same as vms time_diff.dat file
;and are both vms generated little_endians. Only later parts of unix time_diff
;file is unix generated and is big_endian. So, to check for record of file to
;get total # or records, must only swap the bytes if running on a unix (big_endian) machine:

rec = swap_endian(wl_0(0),/SWAP_IF_BIG_ENDIAN)
IF keyword_set(VERBOSE) THEN help,rec

;print,'Number of Records',rec,' Finding Rec ',rec_num

this_time = [image_time, image_time]
w = assoc(time_unit, this_time)

if(rec_num lt 0) then rec_num = rec

if(rec_num le rec) then begin
 new_w = w(rec_num)
 ;if(rec_num ne rec) then begin

; handle vax/unix boundry:
; don't use few records at start of new unix format with dates before last vax record
; (313887) so binary search does not get confused:

;if (rec_num gt 313887L and rec_num lt 313893L) then begin
;  print,'Changed ren_num= ', rec_num, 'to 313894'
;  rec_num= 313894L
;endif


; if(rec_num le 313887L) then begin
;   ; new time_diff.dat file seems to have wrong byte-order (up to rec 313887)
;   ; and requires a byte-swap:
;   print,' *** byte swaped ***' 
;   w_rec = swap_endian(w_rec,/SWAP_IF_BIG_ENDIAN)
;   new_w = swap_endian(new_w,/SWAP_IF_BIG_ENDIAN)
; end

; In late 2011, soc started storing data on new computer. This reversed the endianness of the
; time_diff.dat file.

IF keyword_set(VERBOSE) THEN print,'new_w=',new_w

 IF (newer) THEN BEGIN 
   new_w = swap_endian(new_w,/SWAP_IF_BIG_ENDIAN)
 ENDIF ELSE BEGIN 
   new_w = swap_endian(new_w,/SWAP_IF_LITTLE_ENDIAN)
 ENDELSE

;help,/st,w_rec,new_w
IF keyword_set(VERBOSE) THEN print,'new_w=',new_w
;stop
 
;if (endi EQ 'big') then begin					;; GRL 14/09/2004
;;; if (!VERSION.OS_FAMILY eq 'unix') then begin
; new_w(0).mjd = word_swap(w_rec(0).mjd)  
; new_w(0).time = word_swap(w_rec(0).time)  
; new_w(1).mjd = word_swap(w_rec(1).mjd)  
; new_w(1).time = word_swap(w_rec(1).time)  
;;print,new_w(0).mjd,new_w(0).time
;;print,new_w(1).mjd,new_w(1).time
;endif else begin
; new_w(0).mjd = w_rec(0).mjd
; new_w(0).time = w_rec(0).time  
; new_w(1).mjd = w_rec(1).mjd  
; new_w(1).time = w_rec(1).time  
;endelse
endif
end



FUNCTION MODIFIED_BINARY_SEARCH,img_time,time_unit,unix_file,before=before

  ;n= N_ELEMENTS(list)

  n= -1
  
  ;convert_time,time_unit,n,rec     ;n=-1 is set to n= # of records and also rec = last_record is returned
  convert_time,time_unit,n,rec,unix_file     ;n=-1 is set to n= # of records and also rec = last_record is returned
  
  ;print,'num_records= ',n

  v = img_time.mjd*8.64d4 + 1.e-3*img_time.time

  ;b= 0
  ;t= n-1

  b=1 ; since index 0, w(0), is the first line containg the record numbers n.
  if unix_file then begin
    ;b= 353615
    b= 320000  ; start index in unix file search
  endif
  t= n
 
  s_ind= -1 
  found= 0

  WHILE ((t GE b) AND (NOT found)) DO BEGIN 
    m= (t+b)/2
    convert_time,time_unit,m,mrec, unix_file 
    mrec= mrec(0).mjd*8.64d4 + 1.e-3*mrec(0).time
    IF (mrec EQ v) THEN BEGIN 
      found= -1
      s_ind= m
    ENDIF ELSE BEGIN 
      IF (v GT mrec) THEN $ 
        b= m + 1             $
      ELSE                   $ 
        t= m - 1
    ENDELSE 
  ENDWHILE 

;  print,'t,b,m= ',t,b,m
;  print,'bin_ind= ',s_ind

  IF (KEYWORD_SET(before) AND (NOT found)) THEN s_ind= t

;  print,'returned_ind= ',s_ind
;stop

  RETURN,s_ind

END


FUNCTION TIME_CORRECTION, obe_time, delta_error, correction_string = correction_string,verbose=verbose
;
COMMON reduce_history, version, prev_a, prev_hdr, zblocks0
common las_time_correction, c2_offsets, c2_utc_dates, c2_dates, c2datafile
; NOTE: this common block only applies where date-obs before 1997/12/30
 
version = strarr(2)
version[0] = '@(#)time_correction.pro	1.10 07/26/11' ;  NRL IDL LIBRARY

image_time = anytim2utc(obe_time) 

; July 22, 02: ;AEE
; Jeff Newmark has not added C2 data through '1997/09/03 07:28:00.000' (previous c2 image that
; was processed by star program is for '1997/08/29 18:27:29.462') to the EIT TIME_DIFF.DAT
; so, I will read them from C2, instead:

obe_ecs= anytim2utc(obe_time,/ecs)
IF (KEYWORD_SET(verbose)) THEN print,'Input obe time = ',obe_ecs 

IF datatype(c2datafile) EQ 'UND' THEN c2datafile=''

IF (obe_ecs LT '1997/09/03 07:28:00.000' OR                                          $
    obe_ecs GE '1997/10/19 18:28:29.682' AND obe_ecs LE '1997/10/27 22:41:37.680' OR $
    obe_ecs GE '1997/12/06 00:27.37.672' AND obe_ecs LE '1997/12/30 20:23:22.848'    ) THEN BEGIN
;
; Use C2 offsets
;
 ;path = getenv('NRL_LIB')+'/lasco/data/calib/'
 IF (obe_ecs LT '1997/09/03 07:28:00.000') THEN $
   datafile='c2_012496t1544_082997t1827_timeoffsets.sav'
 IF (obe_ecs GE '1997/10/19 18:28:29.682' AND obe_ecs LE '1997/10/27 22:41:37.680') THEN $
   datafile='c2_101997t1828_102797t2241_timeoffsets.sav'
 IF (obe_ecs GE '1997/12/06 00:27.37.672' AND obe_ecs LE '1997/12/30 20:23:22.848') THEN $
   datafile='c2_120697t0027_123097t2023_timeoffsets.sav'

    IF c2datafile NE datafile THEN BEGIN

	c2datafile=datafile   
	restore,filepath(datafile,ROOT_DIR=getenv('NRL_LIB'),SUBDIR=['idl','data','calib'])

	;save files contain C2_OFFSETS, C2_UTC_DATES, C2_DATES ( str in /ecs format)

	; extend first and last values:

	nelem= n_elements(C2_UTC_DATES)

	lutc= tai2utc(utc2tai(c2_utc_dates(nelem-1))+60.0) ; ; add 60 sec to the last time.
	ldate=anytim2utc(lutc,/ecs)

	C2_DATES=[C2_DATES(0),C2_DATES,ldate]
	C2_OFFSETS=[C2_OFFSETS(0),C2_OFFSETS,C2_OFFSETS(nelem-1)]
	C2_UTC_DATES=[C2_UTC_DATES(0),C2_UTC_DATES,C2_UTC_DATES(0)]
	nelem= n_elements(C2_UTC_DATES)
	C2_UTC_DATES(nelem-1).mjd= lutc.mjd
	C2_UTC_DATES(nelem-1).time= lutc.time 

    ENDIF
  ; Return offset for the time less than or equal to image_time and also a a 2 element delta array
  ; to match the stuff for the times ge '1997/09/03 07:28:00.000'.  

    nelem= n_elements(C2_UTC_DATES)
  list= where(c2_dates le anytim2utc(obe_time,/ecs), cnt)
  delta_error= ['N/A','N/A']
if(cnt lt 1) then begin
    print,''
    print,'Warning - image_time is outside the range of the C2 time_file.'
    print,'          image_time = '+anytim2utc(obe_time,/ecs)
    print,'          time_file range= '+c2_dates(0)+' - '+c2_dates(n_elements(c2_dates)-2)
    print,'          Returning 0 offset.'
    print,''
    correction_string = 'image_time is outside the range of the time_file.'
    RETURN,[0L,0L]
  endif
 
  cnt1= cnt
  cnt = cnt-1 
  delta_time= c2_offsets(cnt)
  if(cnt1 ge nelem) then cnt1= cnt 
  delta_time_2= (c2_offsets(cnt1) - delta_time) > (-15)
  ;delta_error = string([-15,delta_time_2 > 15]) ; AEE added; NBR removed
  delta_time_m = fix(delta_time/60) & delta_time_s = delta_time mod 60
  delta_time_m = strtrim(delta_time_m, 2)
  delta_time_s = string(delta_time_s, format = '$(f7.3)')
  delta_time_s = strtrim(delta_time_s, 2)
  if delta_time gt 15 then begin
     correction_string = 'OBE is running ahead of LOBT by ' + delta_time_m + $
        ' m ' + delta_time_s + ' s.'
  endif else begin
     correction_string = 'OBE is within 15 s of LOBT.'
  end
 
  if(keyword_set(verbose)) then begin
    print,''
    print,'Using C2 offsets from C2 file (not TIME_DIFF.DAT):'
    print,'num_records= ',n_elements(C2_DATES)
    print,'record_ind= ',cnt
    print,'image_time= ',anytim2utc(obe_time,/ecs)
    print,'prev_time & offset= ',c2_dates(cnt), c2_offsets(cnt)
    print,'next_time & offset= ',c2_dates(cnt1), c2_offsets(cnt1)
    print,correction_string
;help,cnt,cnt1
;stop
  end
  
  version[0] = version[0]+': using median-filtered star values from'
  version[1] = datafile
  
  RETURN,[0L,long(c2_offsets(cnt)*1000)]
ENDIF ; EIT gaps, using star median values

;
;print,image_time.mjd,image_time.time
;
current_record = image_time.mjd*8.64d4 + 1.e-3*image_time.time
;print, '%TIME_DIFFERENCE-D-CURRENT, current_record = ' + $
;   strtrim(current_record, 2)
;
; The TIME_DIFF.DAT is provided by EIT and is a VMS data file
; 1st record contains number of records
; succeeding records are data records with 2 time records of 2 long ints each
; in CDS time format (mjd and time in millisecs)
;
;path = getenv('NRL_LIB')+'/lasco/data/calib/'
;datafile='TIME_DIFF.DAT'
;datafile='TIME_DIFF.DAT_unix'
;datafile='TIME_DIFF.DAT'

;print,'obe_ecs= '+obe_ecs

;IF (obe_ecs LE '2007/02/08 14:52:52.944') THEN BEGIN ; last record in vms file
IF obe_ecs LT '2005/12/01 04:43:26.900' THEN BEGIN
  unix_file= 0 
  ;datafile='TIME_DIFF.DAT_vms' 
ENDIF ELSE BEGIN
  unix_file= 1 
  ;datafile='TIME_DIFF.DAT_unix'
  ;datafile='TIME_DIFF.DAT'
ENDELSE
datafile='TIME_DIFF.DAT'

rdfile = FILEPATH(datafile,ROOT_DIR=getenv('NRL_LIB'),SUBDIR=['idl','data','calib'])
;rdfile = '~/idl/sandbox/lasco/time_diff.dat.120102'

if(keyword_set(verbose)) then message,'Using '+datafile,/info

version[1] = datafile + ' '+utc2str(tai2utc(file_date_mod(rdfile)),/date)

openr, time_unit, rdfile, /get_lun 
;
num_recs= -1  ; to read first line of file containing number of records to follow
                  ; and also return the last record in last_rec and number of records
                  ; in num_recs 
convert_time,time_unit,num_recs,last_rec,unix_file,verbose=verbose

rec_ind= MODIFIED_BINARY_SEARCH(image_time,time_unit,unix_file,/before)

;help,image_time
;if (utc2str(image_time) gt '2005-12-23T16:53:10.000' and
;    utc2str(image_time) lt '2005-12-27T20:58:14.000') then begin
;  rec_ind= 313887L 
;endif else begin
;  rec_ind= MODIFIED_BINARY_SEARCH(image_time,time_unit,/before)
;endelse

if (rec_ind lt 1 or rec_ind eq num_recs) then begin
  convert_time,time_unit,1,rec1, 0,verbose=verbose
  print,''
  print,rec1[0]
  print,last_rec[0]
  print,'Warning - image_time is outside the range of the time_file.'
  print,'          image_time = '+utc2str(image_time)
  print,'          time_file range= '+utc2str(rec1(0))+' - '+utc2str(last_rec(0))
  print,'          Returning 0 offset.'
  print,''
  correction_string = 'image_time is outside the range of the time_file.'
  delta_error= ['N/A','N/A']
  wait,2
  free_lun, time_unit
  RETURN,[0L,0L]
endif


IF keyword_set(VERBOSE) THEN message,'convert_time rec_ind:',/info
convert_time,time_unit,rec_ind,last_rec, unix_file,verbose=verbose

; handle vax/unix boundry:
;if (last_rec(0).mjd gt image_time.mjd) then begin
;  convert_time,time_unit,313887L,last_rec, unix_file
;  rec_ind= 313893L
;endif


delta_mjd = last_rec(0).mjd - last_rec(1).mjd
delta_ms = last_rec(0).time - last_rec(1).time
;
; JSN added
;next_rec = w(rec+1)
IF keyword_set(VERBOSE) THEN message,'convert_time next value:',/info
convert_time,time_unit,rec_ind+1,next_rec, unix_file,verbose=verbose

delta_mjd_2 = next_rec(0).mjd - next_rec(1).mjd - delta_mjd
delta_ms_2 = next_rec(0).time - next_rec(1).time - delta_ms
;
delta_time = delta_mjd/86400. + 1.e-3*delta_ms
;
; JSN added
delta_time_2 = delta_mjd_2/86400. + 1.e-3*delta_ms_2 > (-15)
;error = [-15,max(delta_time_2,15)]
delta_error = string([-15,delta_time_2 > 15]) ; AEE added

if(keyword_set(verbose)) then begin
  print,'num_records= ',num_recs
  print,'record_ind= ',rec_ind
  print,'image_time= ',utc2str(image_time)
;help,image_time,last_rec(0),delta_time
;stop
  print,'prev_time & offset = ',utc2str(last_rec(0)), delta_time
  print,'next_time & offset= ',utc2str(next_rec(0)), (next_rec(0).mjd - next_rec(1).mjd)/86400. + $
                                                     1.e-3*(next_rec(0).time - next_rec(1).time)
;help,rec_ind
;stop
end

;
delta_time_m = fix(delta_time/60) & delta_time_s = delta_time mod 60
delta_time_m = strtrim(delta_time_m, 2)
delta_time_s = string(delta_time_s, format = '$(f7.3)')
delta_time_s = strtrim(delta_time_s, 2)
;
; So far, all deltas have been positive, so treat larger negative deltas
; as bogus data.
;
;if (delta_time lt (-15) then begin
if (delta_time lt (-15) or delta_time gt 500) then begin ; AEE added
   delta_time = 0.0
   delta_mjd = 0l & delta_ms = 0.0
end
;
; if delta_time lt (-15) then begin
;    correction_string = 'OBE is running behind LOBT by ' + delta_time_m + $
;       ' m ' + delta_time_s + ' s.'
; endif else
if delta_time gt 15 then begin
   correction_string = 'OBE is running ahead of LOBT by ' + delta_time_m + $
      ' m ' + delta_time_s + ' s.'
endif else begin
   correction_string = 'OBE is within 15 s of LOBT.'
end
;
; print, anytim2utc(last_rec(0), /ecs), '	', anytim2utc(last_rec(1), /ecs)
;
close, time_unit & free_lun, time_unit


return, [delta_mjd, delta_ms]

end


