
pro get_sot_errors, sttim, entim, n_days_lookback=n_days_lookback, info_new=info_new, $
  err_code=err_code, err_num_hex=err_num_hex, err_num_dec=err_num_dec, err_comment=err_comment, $
  do_fake=do_fake, err_fake=err_fake, $
  uniq_vals=uniq_vals, help=help, do_print=do_print, do_write=do_write, debug=debug

; TODO: Handle fpp_err_count rollovers

if exist(n_days_lookback) then begin
   entim = anytim(ut_time(!stime), /ccsds)
   sttim = anytim(anytim(entim) - n_days_lookback*86400l, /ccsds)
endif else begin
   n_days_lookback = ceil((anytim(entim) - anytim(sttim))/86400l)
endelse

if ~exist(dir_sot_err_db) then $
   dir_sot_err_db = '$SSW/hinode/sot/idl/monitoring/sot_error_genxcat'
;  dir_sot_err_db = '/net/topaz/Users/slater/data/sot_genxcat_minime_sot_errors'

if ~exist(outdir_errlist) then $
   outdir_errlist = get_logenv('FPP_ERROR_ARCHIVE')
if not exist(outfil_errlist) then $
   outfil_errlist = concat_dir('/archive1/hinode/sot/sot_errors', $
                                          'error_list_last_' + string(n_days_lookback, format='$(i3.3)') + '_days.txt')
;  outfil_errlist = concat_dir(get_logenv('FPP_ERROR_ARCHIVE'), $
;                                         'error_list_last_' + string(n_days_lookback, format='$(i3.3)') + '_days.txt')

if ~exist(dt_break) then dt_break = 10*60d ; 10 miniute default

no_error_arr = [' No errors found in this time interval', $
                ' No non-roll-over changes in error count found.', $
                ' No changes in error count found.', $
                ' No new data found.']

;data = sag_get_mnem(sttim, entim, ['fpp_err_code','fpp_err_count'])

; Read sot error structure from geny error database files covering specified time interval:
if ~keyword_set(no_initialize) then initialize = 1
read_genxcat, sttim, entim, err_struct, topdir=dir_sot_err_db, $
              count=count, status=status, initialize=initialize

n_err_tot = count

if (count gt 0) then begin

;  Date      Time      Cnt  Err  Num OpCod Sys  DMA  Addr  SeqID
;  17-MAR-08 09:11:59  229  8074 162 34c3       107  6ac   135d

;  IDL> help, err_struct, /str                                                                                      
;  TIME            LONG           3940000
;  DAY             LONG             13552
;  ERR_NAME        STRING    'SP_OUTPUT_TOUT_ERR'
;  ERR_NUM_HEX     STRING    '00008222'
;  ERR_NUM_DEC     LONG             33314
;  ERR_MESS        STRING    'waiting for previous SP output'

;  Missing: error count, extracted corresponding timeline lines, ted comments

   len_err_name_max = max(strlen(strtrim(err_struct.err_name,2)))
;  t_err = anytim({msec:err_struct.time, d79:err_struct.day}, /ccsds)
   t_err = anytim(err_struct, /ccsds)
   t_sec_err = anytim(t_err)

   err_info_arr =  strmid(anytim(t_err, /ecs), 0, 19)  + '  ' + string(err_struct.err_num_dec, '$(i5.5)') + '  ' + $
                   string(err_struct.err_name, format='$(a-' + strtrim(len_err_name_max,2) + ')') + '  ' + $
                   err_struct.err_mess

endif else begin
;  no_error_hdr = ['================================', $
;                  no_error_arr[0] + string(n_days_lookback, format='$(i3.3)') + ' DAYS', $
;                  '================================', '']
   err_info_arr =  no_error_arr[0]

endelse

if keyword_set(do_fake) then $
   err_info_arr =  [err_info_arr, $
                    strmid(anytim(ut_time(), /ecs), 0, 19)  + '  ' + '99999  FAKE_ERROR']

if n_err_tot gt 0 then begin
;  ss_uniq = ssw_uniq_modes(, ['obstitle', 'target'], /interactive)
   err_uniq_arr = all_vals(err_struct.err_num_dec)
   n_err_uniq = n_elements(err_uniq_arr)

   for i=0, n_err_uniq-1 do begin
      ss_err_occur = where(err_struct.err_num_dec eq err_uniq_arr[i], n_occur)
      err_struct_occur = err_struct[ss_err_occur]
      err_info_occur = err_info_arr[ss_err_occur]
      t_err_occur = t_err[ss_err_occur]
      t_sec_err_occur = t_sec_err[ss_err_occur]

; Time sort occurrences of this error:
      ss_sort = sort(t_sec_err_occur)
      t_err_occur = t_err_occur[ss_sort]
      t_sec_err_occur = t_sec_err_occur[ss_sort]
      err_struct_occur = err_struct_occur[ss_sort]
      err_info_occur = err_info_occur[ss_sort]

      dt_err_occur = t_sec_err_occur[1:*] - t_sec_err_occur[0:(n_occur-2)]
      ss_no_break = where(dt_err_occur le dt_break, n_no_break)
      ss_break = where(dt_err_occur gt dt_break, n_break)

      ss_break = [0, ss_break+1]
      n_break = n_break + 1

