;+
; PROCEDURE: 
;	MAG_STS_TO_CDF
;
; PURPOSE: 
;	Convert magnetometer .sts to .cdf. 
;
; AUTHOR: 
;	Roberto Livi (rlilvi@ssl.Berkeley.edu)
;
; CALLING SEQUENCE:
;	MAG_STS_TO_CDF,FILENAME=FILENAME
;
; KEYWORDS:
;	FILENAME: String containing .sts filename to be loaded
;
; NOTES:
;      Uses append_array.pro
;
; EXAMPLE:
;        IDL> dir='/directory-to-mag-files/'
;        IDL> file='mvn_mag_l2_2014d106pl_20140416_v00_r00.sts'
;        IDL> mag_sts_to_cdf, dir+file
;         
; HISTORY:
;
; VERSION:
;   $LastChangedBy: jwl $
;   $LastChangedDate: 2014-10-03 15:10:00 -0500 (Fri, 03 Otc 2014)$
;   $LastChangedRevision: 2014-10-03 15:10:00 -0500 (Fri, 03 Otc 2014)$
;   $URL:svn+ssh://thmsvn@ambrosia.ssl.berkeley.edu/repos/spdsoft/projects/general/CDF/mag_sts_to_cdf.pro$
;-


PRO mag_sts_to_cdf, filename


  ;###########################################################################
  ;Check file

  ;-----------------------------------
  ;No file error
  file=file_search(filename)
  if size(file,/type) eq 7 and file[0] eq '' then begin
     print, 'ERROR: File '+filename+' not found/loaded.'
     return
  endif


  

  ;###########################################################################
  ;Read file

  ;-----------------------------------
  ;Generate variables
  obj_num=0
  str_temp1=''
  str_temp2=''
  obj_struc={header:'',kernel_list:'',record:''}
  obj_str=''
  obj_lev=0
  obj_name=tag_names(obj_struc)
  openr, file_unit, file, /get_lun


  ;-----------------------------------
  ;Check if first object is 'file'
  readf, file_unit, str_temp1
  str_temp2=strsplit(str_temp1,'=',/extract)
  if n_elements(str_temp2) ne 2 then begin
     if str_temp2[1] ne 'file' then $
        print, 'ERROR: No file header.' $
     else print, 'ERROR: No object file'
     return
  endif
  obj_num++


  ;-------------------------------------
  ;Read all objects line by line 
  ;and save as strings 
  while obj_num gt 0 do begin
     readf, file_unit, str_temp1
     str_temp1=strtrim(str_temp1,2)
     str_temp2=strsplit(str_temp1,' ',/extract)
     append_array, obj_str, str_temp1
     append_array, obj_lev, obj_num
     if str_temp2[0] eq 'OBJECT' then obj_num++
     if str_temp2[0] eq 'END_OBJECT' then obj_num--
  endwhile





  ;###########################################################################
  ;Parse headers

  ;-----------------------------------
  ;Find object types
  nn=n_elements(obj_str)
  obj_pos=intarr(nn)
  for i=0, nn-1 do begin
     temp1=strpos(STRUPCASE(obj_str[i]),'OBJECT')
     temp2=strpos(STRUPCASE(obj_str[i]),'END_OBJECT')     
     if temp1 ne -1 and temp2 eq -1 then obj_pos[i]=i $
     else obj_pos[i]=-1     
  endfor
  obj_pos=obj_pos(where(obj_pos ne -1,cc_obj))
  obj_type=strarr(cc_obj)
  for i=0., cc_obj-1 do begin
     temp=strsplit(obj_str[obj_pos[i]],'=',/extract)
     obj_type[i]=strtrim(temp[1],2)          
  endfor



  ;-----------------------------------
  ;Find end_object
  nn=n_elements(obj_str)
  endobj_pos=fltarr(nn)
  for i=0., nn-1. do $
     endobj_pos[i]=strpos(STRUPCASE(obj_str[i]),'END_OBJECT')
  endobj_pos=where(endobj_pos ne -1)



  ;-----------------------------------
  ;Read header
  header_lev=obj_lev[obj_pos[where(obj_type eq 'HEADER',nheader)]]
  if nheader eq 0 then begin
     print, 'ERROR: No header object.'
     return
  endif
  pp=where(obj_lev eq header_lev[0])
  header=obj_str[pp[0]:pp[1]-1]
  header_struc={PROGRAM:'',CMD_LINE:'',DATE:'',HOST:'',COMMENT:'', TITLE:''}
  for i=0, n_elements(header)-1 do begin
     temp=strtrim(strsplit(header[i],'=',/extract),2)
     case temp[0] of
        'PROGRAM' :header_struc.program=temp[1]
        'CMD_LINE':header_struc.cmd_line=temp[1]
        'DATE'    :header_struc.date=temp[1]
        'HOST'    :header_struc.host=temp[1]
        'COMMENT' :header_struc.comment=temp[1]
        'TITLE'   :header_struc.title=temp[1]
        else: break
     endcase
  endfor



  ;-----------------------------------
  ;Read scalar info
  sca_pos=where(obj_type eq 'SCALAR',nsca)
  sca_info=replicate({NAME:'NaN',$
                      ALIAS:'NaN',$
                      FORMAT:'NaN',$
                      TYPE:'NaN',$
                      UNITS:'NaN'},nsca)
  for i=0, nsca-1 do begin
     temp=strtrim($
          strsplit($
          obj_str[obj_pos[sca_pos[i]]],'=',/extract),2)
     if n_elements(temp) eq 2 and $
        temp[0] eq 'OBJECT' then begin
        pos=obj_pos[sca_pos[i]]
        pp=0
        while temp[0] ne 'END_OBJECT' do begin           
           case temp[0] of
              'NAME'  : sca_info[i].NAME   = temp[1]
              'ALIAS' : sca_info[i].ALIAS  = temp[1]
              'FORMAT': sca_info[i].FORMAT = temp[1]
              'TYPE'  : sca_info[i].TYPE   = temp[1]
              'UNITS' : sca_info[i].UNITS  = temp[1]
              else: break
           endcase
           pos=pos+1
           temp=strtrim($
                strsplit($
                obj_str[pos],'=',/extract),2)
        endwhile
     endif
  endfor

  
  ;-----------------------------------
  ;Read kernel list
  ker_pos=where(obj_type eq 'KERNEL_LIST',nker)
  kernel_files=''
  temp1=''
  iker=1.
  while temp1[0] ne 'END_OBJECT' do begin
     pos=obj_pos[ker_pos]+iker
     temp1=strtrim(strsplit(obj_str[pos],'=',/extract),2)
     temp2=strtrim(strsplit(temp1[0],' ',/extract),2)
     nn=n_elements(temp2)-1
     tt1=temp2[0]
     tt2=temp2[nn]
     if tt1 ne 'END_OBJECT' then $
        append_array,kernel_files,tt2     
     iker++;=iker+1.
  endwhile


  ;-----------------------------------
  ;Read vectors
  vec_pos=where(obj_type eq 'VECTOR',nvec)
  vec_info=replicate({NAME:'',$
                      ALIAS:'',$
                      FORMAT:'',$
                      TYPE:'',$
                      UNITS:'',$
                      DIM:0,$
                      VAR_TYPE:'',$
                      VAR_NAME:''},nvec)
  vecs=''
  temp=['','']
  for i=0, nvec-1 do begin
     ivec=0     
     pos=obj_pos[vec_pos[i]]+ivec
     temp=strtrim(strsplit(obj_str[pos],'=',/extract),2)
     while temp[0] ne 'END_OBJECT' do begin
        case temp[0] of
           'NAME'  : vec_info[i].NAME   = temp[1]
           'ALIAS' : vec_info[i].ALIAS  = temp[1]
           'FORMAT': vec_info[i].FORMAT = temp[1]
           'TYPE'  : vec_info[i].TYPE   = temp[1]
           'UNITS' : vec_info[i].UNITS  = temp[1]
           else: break
        endcase
        if temp[1] eq 'SCALAR' then begin
           while temp[0] ne 'END_OBJECT' do begin
              pos=obj_pos[vec_pos[i]]+ivec
              temp=strtrim(strsplit(obj_str[pos],'=',/extract),2)
              if temp[0] eq 'NAME' then $
                 vec_info[i].VAR_NAME=vec_info[i].VAR_NAME+temp[1]+' '
              if temp[0] eq 'FORMAT' then begin
                 temp1=strsplit(temp[1],',',/extract)
                 temp1=strmid(temp1[1],0,1)
                 if temp1 eq 'I' then tt='0'
                 if temp1 eq 'F' then tt='0.D'
                 vec_info[i].VAR_TYPE=vec_info[i].VAR_TYPE+tt+' '                 
              endif
              ivec=ivec+1              
           endwhile
        endif
        pos=obj_pos[vec_pos[i]]+ivec
        temp=strtrim(strsplit(obj_str[pos],'=',/extract),2)
        ivec=ivec+1
     endwhile
     ive=ivec+1
     vec_info[i].dim=n_elements($
                     strsplit($
                     vec_info[i].var_name,' ',/extract))
  endfor
  




  ;-----------------------------------
  ;Find first line for formatting  
  str_temp=''
  readf, file_unit, str_temp
  temp=strsplit(str_temp,' ',/extract)
  nn=n_elements(temp)
  var_locs=intarr(nn)
  add_len=0.
  for i=0, nn-1 do begin
     temp1=strpos(str_temp,temp[i])
     tot_len=strlen(str_temp)
     len=strlen(temp[i])
     var_locs[i]=temp1+add_len
     ;The first six columns are time
     ;elements (int), the rest float
     if i gt 6 and temp[i] ge 0 then var_locs[i]=var_locs[i]-1
     str_temp=strmid(str_temp,temp1+len,tot_len)
     add_len=add_len+temp1+len
  endfor



  
  ;-----------------------------------
  ;Read record object
  fieldnames  = sca_info.name
  temp=sca_info.format
  fieldcount=n_elements(temp)
  fieldformat = strarr(2,fieldcount)
  fieldtype=intarr(fieldcount)
  for i=0, nsca-1 do fieldformat[*,i] = strsplit(temp[i],',',/extract)
  fieldformat = strmid(reform(fieldformat[1,*]),0,1)
  ppi=where(fieldformat eq 'I',cci)
  ppf=where(fieldformat eq 'F',ccf)
  if cci ne 0 then fieldtype[ppi]=2
  if ccf ne 0 then fieldtype[ppf]=4
  nvars = n_elements(fieldnames)
  if nvars ne 11 then begin
     print,'ERROR: Format structure changed in .sts file'
     return
  endif
  index=n_elements(endobj_pos)-1
  template={$
           VERSION:1.0,$
           DATASTART:endobj_pos[index]+2L,$
           DELIMITER:byte(32),$
           MISSINGVALUE:!VALUES.F_NAN,$
           COMMENTSYMBOL:'',$
           FIELDCOUNT:fieldcount,$
           FIELDTYPES:fieldtype,$
           FIELDNAMES:fieldnames,$
           FIELDLOCATIONS:var_locs,$
           FIELDGROUPS:indgen(fieldcount)}
  data_asc=read_ascii(file,template=template)
  nvals=n_elements(data_asc.year)




  ;-----------------------------------
  ;Convert time to unix time
  time_unix = replicate(time_struct(0D), n_elements(data_asc.year))
  time_unix.year = data_asc.year
  time_unix.doy = data_asc.doy
  time_unix.hour = data_asc.hour
  time_unix.min = data_asc.min
  time_unix.sec = data_asc.sec
  time_unix.fsec = double(data_asc.msec)/1000D
  doy_to_month_date, data_asc.year, data_asc.doy, month, date
  time_unix.month = month
  time_unix.date = date
  time_unix = time_double(time_unix)



  ;-----------------------------------
  ;Find frame from filename
  sts_pos=strpos(file,'.sts')
  tn=['pl','ss','pc']
  temp=[strpos(strmid(file,0,sts_pos[0]),tn[0]),$
        strpos(strmid(file,0,sts_pos[0]),tn[1]),$
        strpos(strmid(file,0,sts_pos[0]),tn[2])]
  pp=where(temp ne -1,cc)
  if cc eq 0 or cc gt 1 then begin
     print, 'ERROR: No frame designation '+$
            '(pl,ss,pc) identified'
     return
  endif
  frame=tn[pp[0]]
  str_element, data_asc, 'frame', frame, /add 


  ;-----------------------------------
  ;Create structures and arrays
  for i=0, nvec-1 do begin
     cmd=''
     temp1=strsplit(vec_info[i].var_name,' ',/extract)
     temp2=strsplit(vec_info[i].var_type,' ',/extract)     
     nn=n_elements(temp1)
     for ii=0, nn-1 do append_array,cmd,temp1[ii]+':data_asc.'+temp1[ii]        
     tt1=execute(vec_info[i].name+'={'+strjoin(cmd,',')+'}')
     vec=strlowcase(vec_info[i].name)
     tt2=execute("str_element, data, '"+vec+"',"+vec+",/add") 
  endfor
  str_element, data, 'time_unix',/add 
  str_element, data, 'frame', frame, /add
  str_element, data, 'header_full', obj_str, /add  
  str_element, data, 'header_info', header_struc, /add  
  str_element, data, 'scalar_info', sca_info, /add  
  str_element, data, 'vector_info', vec_info, /add  
  str_element, data, 'spice_kernels', kernel_files, /add    





  ;###########################################################################
  ;Write to CDF


  ;--------------------
  ;Create cdf 
  sts_pos=strpos(file,'.sts')
  cdf_filename=strmid(file,0,sts_pos[0])+'.cdf'
  fileid = cdf_create(cdf_filename,$
                      /single_file,$
                      /network_encoding,$
                      /clobber)

  ;---------------------------------------
  ;Create cdf header and add information
  id0  = cdf_attcreate(fileid,'DATE',        /global_scope)
  id1  = cdf_attcreate(fileid,'HOST',        /global_scope)
  id2  = cdf_attcreate(fileid,'TITLE',       /global_scope)
  id3  = cdf_attcreate(fileid,'FRAME',       /global_scope)
  id4  = cdf_attcreate(fileid,'PROGRAM',     /global_scope)
  id5  = cdf_attcreate(fileid,'COMMENT',     /global_scope)
  id6  = cdf_attcreate(fileid,'CMD_LINE',    /global_scope)
  id7  = cdf_attcreate(fileid,'KERNEL_FILES',/global_scope)

  cdf_attput,fileid,'DATE',0,header_struc.date
  cdf_attput,fileid,'HOST',0,header_struc.host
  cdf_attput,fileid,'TITLE',0,header_struc.title
  cdf_attput,fileid,'FRAME',0,frame
  cdf_attput,fileid,'PROGRAM',0,header_struc.program
  cdf_attput,fileid,'COMMENT',0,header_struc.comment
  cdf_attput,fileid,'CMD_LINE',0,header_struc.cmd_line
  cdf_attput,fileid,'KERNEL_FILES',0,strjoin(kernel_files,',')

  ;--------------------
  ;Attributes
  dummy = cdf_attcreate(fileid,'OBJECT',/variable_scope)
  dummy = cdf_attcreate(fileid,'NAME',/variable_scope)
  dummy = cdf_attcreate(fileid,'ALIAS',/variable_scope)
  dummy = cdf_attcreate(fileid,'FORMAT',/variable_scope)
  dummy = cdf_attcreate(fileid,'TYPE',/variable_scope)
  dummy = cdf_attcreate(fileid,'UNITS',/variable_scope)

  ;--------------------
  ;Insert Variables
  nn=n_elements(sca_info)
  for i=0., nn-1 do begin
     if fieldtype[i] eq 2 then $
        varid = cdf_varcreate(fileid,sca_info[i].name, /CDF_INT2  ,/ZVARIABLE)
     if fieldtype[i] eq 4 then $
        varid = cdf_varcreate(fileid,sca_info[i].name, /CDF_DOUBLE,/ZVARIABLE)
     cdf_attput,fileid,'OBJECT',varid,'SCALAR'          ,/ZVARIABLE
     cdf_attput,fileid,'NAME'  ,varid,sca_info[i].name  ,/ZVARIABLE
     cdf_attput,fileid,'ALIAS' ,varid,sca_info[i].alias ,/ZVARIABLE
     cdf_attput,fileid,'FORMAT',varid,sca_info[i].format,/ZVARIABLE
     cdf_attput,fileid,'TYPE'  ,varid,sca_info[i].type  ,/ZVARIABLE
     cdf_attput,fileid,'UNITS' ,varid,sca_info[i].units ,/ZVARIABLE
     tt=execute('cdf_varput,fileid,sca_info[i].name,data_asc.'+$
                sca_info[i].name)
  endfor
  cdf_close,fileid
  


  ;----------------------------
  ;Create IDL .sav  
  save, filename=strmid(file,0,sts_pos[0])+'.sav', data



end

