from parallels.core import messages


class BaseStreamPacketReader(object):
    """Each time we read from fileobj, read data accumulates in _collected_data.
    Accumulated data can be get with property 'collected_data' and reset with method 'reset_collected_data'.
    _collected_data is useful for debugging. Reset it once it were parsed correctly.
    For example:
    If unexpected data received, part of the data can be mistakenly parsed as part of a packet before the error occurs.
    _collected_data allows to reinterpret unexpected data from it`s supposed beginning.
    """
    def __init__(self, fileobj):
        self._fileobj = fileobj
        self._collected_data = ''

    @property
    def collected_data(self):
        """Return all data which were read from fileobj since the last reset

        :rtype: str
        """
        return self._collected_data

    def reset_collected_data(self):
        self._collected_data = ''

    def iter_packets(self):
        raise NotImplementedError()

    def _read(self, length):
        read_data = self._fileobj.read(length)
        self._collected_data += read_data
        return read_data

    def _read_line(self):
        line = ''
        while True:
            c = self._read(1)
            if c == '' or c == '\n':
                break
            line += c
        return line

    def _read_bytes(self, bytes_count):
        data = ''

        while True:
            c = self._read(bytes_count - len(data))
            data += c

            if len(data) == bytes_count:
                break

            if c == '':
                raise Exception(messages.BASE_STREAM_PACKET_READER_EXPECTED_DATA)

        c = self._read(1)

        if c != '\n':
            raise Exception(messages.BASE_STREAM_PACKET_READER_EXPECTED_NEW_LINE)

        return data