;     if n_break gt 0 then begin ; Always, since an artificial break is always added at the beginning

         for j=1, n_break-1 do begin

            n_occur_block = (ss_break[j]-1) - ss_break[j-1] + 1
PRINT, 'N_OCCUR_BLOCK = ' + STRTRIM(N_OCCUR_BLOCK,2)
            if n_occur_block eq 1 then begin
               if ~exist(out_arr) then out_arr = err_info_occur[ss_break[j]-1] else $
                  out_arr = [out_arr, err_info_occur[ss_break[j]-1]]
            endif else begin
               summary_line = '( ' + string(n_occur_block,'$(i3.3)') + $
                              ' occurrences of this error between ' + t_err_occur[ss_break[j-1]] + $
                              ' and ' + t_err_occur[ss_break[j]-1]
               buff = err_info_occur[ss_break[j]-1] + ' ' +summary_line
               if ~exist(out_arr) then out_arr = buff else $
                  out_arr = [out_arr, buff]
            endelse

;            case j of
;               0: begin
;                  err_struct_block = err_struct_occur[0:ss_break[0]]
;                  err_info_arr_block =  err_info_occur[0:ss_break[0]]
;                  t_err_block = t_err_occur[0:ss_break[0]]
;               end
;            
;               n_break-1: begin
;                  err_struct_block = err_struct_occur[ss_break[j]:*]
;                  err_info_arr_block =  err_info_occur[ss_break[j]:*]
;                  t_err_block = t_err_occur[ss_break[j]:*]
;               end
;
;               else: begin
;                  err_struct_block = err_struct_occur[ss_break[j]+1:ss_break[j+1]]
;                  err_info_arr_block =  err_info_occur[ss_break[j]+1:ss_break[j+1]]
;                  t_err_block = t_err_occur[ss_break[j]+1:ss_break[j+1]]
;               end
;            endcase
;
;            n_occur_block = n_elements(err_struct_block)
;            if n_occur_block le 1 then begin
;               if i eq 0 then out_arr = err_info_arr_block[0] else $
;                  out_arr = [out_arr, err_info_arr_block[0]]
;            endif else begin
;               summary_line = '( ' + string(n_occur_block,'$(i3.3)') + $
;                              ' occurrences of this error between ' + t_err[0] + $
;                              ' and ' + t_err[n_occur_block-1]
;               if i eq 0 then out_arr = err_info_arr_block[0] + ' ' + summary_line else $
;                  out_arr = [out_arr, err_info_arr_block[0] + ' ' + summary_line]
;            endelse

         endfor

         if ss_break[n_break-1]+1 ne n_occur then begin
            n_occur_block = (n_occur-1) - (ss_break[n_break-1]) + 1
PRINT, 'LAST N_OCCUR_BLOCK = ' + STRTRIM(N_OCCUR_BLOCK,2)
            if n_occur_block eq 1 then begin
               if ~exist(out_arr) then out_arr = err_info_occur[n_occur-1] else $
                  out_arr = [out_arr, err_info_occur[n_occur-1]]
            endif else begin
               summary_line = '( ' + string(n_occur_block,'$(i3.3)') + $
                              ' occurrences of this error between ' + t_err_occur[ss_break[n_break-1]] + $
                              ' and ' + t_err_occur[n_occur-1]
               buff = err_info_occur[n_occur-1] + ' ' + summary_line
               if ~exist(out_arr) then out_arr = buff else $
                  out_arr = [out_arr, buff]
            endelse
         endif else begin
            if ~exist(out_arr) then out_arr = err_info_occur[n_occur-1] else $
               out_arr = [out_arr, err_info_occur[n_occur-1]]
         endelse

;     endif else begin ; (Case of no breaks for this unique error number)
;        if n_occur eq 1 then begin
;           if i eq 0 then out_arr = err_info_occur[0] else $
;              out_arr = [out_arr, err_info_occur[0]]
;        endif else begin
;           summary_line = '( ' + string(n_occur,'$(i3.3)') + $
;                          ' occurrences of this error between ' + err_struct_occur[0].t_err + $
;                          ' and ' + err_struct_occur[n_occur-1].t_err
;
;           if i eq 0 then out_arr = err_info_occur[0] + ' ' + summary_line else $
;              out_arr = [out_arr, err_info_occur[0] + ' ' + summary_line]
;        endelse
;     endelse

   endfor

endif else begin
   out_arr = no_error_arr[0]
endelse

; Reverse time order all records (except for 'no error' case):
if count gt 0 then begin
   t_out_arr = strmid(out_arr, 0, 19)
   ss_sort = reverse(sort(anytim(t_out_arr)))
   out_arr = out_arr[ss_sort]
endif

hdr_arr = ['', $
           'FPP Error Listing For Last ' + string(n_days_lookback, format='$(i3.3)') + ' Days, ' + $
           'as of ' + strmid(anytim(ut_time(), /ecs), 0, 19) + ' UT', $
           '', $
           'Date       Time      Num    Error Code' + string('', format='$(a8)') + '  Diagnoses', $
           '---------- --------  -----  ----------' + string('', format='$(a8)') + '  ---------']

out_arr = [hdr_arr, out_arr]

if keyword_set(do_print) then prstr, out_arr, /nomore
if keyword_set(do_write) then file_append, outfil_errlist, out_arr, /new

if keyword_set(debug) then stop, ' Stopping on request.'

end
