PRO write_xrt, index, data, archive=archive, outdir=outdir,             $
               outfile=outfile, paths_only=paths_only,                  $
               out_paths=out_paths, make_dir=make_dir, verbose=verbose, $
               quiet=quiet, qabort=qabort, qstop=qstop

; =========================================================================
;+
; PROJECT:
;       Solar-B / XRT
;
; NAME:
;       WRITE_XRT
;
; CATEGORY:
;       File I/O.
;
; PURPOSE:
;       Write Level-1 XRT data image files.
;
; CALLING SEQUENCE:
;
;       WRITE_XRT, index, data                                        $
;                  [,/archive] [,outdir=outdir] [,outfile=outfile]    $
;                  [,/paths_only] [,/make_dir] [,out_paths=out_paths] $
;                  [,/verbose] [,/quiet] [,/qstop] [,qabort=qabort]
;
; INPUTS:
;
;       INDEX       - [Mandatory] (structure, or structure array, [Nimg])
;                     The XRT data keywords. These come from the 
;                     Level-0 FITS files in the header.
;       DATA        - [Mandatory*] (number array, [Nx,Ny,Nimg])
;                     (*This keyword is mandatory UNLESS the PATHS_ONLY
;                     switch is used.) This is the data-cube paired to 
;                     "index".
;
; KEYWORDS:
;
;       /ARCHIVE    - [Optional] (Boolean)
;                     If set, the FITS files will be written into the site
;                     XRT data archive with the standard filename format.
;                     ARCHIVE overrides OUTDIR and OUTFILE.
;       OUTDIR      - [Optional] (string scalar)
;                     Specifies the fully qualified output directory. 
;                     Default = the current working directory. 
;                     OUTDIR overrides ONLINE.
;       OUTFILE     - [Optional] (string array, [Nimg])
;                     Specifies the output filenames. Default = follow
;                     the XRT filename standard for Level-1 FITS files:
;                     L1_XRTyyymmdd_hhmmss.s.fits .
;       /PATHS_ONLY - [Optional] (Boolean)
;                     If set, just return OUT_PATHS but don't write any 
;                     files. 
;       /MAKE_DIR   - [Optional] (Boolean)
;                     If set, create implied directories if they do not
;                     exist.
;       /VERBOSE    - [Optional] (Boolean) If set, print out extra
;                     information. Overrides "/quiet" (see Note #1).
;       /QUIET      - [Optional] (Boolean) If set, suppress messages
;                     (see Note #1).
;       /QSTOP      - [Optional] (Boolean) For debugging.
;
; OUTPUTS:
;
;       This program will write Level-1 FITS files for the input data
;       (unless the PATHS_ONLY switch is used). There will be one image per
;       file. By default, the files will be written into the current working
;       directory, but file-paths can be modified with keywords.
;
;       OUT_PATHS   - [Optional] (string array, [Nimg])
;                     List of implied/derived full file-paths for the 
;                     output.
;       QABORT      - [Optional] (Boolean) Indicates that the program
;                     exited gracefully without completing. (Might be
;                     useful for calling programs.)
;                     0: Program ran to completion.
;                     1: Program aborted before completion.
;
; EXAMPLES:
;
;       Write Level-1 data-cube into current directory:
;       IDL> write_xrt, index, data
;
;       Write Level-1 data-cube into the site XRT archive:
;       IDL> write_xrt, index, data, /archive
;
;       Get the output filenames without writing the files:
;       IDL> write_xrt, index, data, /paths_only, out_paths
;       
; COMMON BLOCKS:
;
;       none
;
; NOTES:
;
;       1) There are three levels of verbosity.
;          a) "verbose" = highest priority. All errors and messages are
;                         displayed. ("if q_vb")
;          b) "quiet" = lower priority. No errors or messages are
;                       displayed. ("if q_qt")
;          c) neither = lowest priority. All errors and some messages are
;                       displayed. ("if not q_qt")
;
;       2) If the /ARCHIVE switch is used, then the standard archive path
;          and standard filename format will be followed. This overrides
;          OUTDIR and OUTFILE. If /ARCHIVE is not used, then OUTDIR and 
;          OUTFILE are used if they are given. If OUTDIR is not given,
;          then the current working directory is used. If OUTFILE is not
;          given, then standard format filenames are used. The OUTDIR and
;          OUTFILE keywords operate independently. If they are both given,
;          then OUTDIR+OUTFILE will be used.
;
;       3) Obviously, /MAKE_DIR cannot create directories if you don't
;          have permission on that filesystem to create those directories.
;
; MODIFICATION HISTORY:
;
progver = 'v2007-Apr-10' ;--- (M.Weber, J.Cirtain (SAO)) Written. (Based on
;                             <write_sot.pro>, 2007-Jan-09.)
progver = 'v2007-May-20' ;--- (K.Reeves (SAO)) Fixed bug with transposing
;                             "dir_ends" when it is a scalar (one file).
progver = 'v2007-Jun-13' ;--- (M.Weber (SAO)) Removed contraint on 
;                             data level.
progver = 'v2011-Jan-06; ;--- (S.Saar (SAO)) added check for length of
;                             history lines, wrapping as needed 
;
;-
; =========================================================================

