;+
; NAME: eis_md_decomp.pro
;
; PURPOSE: Decompress EIS mission data packets.
;      
; CATEGORY: Science
;
; CALLING SEQUENCE: eis_mk_decomp, 'md_archive'
;
; INPUTS: Filename string of the mission data archive
;
; KEYWORD PARAMETERS: None
;
; OUTPUTS: One decompressed mission data archive in /tmp
;
; CALLS: Various SSW fits routines.
;
; COMMON BLOCKS:None.
;
; PROCEDURE:
;
; RESTRICTIONS: Uses SolarSoft
;
; MODIFICATION HISTORY:
;	23/11/05 mcrw	wrote
;       14/08/06 mcrw	added documentation
;
;-

; Create a single mission data packet from the decompressed data
; rl is the read lun
; wl is the write lun
; ccsdsHeader is the header of the first ccsds packet in the original archive
; mdHeader is the first md header of the original archive
; buffer is an intarr of pixels
pro eis_write_decompressed_packet, rl, wl, ccsds_header, md_header, buffer
;    on_ioerror, badRd

    total_pixels = long(n_elements(buffer))
    pixel_pointer = 0L
    pixels_left = total_pixels - pixel_pointer

    hdr = ccsds_header
    hdr[2] = hdr[2] and 2^6 - 1 ; Clear flag to make sure or works ok
    seq_count = ishft(hdr[2], -6) or hdr[3]
    seq_flag = 0

    ; Set sequence flag
    if pixels_left lt 1016 then seq_flag = 3

    ; Write out md header
    writeu, wl, ccsds_header
    writeu, wl, md_header

    ; Now read the decompressed data and write back out in ccsds packets
    going = 1
    while going do begin			; Try to write a full pixel ccsds packet
        ; Create ccsds packet with the data
        seq_count = seq_count + 1
        if pixels_left gt 1016 then begin ; Full packet
            hdr[2] = hdr[2] or ishft(seq_count, -8)
            hdr[3] = (seq_count and 255)
            hdr[4] = 7          			; MSB length
            hdr[5] = 243				; LSB length
            writeu, wl, hdr
            writeu, wl, buffer[pixel_pointer:(pixel_pointer+1015)]
            pixel_pointer = pixel_pointer + 1016
            pixels_left = total_pixels - pixel_pointer
            going = pixels_left gt 1016
        endif
    endwhile

    ; Packet up residual data
    if pixels_left gt 0 then begin
        bytes_left = pixels_left * 2
        seq_count = seq_count + 1
        seq_flag = 2
        hdr[2] = hdr[2] or ishft(seq_flag, 6)		; Sequence flag
        hdr[2] = hdr[2] or ishft(seq_count, -8)
        hdr[3] = (seq_count and 255)
        bytes_left = bytes_left + 3
        hdr[4] = ishft((bytes_left and 65280), -8)	; MSB length
        hdr[5] = bytes_left and 255			; LSB length
        writeu, wl, hdr
        writeu, wl, buffer[pixel_pointer:*], transfer_count=t_count
    endif

;;;    print, "Finished reading 'n writing"

;    badRd: begin
;        print, !err_string
;        print, buffer
;        print, 'Actually read: ', numBytes
;    end

end

; Process a single md packet
; archive is the ccsds reader object
; compression is the compression number from the mission data header
; basename is the original archive without the path
function eis_process_packet, archive, compression, basename, integers_in_count, integers_out_count, ctab,ctype,merge=merge
;;;;    help, compression

    ; Path to the decompression programs
    progs = getenv('EIS_BIN')

    ; Get the 8 byte table in the header
    hdr = archive->md_header();
    comp_table = hdr[0:7]
    ctab = comp_table
;;;    print,'COMP TABLE: ',comp_table

    ; Read in the rest of archive
    if archive->read_ccsds_header() then begin
        data = archive->read_user_data()

        ; data is a BYTE array
        while not archive->is_end_packet_of_sequence() do begin
            foo = archive->read_ccsds_header()
            data = [data, archive->read_user_data()]
        endwhile 

        integers_in_count = integers_in_count + (n_elements(data) / 2)

        ; Now write the compressed data out

        ; Create temporary filename
        tmp = getenv('HOME') + '/work/tmp/'
        temp_file = tmp + basename + '_image'
        openw, lu, temp_file, /get_lun
        writeu, lu, data
        close, lu
        free_lun, lu

        ; Now do image decompression
        ; 0x3B28 : DPCM
        ; 0x3F28 : JPEG
        print, 'Doing image decompression...'

        decomp_program = ''
        if (compression and '0700'x) eq '0700'x then begin
            decomp_program = progs + '/djpeg ' + temp_file + ' > ' + temp_file + '_decomp'
;;;;;;;;;;;;;;;;            printf,outlun,'JPEG ', string(compression,
;;;;;;;;;;;;;;;;            format='(Z04)')
            ctype = 'JPEG '
        endif else begin
            if (compression and '0300'x) eq '0300'x then begin
