;;+
;PROCEDURE:   mvn_lpw_anc_clocks_spice
;PURPOSE:
;  Routine takes MAVEN s/c clock time in mvn_lpw_pkt routines and uses SPICE
;    to determine correct start / end times of each dataset.
;  
;USAGE:
;  mvn_lpw_anc_clocks_spice, sclk_in1, sclk_in2,clock_field_str,clock_start_t,clock_end_t,spice,spice_used,str_xtitle,kernel_version,unix_time
;
;INPUTS:
;  Times must be in the correct MAVEN format ie 0123456789.12345. See MAVEN sclk SPICE kernels
;  for more info (http://naif.jpl.nasa.gov/naif/data_mars.html).
;       sclk_in1: s/c clock main seconds in - the time to be SPICE corrected. Must be a long, float, double or array of these types.
;       sclk_in2: s/c clock fraction of seconds in. Must be a long, float, double or array of these types.
;
;
;OUTPUTS:
;            clock_field_str  what clock_start_t /clock_end_t    contain in text 
;            clock_start_t     first time point of the array   < this is now a number not an string
;            clock_end_t      last  time point of the array < this is now a number not an string
;            
;            spice            newly added; either defined and then contain the directory of the kernel or undefined            
;            spice_used       text out
;            str_xtitle       text out
;            kernel_version   text out
;            unix_time       this is the full time arry in unix time
;            
;KEYWORDS:
;Set /clear_kernels to clear SPICE kernels from IDL memory once run. DO NOT set this when processing L0 data, as kernels must then be looked up from NAIF for each pkt variable.
;
;Example:
; time = mvn_lpw_pkt_clocks_spice([0123456789], [12345]) ;for MET time of 0123456789.12345
; "time" will be a string array containing the outputs. 
;
;
;CREATED BY:   Chris Fowler on Feb 19th 2014
;FILE: mvn_lpw_anc_clocks_spice.pro
;VERSION:   2.0
;LAST MODIFICATION:   
;04/25/14 L. Andersson change it from being a function to an procedure, changed the time from string to double, 
;              moved all information into this routine so that it is not spread out in other routines.
;               spice is presently used to carry the kernel_directory, later on this can be turn into a 'yes' 
;              when routines exsits to automatically find the directory.
;
;04/29/2014 CF: added automated kernel loading added. Also checks to see if times are predicted or reconstructed. 
;;140718 clean up for check out L. Andersson
;2015-10-08 CMF made clearing SPICE kernels a keyword.
;2019-08-20 CMF commented out the call to timespan, as this doesn't appear to be necessary.
;
;-




pro mvn_lpw_anc_clocks_spice, sclk_in1, sclk_in2,clock_field_str,clock_start_t,clock_end_t,spice,spice_used,str_xtitle,kernel_version,unix_time2, clear_kernels=clear_kernels

;------------------------------------------------
          spice_used = 'SPICE used'
          str_xtitle = 'Time (UNIX)'   ;we add on constructed or reconstructed at the end as well
          kernel_version = 'anc_clocks_spice_ver V2.0'
;------------------------------------------------

Input_info_correct=1
sl = path_sep()  ;/ for unix, \ for Windows
;======================
;Make sure two numbers have been entered for sclk_in1 and sclk_in2:
IF size(sclk_in1, /type) NE 3 AND size(sclk_in1, /type) NE 4 AND size(sclk_in1, /type) NE 5 THEN BEGIN
      print, "############################"
      print, "Spacecraft -seconds- clock entered is not in the correct format (float or double precision number)." 
      print, "For MAVEN, spacecraft clock is of the format 0123456789.12345."
      print, "-second- clock: 0123456789."
      print, "-subsecond- clock: .12345"
      print, "Check sclk_in1 and sclk_in2 are in correct format before being input into this routine."
      print, "############################"
      Input_info_correct=0
ENDIF
IF size(sclk_in2, /type) NE 3 AND size(sclk_in2, /type) NE 4 AND size(sclk_in2, /type) NE 5 THEN BEGIN
      print, "############################"
      print, "Spacecraft -subsecond- clock entered is not in the correct format (float or double precision number)." 
      print, "For MAVEN, spacecraft clock is of the format 0123456789.12345."
      print, "-second- clock: 0123456789."
      print, "-subsecond- clock: .12345"
      print, "Check sclk_in1 and sclk_in2 are in correct format before being input into this routine."
      print, "############################"
     Input_info_correct=0
ENDIF

IF Input_info_correct EQ 1 then begin

;Combine 
ssclk_in1 = string(sclk_in1, format='(F16.5)')  ;if we have double values:
;Combine subseconds to main seconds. Subseconds can only go up to .65535, so have to be carefull BECAUSE subseconds come in as 12345, not a fraction. So
;14.0 is actually 0.00014 when joining to sclk_in1:

;     The on-board clock, the conversion for which is provided by this SCLK
;     file, consists of two fields:
;          SSSSSSSSSS.FFFFF
;     where:
;          SSSSSSSSSS -- count of on-board seconds
;          FFFFF      -- count of fractions of a second with one fraction
;                        being 1/65536 of a second; normally this field value
;                        is within 0..65535 range.

sclk_time = double(sclk_in1+(sclk_in2/100000.d))  ;create time in double array
sclk      = string(sclk_time, format='(F16.5)')  ;create time in correct string format for spice

nele_sclk = n_elements(sclk)
;======================

scid = -202  ;MAVEN s/c ID for SPICE

    ;filedir =spice ; '/Users/andersson/Idl/2014_maven/spice/spice_kernels/'  ;base directory for local kernels (need to find an automated way to check for updates)


;==================
;---Load kernels---
;==================
;Code for automatically loading found kernels:
;Get kernel info from tplot variables and load:
tplotnames = tnames()  ;list of tplot variables in memory
if total(strmatch(tplotnames, 'mvn_lpw_load_kernel_files')) eq 1 then begin  ;found kernel tplot variable
    get_data, 'mvn_lpw_load_kernel_files', data=data_kernels, dlimit=dl_kernels  ;dl.kernels contains the kernel names
    nele_kernels = n_elements(dl_kernels.Kernel_files)  ;number of kernels to load
    loaded_clock_kernels = ['']  ;start array
    for aa = 0, nele_kernels-1 do begin
        if (stregex(dl_kernels.Kernel_files[aa], sl+'lsk', /boolean) eq 1) or (stregex(dl_kernels.Kernel_files[aa], sl+'sclk', /boolean) eq 1) then begin   ;#### /\ for windows
            cspice_furnsh, dl_kernels.Kernel_files[aa]  ;load lsk or sclk kernel
            loaded_clock_kernels = [loaded_clock_kernels, dl_kernels.Kernel_files[aa]]
            
            ;Extract just kernel name and remove directory:
            nind = strpos(dl_kernels.Kernel_files[aa], sl, /reverse_search)  ;nind is the indice of the last '/' in the directory before the kernel name
            lenstr = strlen(dl_kernels.Kernel_files[aa])  ;length of the string directory
            kname = strmid(dl_kernels.Kernel_files[aa], nind+1, lenstr-nind)  ;extract just the kernel name                       
            kernel_version = kernel_version + " # " + kname  ;add kernels used to dlimit field
        endif       
    endfor  ;over aa
        if n_elements(loaded_clock_kernels) le 2 then begin  ;we need at least one lsk and one sclk kernel, plus the dummy entry = 3 element array
           print, "#### WARNING ####: No lsk and / or sclk kernels found to load. Check kernels are found and loaded."
           retall
        endif   
endif else begin
      print, "####################"
      print, "WARNING: No SPICE kernels found which match this data set.
      print, "Check there are kernels available online for this data.
      print, "If they are present, check the kernel finder to see if it's finding them.
      print, "####################"
      retall
endelse

;===============================
;--- SSL convert MET to UNIX ---
;===============================
;Use the SSL routine to convert MET to UNIX time, so that we're using the same routine as the PFP team:
;This takes the time as full seconds I believe, so:
;Convert subseconds to "real fractional seconds"
whole = double(sclk_in1)  ;already as main seconds
frac = double(sclk_in2)
frac = frac / ((2.d^16))  ;convert to sub seconds

MET = whole+frac  ;double prec number, seconds into s/c mission (MET)

;Call timespan first to avoid the manual call. Get the input string from tplot:
get_data, 'mvn_lpw_load_file', dlimit=dl

;timespan, dl.utc, 1.  ;use the UTC input string   ;CMF commented out on 2019-08-20 - doesn't seem to be needed anymore as not used by code.
unix_time2 = mvn_spc_met_to_unixtime(MET)  ;default is now to correct for  clockdrift

;===============================


;Ephermeris time: one below using davin's routine
;cspice_scs2e, scid, sclk, et_time  ;et is the converted ephermeris time. This won't work for -ve et_times, I think this is because the routine
                                   ;requires the MAVEN ID and MAVEN times should all be +ve et_times.

;Convert ET to UTC time:
;cspice_et2utc, et_time, 'ISOC', 5, utc_time ;<== number determines how many dp to have in seconds

;For consistency, use Davin's routine to convert unix to UTC time:
utc_time = time_string(unix_time2, precision=5)   ;precision give you dp to have in seconds

;Get ET time using Davin's routine:
et_time = time_ephemeris(utc_time, /ut2et)

utc_time_time=dblarr(nele_sclk)
for i=0L,nele_sclk-1 do begin
   aa= strsplit(utc_time[i],'/',/extract)  ;this is 'T' when using utc times ouput by SPICE
   bb= strsplit(aa[0],'-',/extract)
   cc= strsplit(aa[1],':',/extract)
  utc_time_time[i] =10000000000.0 * double( bb[0]) + 100000000.0 * double(bb[1]) + 1000000.0 * double(bb[2]) + 10000.0 *double(cc[0]) + 100.0 * double(cc[1]) +double(cc[2]) 
endfor  


;Make arrays for different times, append to them in for loop:
jd_time = dblarr(nele_sclk)
;unix_time = dblarr(nele_sclk)
added_ls = dblarr(nele_sclk)

;Load SPICE leapsecond kernels if available:
cspice_dtpool, 'DELTET/DELTA_AT', found1, n, type  ;found=1 if kernel is found, n is the total size of the 2 column array.

IF found1 EQ 1 THEN cspice_gdpool, 'DELTET/DELTA_AT', 0, n, values, found2  ;extract the leapsecs kernel. One column = #, second column = leapsecond date          

;Go through each UTC time and convert to Julian:
FOR bbb = 0L, nele_sclk -1 DO BEGIN
        ;old way to get JD: identical to 3rd dp with spice routine, so good either way, but old way is probably longer
        ;  ;UTC time is given in the format "2013 NOV 09 19:00:46.690", so split up strings based on the characters " :"
        ;  utc_elements = strsplit(utc_time[bbb], "-T:.", /extract)  ;utc_elements is a 6 element array in the format [year, month, day, hour, min, sec.subsec]    
          
        ;  ;Result = JULDAY(Month, Day, Year, Hour, Minute, Second). Convert strings to floats.
        ;  jd_time[bbb] = julday(float(utc_elements[1]), float(utc_elements[2]), float(utc_elements[0]), float(utc_elements[3]), float(utc_elements[4]), float(utc_elements[5]))
          
      jd_time[bbb] = cspice_unitim(et_time[bbb], 'ET', 'JED')  ;convert to JD from ET epoch, using spice
      
      ;Comute UNIX time:
          ;Old way, use Davin's routine below outside of for loop:
          ;  ;First convert the epoch 00:00:00 Jan 1st 1970 to JD date:
          ;  epoch = julday(1,1,1970,0,0,0)
            
          ;  ;Get UNIX time:
          ;  unix_time[bbb] = (jd_time[bbb] - epoch) * 86400.D  ;convert days to secs (after 00:00:00 Jan 1st 1970)
       
      
      ;;Get # of leapseconds passed up to date of interest:
      ;Need to pull out data from the array "DELTET/DELTA_AT" from the LSK kernel:      
 
          IF found2 EQ 1 THEN BEGIN  
              cspice_gdpool, 'DELTET/DELTA_T_A', 0, 1, delta_t_a, found3  ;get delta_t_a from kernel.
              
              IF found3 EQ 1 THEN BEGIN
                  cspice_deltet, et_time[bbb], 'ET', delta_et  ;delta_et is ET offset from UTC 
                  added_ls[bbb] = round(delta_et - delta_t_a)  ;the number of leapsecs added for the current et_time[bbb]             
              ENDIF ELSE BEGIN  ;found3 = 1
                  added_ls[bbb] = -999.  ;if we can't find the kernel values use this error number instead
              ENDELSE
          ENDIF ELSE BEGIN  ;found2 = 1    
              ;If the leapseconds kernel wasn't found:
              added_ls[bbb] = -999.  ;return a float as this will go in a float array.
          ENDELSE
ENDFOR  ;over nele_sclk2

;Get CDF_TT2000 time using CDF routine:
;The Idl routine requires the UTC time to be in this format: 2014-10-10T01:34:05.765, this format is output by cspice_et2utc already, but not by Davin's routines

utc_time_temp = utc_time
for ttt = 0L, n_elements(utc_time)-1 do begin
  dd = strsplit(utc_time[ttt], '/', /extract)  ;break up string based on '/'
  utc_time[ttt] = dd[0]+'T'+dd[1]  ;recombine with new delimeter 'T'
endfor

tt1 = cdf_parse_tt2000(utc_time[0])  ;get first and last times and convert
tt2 = cdf_parse_tt2000(utc_time[nele_sclk-1])


;=======================
;--- Check last time ---
;=======================
;Check that the last timestamp from the data lies inside the reconstructed part of the sclk kernel. If it is outside (predicted) then we
;will need to re-run at a later date to get reconstructed time. This will be noted in the x axis title of the tplot variable.

time_check = mvn_lpw_anc_spice_time_check(et_time[nele_sclk-1])  ;give routine the last time point

;------------
str_xtitle = str_xtitle+' '+time_check  ;add to str_xtitle
;------------

if keyword_set(clear_kernels) then mvn_lpw_anc_clear_spice_kernels ;Clear kernel_verified flag, jmm, 2015-02-11   ;CMF made this a keyword 2015-10-08

;Append values to array:
tt = [[sclk], [utc_time], [string(et_time, format='(F16.5)')], $
     [string(jd_time, format='(F16.5)')], [string(unix_time2, format='(F16.5)')], [strtrim(added_ls,2)]]

;NOTE: using print, format='(g)' will print just the year from UTC times, as '(g)' is for doubles. Just use print - they're all strings.

;the array tt is returned, with the format:
;tt=[[MET (s/c time)], [UTC_time], [ET_time], [jd_time], [unix_time], [leapsecs]]
;where each row is the next clock format.

          clock_field_str = ['mission_elapsed_time (SPICE sclk format)', 'UTC_time (yyyymmddhhmmss.ms)', 'ephermeris_time (ET)', 'julian_date (JD)', 'UNIX_time', 'CDF TT2000 Time', 'leapseconds', time_check[0]]
        
   
   ; change so the clock arrays are double instead
    
          clock_start_t = [sclk_time[0],          utc_time_time[0],            et_time[0],          jd_time[0],          unix_time2[0],       tt1,        added_ls[0]] 
          clock_end_t   = [sclk_time[nele_sclk-1],utc_time_time[nele_sclk-1,0],et_time[nele_sclk-1],jd_time[nele_sclk-1],unix_time2[nele_sclk-1],      tt2,      added_ls[nele_sclk-1]] 
   
endif  ;input data OK     

end