;=== Initial setup =======================================

  ;=== Set Booleans which control print statements.
  ;=== Keyword "verbose" overrules "quiet".
  q_vb = keyword_set(verbose)
  q_qt = keyword_set(quiet) and (not q_vb)

  ;=== Initialize program constants.
  prognam='WRITE_XRT'
  prognam_len = strlen(prognam)
  prognam_nul = strmid('                                               ', $
                       0, prognam_len)

  ;=== Announce version of <read_xrt.pro>.
  if q_vb then box_message, prognam+': Running ' + prognam + $
                            ' ' + progver + '.'
  if q_vb then print, prognam+': Performing initial setup...'


  ;=== Set some keyword Booleans.
  q_archive = keyword_set(archive)
  q_outfile = keyword_set(outfile)
  q_outdir  = keyword_set(outdir)
  q_nowrite = keyword_set(paths_only)
  q_makedir = keyword_set(make_dir)
  qstop     = keyword_set(qstop)
  qabort    = 0B

  ;=== Other useful stuff.
  n_ind = n_elements(index)
  pdelim = get_delim()

  if q_vb then print, prognam_nul+'                          ...OK'


;=== Check inputs ========================================

  if q_vb then print, prognam+': Checking inputs...'

  ;=== Check number of inputs.
  if (n_params() ne 2) then begin
    if (not q_qt) then box_message, prognam+': Need to provide both ' $
                                          + 'INDEX and DATA. Aborting.'
    qabort = 1B
    return
  endif

  ;=== Check index structure for XRT ID.
  if not required_tags(index, 'date_obs,ec_fw1') then begin
    if (not q_qt) then box_message, prognam+': This is not an XRT index ' $
                                    + 'structure. Aborting.'
    qabort = 1B
    return
  endif




  if q_vb then print, prognam_nul+'                 ...OK'


;=== Generate filenames ==================================

  if q_vb then print, prognam+': Generating filenames...'

  ;=== If going into the archive, then follow standard format.
  if q_archive then begin
    out_paths = xrt_index2filename(index, /archive_path)

  ;=== If NOT going into the archive, then proceed.
  endif else begin

    ;=== Use filenames if given.
    if q_outfile then begin
      out_paths = outfile
    endif else begin
      out_paths = xrt_index2filename(index)
    endelse

    ;=== Use directories if given.
    if q_outdir then begin
      out_paths = outdir   + pdelim + temporary(out_paths)
    endif else begin
      out_paths = curdir() + pdelim + temporary(out_paths)
    endelse

  endelse

  if q_vb then print, prognam_nul+'                      ...OK'


;=== Make directories, as necessary ======================

  if q_vb then print, prognam+': Checking whether directories exist...'

  ;=== Make sorted list of unique directory paths.
  dir_ends  = strpos(out_paths, pdelim, /reverse_search)
  if n_elements(dir_ends) eq 1 then tr_dir_ends = dir_ends          $
                               else tr_dir_ends = transpose(dir_ends)
  dir_trunc = strmid(out_paths, 0, tr_dir_ends)
  uniq_dirs = dir_trunc(uniq(dir_trunc, sort(dir_trunc)))
  dirs_need = where(1 - file_exist(uniq_dirs), need_count)

  ;=== If some directories do not exist...
  if (need_count ne 0) then begin

    ;=== If didn't ask to create directories, then abort.
    if not q_makedir then begin
      if (not q_qt) then begin
        box_message, [prognam+': Some of the directories do not exist. ' $
          +'Check OUT_PATHS to see', prognam_nul+'  a list of all '      $
          +'directories. Use /MAKE_DIR to automatically',                $
          prognam_nul+'  create these directories. Aborting.']
      endif
      qabort = 1B
      return
    endif else begin

      ;=== If asked to create directories, then do so.
      if q_vb then print,     prognam+': Making directories...'
      for ii = 0, (need_count-1) do begin
        mk_dir, uniq_dirs(dirs_need[ii]), verbose=q_vb
      endfor
      if q_vb then print, prognam_nul+':                   ...OK'
    endelse

  endif

  if q_vb then print, $
                 prognam_nul+'                                     ...OK'


;=== Write files =========================================

  if not q_nowrite then begin

    if q_vb then print, prognam+': Writing FITS files...'

;=== check index.history for lines > FITS limit (72) and wrap if needed

    hist0=index.history
    sizh0=size(hist0)
    if max(strlen(hist0)) gt 72 then begin    ; if some history lines too long
       hist=history_wrap(hist0)               ; wrap them onto new lines
       nhist=n_elements(hist)                 ; count new number of lines
       if sizh0(0) eq 2 then nim=sizh0(2) else nim=1  ; find number of images
       hlen=nhist/nim                               ; new # history lines/image
       hlen0=n_elements(hist0)/nim                  ; old # history lines/image
       for jj=0, nim-1 do begin                     ; for each image index
          histj=hist(jj*hlen:(jj+1)*hlen-1)           
          index_outj=index(jj)
          index_outj.history = histj(0:hlen0-1)    ; replace hlen0 history lines
          update_history,index_outj,histj(hlen0:*),/noroutine ; update new lines
          if jj eq 0 then index_out=index_outj else  $
            index_out=[index_out,index_outj]          
       endfor
    endif else index_out=index
    
    mwritefits, index_out, data, outfile=out_paths, /flat_fits, $
                loud=q_vb, quiet=q_qt
    if q_vb then print, prognam_nul+'                    ...OK'

  endif ;; (not q_nowrite)


;=== Finish ==============================================

  if q_vb then box_message, prognam+': Finished.'


END ;======================================================================
