import logging
import os
import pathlib
import struct
import typing

from . import dna_io, exceptions

log = logging.getLogger(__name__)


class BlendFileHeader:
    """
    BlendFileHeader represents the first 12 bytes of a blend file.

    It contains information about the hardware architecture, which is relevant
    to the structure of the rest of the file.
    """
    structure = struct.Struct(b'7s1s1s3s')

    def __init__(self, fileobj: typing.BinaryIO, path: pathlib.Path):
        log.debug("reading blend-file-header %s", path)
        fileobj.seek(0, os.SEEK_SET)
        header = fileobj.read(self.structure.size)
        values = self.structure.unpack(header)

        self.magic = values[0]

        pointer_size_id = values[1]
        if pointer_size_id == b'-':
            self.pointer_size = 8
        elif pointer_size_id == b'_':
            self.pointer_size = 4
        else:
            raise exceptions.BlendFileError('invalid pointer size %r' % pointer_size_id, path)

        endian_id = values[2]
        if endian_id == b'v':
            self.endian = dna_io.LittleEndianTypes
            self.endian_str = b'<'  # indication for struct.Struct()
        elif endian_id == b'V':
            self.endian = dna_io.BigEndianTypes
            self.endian_str = b'>'  # indication for struct.Struct()
        else:
            raise exceptions.BlendFileError('invalid endian indicator %r' % endian_id, path)

        version_id = values[3]
        self.version = int(version_id)

    def create_block_header_struct(self) -> struct.Struct:
        """Create a Struct instance for parsing data block headers."""
        return struct.Struct(b''.join((
            self.endian_str,
            b'4sI',
            b'I' if self.pointer_size == 4 else b'Q',
            b'II',
        )))
