"""
    This module defines a class FortranBinary for interaction with binary files 
    generated by FORTRAN unformatted I/O
"""
import struct, sys

class FortranBinary():
    """Class for binary files compatible with Fortran Unformatted I/O"""
    pad = 4
    def __init__(self, name, status=None):
        self.name = name
        if status == 'new':
            self.file = open(name,'wb')
        else:
            try:
                self.file = open(name, 'rb', 10)
            except(IOError):
                print("\n%s: file %s not found\n" % (__name__ + '.' + self.__class__.__name__, name))
                raise IOError
        self.data = None
        self.loc = 0
        self.reclen = 0

    def __iter__(self):
        return self

    def __next__(self): #pragma: no cover
        return self.next()

    def next(self):
        """Read a Fortran record"""
        head = self.file.read(self.pad)
        if head:
            size = struct.unpack('i', head)[0]
            self.data = self.file.read(size)
            self.reclen = size
            tail = self.file.read(self.pad)
            assert head == tail
            self.loc = 0
            self.rec = Rec(self.data) 
            return self.rec
        else:
            raise StopIteration

    def readbuf(self, n, c):
        """Read data from current record"""
        vec = self.rec.read(n, c)
        return vec

    def find(self, label):
        """Find string label in file"""
        if type(label) == str:
            try:
                blabel = bytes(label, 'utf-8')
            except TypeError:
                blabel = label
        elif type(label) == bytes:
            blabel = label
        else:
            raise ValueError

        for rec in self:
            if blabel in rec: return rec

    def close(self):
        """Close file"""
        self.file.close()

    def record_byte_lengths(self):
        reclengths = [self.reclen for record in self]
        return tuple(reclengths)

class Rec():
    def __init__(self, data):
        self.data = data
        self.loc = 0
        self.reclen = len(data)

    def __contains__(self, obj):
        return obj in self.data

    def read(self, n, c):
        """Read data from current record"""
        start, stop = self.loc, self.loc+struct.calcsize(c*n)
        vec = struct.unpack(c*n, self.data[start:stop])
        self.loc = stop
        return vec
        
if __name__ == "__main__": #pragma: no cover
    pass
