import re


class FirmwareFile(object):
    def __init__(self, binary, desc=None, source=None, version=None):
        self.binary = binary
        self.desc = desc
        self.source = source
        self.version = version


class FirmwareSection(object):
    def __init__(self, driver, files, licence):
        self.driver = driver
        self.files = files
        self.licence = licence


class FirmwareWhence(list):
    def __init__(self, file):
        self.read(file)

    def read(self, file):
        in_header = True
        driver = None
        files = {}
        licence = None
        binary = []
        desc = None
        source = []
        version = None

        for line in file:
            if line.startswith("----------"):
                if in_header:
                    in_header = False
                else:
                    # Finish old section
                    if driver:
                        self.append(FirmwareSection(driver, files, licence))
                    driver = None
                    files = {}
                    licence = None
                continue

            if in_header:
                continue

            if line == "\n":
                # End of field; end of file fields
                for b in binary:
                    # XXX The WHENCE file isn't yet consistent in its
                    # association of binaries and their sources and
                    # metadata.  This associates all sources and
                    # metadata in a group with each binary.
                    files[b] = FirmwareFile(b, desc, source, version)
                binary = []
                desc = None
                source = []
                version = None
                continue

            match = re.match(
                r"(Driver|File|Info|Licen[cs]e|Source|Version"
                r"|Original licen[cs]e info(?:rmation)?):\s*(.*)\n",
                line,
            )
            if match:
                keyword, value = match.group(1, 2)
                if keyword == "Driver":
                    driver = value.split(" ")[0].lower()
                elif keyword == "File":
                    match = re.match(r"(\S+)(?:\s+--\s+(.*))?", value)
                    binary.append(match.group(1))
                    desc = match.group(2)
                elif keyword in ["Info", "Version"]:
                    version = value
                elif keyword == "Source":
                    source.append(value)
                else:
                    licence = value
            elif licence is not None:
                licence = (
                    licence
                    + "\n"
                    + re.sub(r"^(?:[/ ]\*| \*/)?\s*(.*?)\s*$", r"\1", line)
                )

        # Finish last section if non-empty
        for b in binary:
            files[b] = FirmwareFile(b, desc, source, version)
        if driver:
            self.append(FirmwareSection(driver, files, licence))
