#!/usr/bin/env python3
import sys, os, struct, binascii
fn=sys.argv[1]
if len(sys.argv) > 2:
    s=sys.argv[2]
else:
    s=None

R_NONE    = 0x00
R_EMPTY   = 0x01
R_REAL    = 0x02
R_IMAG    = 0x04
R_SYMM    = 0x08
R_ASYMM   = 0x10

def flag_str(f):
    r=""
    if f & R_EMPTY:
        r += "empty "
    if f & R_REAL:
        r += "real "
    if f & R_IMAG:
        r += "imag "
    if f & R_SYMM:
        r += "symm "
    if f & R_ASYMM:
        r += "asymm "
    return r.strip()

def reconstruct_full(flags, i):
    if flags & R_SYMM:
        N=len(i)//2
        for j in range(N//2+1,N):
            jm=N - j
            i[2*j + 0] = i[2*jm + 0]
            i[2*j + 1] = -i[2*jm + 1]

    if flags & R_ASYMM:
        N=len(i)//2
        for j in range(N//2+1,N):
            jm=N - j
            i[2*j + 0] = -i[2*jm + 0]
            i[2*j + 1] = i[2*jm + 1]

def reconstruct_min(flags, i, NT):
    if flags & R_EMPTY:
        return [ 0.0 for l in 2*range(NT) ]
    if flags == 0:
        return i

    o=[ 0.0 for l in 2*range(NT) ]

    # first fill in data at right places
    i0=0
    istep=1

    if flags & R_REAL:
        istep=2
    if flags & R_IMAG:
        istep=2
        i0=1

    for j in range(len(i)):
        o[istep*j + i0] = i[j]

    return o


f=open(fn,"rb")
try:
    while True:
        rd=f.read(4)
        if len(rd) == 0:
            break
        ntag=struct.unpack('i', rd)[0]
        tag=f.read(ntag).decode("utf-8")
        (crc32,ln,flags)=struct.unpack('IHH', f.read(4*2))

        nf = 1
        lnr = ln
        if flags & (R_REAL|R_IMAG):
            nf = 2
        if flags & (R_SYMM|R_ASYMM):
            lnr = ln//2+1
        if flags & R_EMPTY:
            lnr = 0

        if s == None or s==tag[0:-1]:

            rd=reconstruct_min( flags, struct.unpack('d'*(2*lnr // nf), f.read(16*lnr // nf) ) , ln)
            crc32comp= ( binascii.crc32(struct.pack('d'*2*ln,*rd)) & 0xffffffff)

            reconstruct_full( flags, rd )
            
            if crc32comp != crc32:
                print("Data corrupted!")
                f.close()
                sys.exit(1)

            print("Tag[%s] Size[%d] Flags[%s] CRC32[%X]" % (tag[0:-1],ln,flag_str(flags),crc32))

            if flags != R_EMPTY:
                for j in range(ln):
                    print("%d %.15g %.15g" % (j,rd[j*2+0],rd[j*2+1]))

        else:
            f.seek(lnr*16 // nf,1)

    f.close()
except:
    raise
#pass