;;;          decomp_program = progs + '/dpcmtopnm -v ' + temp_file + ' > ' + temp_file + '_decomp'
                decomp_program = progs + '/dpcmtopnm ' + temp_file + '  ' + temp_file + '_decomp'
;;;;;;;;;;;;;;;;;;;                printf,outlun,'DPCM ',
;;;;;;;;;;;;;;;;;;;                string(compression, format='(Z04)')
                ctype = 'DPCM '
            endif
        endelse
        if decomp_program eq '' then stop

        ; Spawn a child process to do the image decompressing
;;;        print, decomp_program
        spawn, decomp_program

        ; Now read the decompressed image data
        ; and perform bit compression on it
        decompressed_image=read_binary(temp_file + '_decomp',data_type=2)

        integers_out_count = integers_out_count + n_elements(decompressed_image)

        ; Do bit decompression and write bit decompressed data to temporary file
        if(compression and '7800'x) ne 0 then begin
            print, 'Doing bit decompression...'
            bit_data = eis_bit_decomp(decompressed_image)
        endif else begin
            print, 'NO BIT COMPRESSION...'
        endelse

;;;        integers_out_count = integers_out_count + n_elements(bit_data)

        ; Now rebuild the archive
        byteorder, bit_data, /swap_if_little_endian

        if keyword_set(merge) then begin
            out_file = getenv('HOME') + '/work/localdata/sdtp/merge/decompressed/' + basename
        endif else begin
            out_file = getenv('HOME') + '/work/localdata/sdtp/decompressed/' + basename
        endelse
        openw, wlu, out_file, /get_lun, /append

;;;        print, 'Writing to file ', out_file

        eis_write_decompressed_packet, rlu, wlu, archive->first_ccsds_header(), archive->md_header(), bit_data

        close, wlu
        free_lun, wlu

        return, 1
    endif

    ; No packets left in archive
    ; Premature end
    return, 0
end

; Main procedure.
pro eis_md_decomp, filename, merge=merge

openw,rat,'$HOME/work/localdata/sdtp/decompressed/decomp_record.txt',/get_lun,/append
printf,rat,filename

;;;    print, 'Filename is ', filename

    p = strpos(filename, '/', /reverse_search)
    newfilename = strmid(filename, p + 1, 255)
;;;    print, 'New filename is ', newfilename

    md_archive = obj_new('eis_ccsds_interface')
    md_archive->open_for_reading, filename, ok
    if not ok then begin
        print, 'No such file'
        return
    endif

    ; Read in decompression factors (a, b, c, Nc)

    integers_in_count = 0
    integers_out_count = 0
    first_md_header = 1
    while md_archive->read_md_header_packet() do begin

        if first_md_header then begin
            first_md_header = 0
            if md_archive->is_compressed() then begin

                ; Get a string here which can be spawned...
                compression = md_archive->get_compression_method()
                flags_ok = 0
                flags = md_archive->get_md_sequence_flags()
                case flags of
                    '11' : flags_ok = 1
                    '13' : flags_ok = 1
                    '31' : flags_ok = 1
                    '33' : flags_ok = 1
                    '23' : flags_ok = 1 ; should really be bad flags
                    else: print, 'Bad flags: ', flags ; May remove
                endcase
            endif else begin
                print, 'Archive not compressed'
                ; Close files
                md_archive->close_input
                ; Move stuff about
                if keyword_set(merge) then begin
                    dest = getenv('HOME') + '/work/localdata/sdtp/merge/decompressed/'
                endif else begin
                    dest = getenv('HOME') + '/work/localdata/sdtp/decompressed/'
                endelse
                cmd_line = strarr(3)
                cmd_line[0] = 'mv'
                cmd_line[1] = filename
                cmd_line[2] = dest
                spawn, cmd_line, result, /noshell
                return
            endelse
        endif

        if flags_ok then begin
;;;            print, 'Processing for flags: ', flags
            processed = eis_process_packet(md_archive, compression, newfilename, integers_in_count, integers_out_count,ctab,ctype,merge=merge)
        endif else begin
            print, 'Flags indicate this is not the start of a raster' ; Will log this to a file
            ; Close files
            md_archive->close_input
            return
        endelse
            
        if processed then begin
            print, 'Removing temporary files'
            cmd = '/bin/rm ' + getenv('HOME') + '/work/tmp/eis_md*'
            spawn, cmd
        endif

    endwhile

    md_archive->close_input
    print, 'Processed: ', processed
    print, 'Integers in : ', integers_in_count
    print, 'Integers out: ', integers_out_count
    print, 'Compression: ', (float(integers_in_count)/float(integers_out_count))*100.0

printf,rat,'Comp table ',ctab,' type ',ctype, string(compression,format='(Z04)')
printf,rat,'Integers in : ',integers_in_count
printf,rat,'Integers out: ',integers_out_count
printf,rat,'Compression: ', (float(integers_in_count)/float(integers_out_count))*100.0
printf,rat,''
close, rat
free_lun, rat


end
