from fontTools.config import OPTIONS
from fontTools.misc.textTools import Tag, bytesjoin
from .DefaultTable import DefaultTable
from enum import IntEnum
import sys
import array
import struct
import logging
from functools import lru_cache
from typing import Iterator, NamedTuple, Optional, Tuple

log = logging.getLogger(__name__)

have_uharfbuzz = False
try:
    import uharfbuzz as hb

    # repack method added in uharfbuzz >= 0.23; if uharfbuzz *can* be
    # imported but repack method is missing, behave as if uharfbuzz
    # is not available (fallback to the slower Python implementation)
    have_uharfbuzz = callable(getattr(hb, "repack", None))
except ImportError:
    pass

USE_HARFBUZZ_REPACKER = OPTIONS[f"{__name__}:USE_HARFBUZZ_REPACKER"]


class OverflowErrorRecord(object):
    def __init__(self, overflowTuple):
        self.tableType = overflowTuple[0]
        self.LookupListIndex = overflowTuple[1]
        self.SubTableIndex = overflowTuple[2]
        self.itemName = overflowTuple[3]
        self.itemIndex = overflowTuple[4]

    def __repr__(self):
        return str(
            (
                self.tableType,
                "LookupIndex:",
                self.LookupListIndex,
                "SubTableIndex:",
                self.SubTableIndex,
                "ItemName:",
                self.itemName,
                "ItemIndex:",
                self.itemIndex,
            )
        )


class OTLOffsetOverflowError(Exception):
    def __init__(self, overflowErrorRecord):
        self.value = overflowErrorRecord

    def __str__(self):
        return repr(self.value)


class RepackerState(IntEnum):
    # Repacking control flow is implemnted using a state machine. The state machine table:
    #
    # State       | Packing Success | Packing Failed | Exception Raised |
    # ------------+-----------------+----------------+------------------+
    # PURE_FT     | Return result   | PURE_FT        | Return failure   |
    # HB_FT       | Return result   | HB_FT          | FT_FALLBACK      |
    # FT_FALLBACK | HB_FT           | FT_FALLBACK    | Return failure   |

    # Pack only with fontTools, don't allow sharing between extensions.
    PURE_FT = 1

    # Attempt to pack with harfbuzz (allowing sharing between extensions)
    # use fontTools to attempt overflow resolution.
    HB_FT = 2

    # Fallback if HB/FT packing gets stuck. Pack only with fontTools, don't allow sharing between
    # extensions.
    FT_FALLBACK = 3


class BaseTTXConverter(DefaultTable):
    """Generic base class for TTX table converters. It functions as an
    adapter between the TTX (ttLib actually) table model and the model
    we use for OpenType tables, which is necessarily subtly different.
    """

    def decompile(self, data, font):
        """Create an object from the binary data. Called automatically on access."""
        from . import otTables

        reader = OTTableReader(data, tableTag=self.tableTag)
        tableClass = getattr(otTables, self.tableTag)
        self.table = tableClass()
        self.table.decompile(reader, font)

    def compile(self, font):
        """Compiles the table into binary. Called automatically on save."""

        # General outline:
        # Create a top-level OTTableWriter for the GPOS/GSUB table.
        # 	Call the compile method for the the table
        # 		for each 'converter' record in the table converter list
        # 			call converter's write method for each item in the value.
        # 				- For simple items, the write method adds a string to the
        # 				writer's self.items list.
        # 				- For Struct/Table/Subtable items, it add first adds new writer to the
        # 				to the writer's self.items, then calls the item's compile method.
        # 				This creates a tree of writers, rooted at the GUSB/GPOS writer, with
        # 				each writer representing a table, and the writer.items list containing
        # 				the child data strings and writers.
        # 	call the getAllData method
        # 		call _doneWriting, which removes duplicates
        # 		call _gatherTables. This traverses the tables, adding unique occurences to a flat list of tables
        # 		Traverse the flat list of tables, calling getDataLength on each to update their position
        # 		Traverse the flat list of tables again, calling getData each get the data in the table, now that
        # 		pos's and offset are known.

        # 		If a lookup subtable overflows an offset, we have to start all over.
        overflowRecord = None
        # this is 3-state option: default (None) means automatically use hb.repack or
        # silently fall back if it fails; True, use it and raise error if not possible
        # or it errors out; False, don't use it, even if you can.
        use_hb_repack = font.cfg[USE_HARFBUZZ_REPACKER]
        if self.tableTag in ("GSUB", "GPOS"):
            if use_hb_repack is False:
                log.debug(
                    "hb.repack disabled, compiling '%s' with pure-python serializer",
                    self.tableTag,
                )
            elif not have_uharfbuzz:
                if use_hb_repack is True:
                    raise ImportError("No module named 'uharfbuzz'")
                else:
                    assert use_hb_repack is None
                    log.debug(
                        "uharfbuzz not found, compiling '%s' with pure-python serializer",
                        self.tableTag,
                    )

        if (
            use_hb_repack in (None, True)
            and have_uharfbuzz
            and self.tableTag in ("GSUB", "GPOS")
        ):
            state = RepackerState.HB_FT
        else:
            state = RepackerState.PURE_FT

        hb_first_error_logged = False
        lastOverflowRecord = None
        while True:
            try:
                writer = OTTableWriter(tableTag=self.tableTag)
                self.table.compile(writer, font)
                if state == RepackerState.HB_FT:
                    return self.tryPackingHarfbuzz(writer, hb_first_error_logged)
                elif state == RepackerState.PURE_FT:
                    return self.tryPackingFontTools(writer)
                elif state == RepackerState.FT_FALLBACK:
                    # Run packing with FontTools only, but don't return the result as it will
                    # not be optimally packed. Once a successful packing has been found, state is
                    # changed back to harfbuzz packing to produce the final, optimal, packing.
                    self.tryPackingFontTools(writer)
                    log.debug(
                        "Re-enabling sharing between extensions and switching back to "
                        "harfbuzz+fontTools packing."
                    )
                    state = RepackerState.HB_FT

            except OTLOffsetOverflowError as e:
                hb_first_error_logged = True
                ok = self.tryResolveOverflow(font, e, lastOverflowRecord)
                lastOverflowRecord = e.value

                if ok:
                    continue

                if state is RepackerState.HB_FT:
                    log.debug(
                        "Harfbuzz packing out of resolutions, disabling sharing between extensions and "
                        "switching to fontTools only packing."
                    )
                    state = RepackerState.FT_FALLBACK
                else:
                    raise

    def tryPackingHarfbuzz(self, writer, hb_first_error_logged):
        try:
            log.debug("serializing '%s' with hb.repack", self.tableTag)
            return writer.getAllDataUsingHarfbuzz(self.tableTag)
        except (ValueError, MemoryError, hb.RepackerError) as e:
            # Only log hb repacker errors the first time they occur in
            # the offset-overflow resolution loop, they are just noisy.
            # Maybe we can revisit this if/when uharfbuzz actually gives
            # us more info as to why hb.repack failed...
            if not hb_first_error_logged:
                error_msg = f"{type(e).__name__}"
                if str(e) != "":
                    error_msg += f": {e}"
                log.warning(
                    "hb.repack failed to serialize '%s', attempting fonttools resolutions "
                    "; the error message was: %s",
                    self.tableTag,
                    error_msg,
                )
                hb_first_error_logged = True
            return writer.getAllData(remove_duplicate=False)

    def tryPackingFontTools(self, writer):
        return writer.getAllData()

    def tryResolveOverflow(self, font, e, lastOverflowRecord):
        ok = 0
        if lastOverflowRecord == e.value:
            # Oh well...
            return ok

        overflowRecord = e.value
        log.info("Attempting to fix OTLOffsetOverflowError %s", e)

        if overflowRecord.itemName is None:
            from .otTables import fixLookupOverFlows

            ok = fixLookupOverFlows(font, overflowRecord)
        else:
            from .otTables import fixSubTableOverFlows

            ok = fixSubTableOverFlows(font, overflowRecord)

        if ok:
            return ok

        # Try upgrading lookup to Extension and hope
        # that cross-lookup sharing not happening would
        # fix overflow...
        from .otTables import fixLookupOverFlows

        return fixLookupOverFlows(font, overflowRecord)

    def toXML(self, writer, font):
        self.table.toXML2(writer, font)

    def fromXML(self, name, attrs, content, font):
        from . import otTables

        if not hasattr(self, "table"):
            tableClass = getattr(otTables, self.tableTag)
            self.table = tableClass()
        self.table.fromXML(name, attrs, content, font)
        self.table.populateDefaults()

    def ensureDecompiled(self, recurse=True):
        self.table.ensureDecompiled(recurse=recurse)


# https://github.com/fonttools/fonttools/pull/2285#issuecomment-834652928
assert len(struct.pack("i", 0)) == 4
assert array.array("i").itemsize == 4, "Oops, file a bug against fonttools."


class OTTableReader(object):
    """Helper class to retrieve data from an OpenType table."""

    __slots__ = ("data", "offset", "pos", "localState", "tableTag")

    def __init__(self, data, localState=None, offset=0, tableTag=None):
        self.data = data
        self.offset = offset
        self.pos = offset
        self.localState = localState
        self.tableTag = tableTag

    def advance(self, count):
        self.pos += count

    def seek(self, pos):
        self.pos = pos

    def copy(self):
        other = self.__class__(self.data, self.localState, self.offset, self.tableTag)
        other.pos = self.pos
        return other

    def getSubReader(self, offset):
        offset = self.offset + offset
        return self.__class__(self.data, self.localState, offset, self.tableTag)

    def readValue(self, typecode, staticSize):
        pos = self.pos
        newpos = pos + staticSize
        (value,) = struct.unpack(f">{typecode}", self.data[pos:newpos])
        self.pos = newpos
        return value

    def readArray(self, typecode, staticSize, count):
        pos = self.pos
        newpos = pos + count * staticSize
        value = array.array(typecode, self.data[pos:newpos])
        if sys.byteorder != "big":
            value.byteswap()
        self.pos = newpos
        return value.tolist()

    def readInt8(self):
        return self.readValue("b", staticSize=1)

    def readInt8Array(self, count):
        return self.readArray("b", staticSize=1, count=count)

    def readShort(self):
        return self.readValue("h", staticSize=2)

    def readShortArray(self, count):
        return self.readArray("h", staticSize=2, count=count)

    def readLong(self):
        return self.readValue("i", staticSize=4)

    def readLongArray(self, count):
        return self.readArray("i", staticSize=4, count=count)

    def readUInt8(self):
        return self.readValue("B", staticSize=1)

    def readUInt8Array(self, count):
        return self.readArray("B", staticSize=1, count=count)

    def readUShort(self):
        return self.readValue("H", staticSize=2)

    def readUShortArray(self, count):
        return self.readArray("H", staticSize=2, count=count)

    def readULong(self):
        return self.readValue("I", staticSize=4)

    def readULongArray(self, count):
        return self.readArray("I", staticSize=4, count=count)

    def readUInt24(self):
        pos = self.pos
        newpos = pos + 3
        (value,) = struct.unpack(">l", b"\0" + self.data[pos:newpos])
        self.pos = newpos
        return value

    def readUInt24Array(self, count):
        return [self.readUInt24() for _ in range(count)]

    def readTag(self):
        pos = self.pos
        newpos = pos + 4
        value = Tag(self.data[pos:newpos])
        assert len(value) == 4, value
        self.pos = newpos
        return value

    def readData(self, count):
        pos = self.pos
        newpos = pos + count
        value = self.data[pos:newpos]
        self.pos = newpos
        return value

    def __setitem__(self, name, value):
        state = self.localState.copy() if self.localState else dict()
        state[name] = value
        self.localState = state

    def __getitem__(self, name):
        return self.localState and self.localState[name]

    def __contains__(self, name):
        return self.localState and name in self.localState


class OffsetToWriter(object):
    def __init__(self, subWriter, offsetSize):
        self.subWriter = subWriter
        self.offsetSize = offsetSize

    def __eq__(self, other):
        if type(self) != type(other):
            return NotImplemented
        return self.subWriter == other.subWriter and self.offsetSize == other.offsetSize

    def __hash__(self):
        # only works after self._doneWriting() has been called
        return hash((self.subWriter, self.offsetSize))


class OTTableWriter(object):
    """Helper class to gather and assemble data for OpenType tables."""

    def __init__(self, localState=None, tableTag=None):
        self.items = []
        self.pos = None
        self.localState = localState
        self.tableTag = tableTag
        self.parent = None

    def __setitem__(self, name, value):
        state = self.localState.copy() if self.localState else dict()
        state[name] = value
        self.localState = state

    def __getitem__(self, name):
        return self.localState[name]

    def __delitem__(self, name):
        del self.localState[name]

    # assembler interface

    def getDataLength(self):
        """Return the length of this table in bytes, without subtables."""
        l = 0
        for item in self.items:
            if hasattr(item, "getCountData"):
                l += item.size
            elif hasattr(item, "subWriter"):
                l += item.offsetSize
            else:
                l = l + len(item)
        return l

    def getData(self):
        """Assemble the data for this writer/table, without subtables."""
        items = list(self.items)  # make a shallow copy
        pos = self.pos
        numItems = len(items)
        for i in range(numItems):
            item = items[i]

            if hasattr(item, "subWriter"):
                if item.offsetSize == 4:
                    items[i] = packULong(item.subWriter.pos - pos)
                elif item.offsetSize == 2:
                    try:
                        items[i] = packUShort(item.subWriter.pos - pos)
                    except struct.error:
                        # provide data to fix overflow problem.
                        overflowErrorRecord = self.getOverflowErrorRecord(
                            item.subWriter
                        )

                        raise OTLOffsetOverflowError(overflowErrorRecord)
                elif item.offsetSize == 3:
                    items[i] = packUInt24(item.subWriter.pos - pos)
                else:
                    raise ValueError(item.offsetSize)

        return bytesjoin(items)

    def getDataForHarfbuzz(self):
        """Assemble the data for this writer/table with all offset field set to 0"""
        items = list(self.items)
        packFuncs = {2: packUShort, 3: packUInt24, 4: packULong}
        for i, item in enumerate(items):
            if hasattr(item, "subWriter"):
                # Offset value is not needed in harfbuzz repacker, so setting offset to 0 to avoid overflow here
                if item.offsetSize in packFuncs:
                    items[i] = packFuncs[item.offsetSize](0)
                else:
                    raise ValueError(item.offsetSize)

        return bytesjoin(items)

    def __hash__(self):
        # only works after self._doneWriting() has been called
        return hash(self.items)

    def __ne__(self, other):
        result = self.__eq__(other)
        return result if result is NotImplemented else not result

    def __eq__(self, other):
        if type(self) != type(other):
            return NotImplemented
        return self.items == other.items

    def _doneWriting(self, internedTables, shareExtension=False):
        # Convert CountData references to data string items
        # collapse duplicate table references to a unique entry
        # "tables" are OTTableWriter objects.

        # For Extension Lookup types, we can
        # eliminate duplicates only within the tree under the Extension Lookup,
        # as offsets may exceed 64K even between Extension LookupTable subtables.
        isExtension = hasattr(self, "Extension")

        # Certain versions of Uniscribe reject the font if the GSUB/GPOS top-level
        # arrays (ScriptList, FeatureList, LookupList) point to the same, possibly
        # empty, array.  So, we don't share those.
        # See: https://github.com/fonttools/fonttools/issues/518
        dontShare = hasattr(self, "DontShare")

        if isExtension and not shareExtension:
            internedTables = {}

        items = self.items
        for i in range(len(items)):
            item = items[i]
            if hasattr(item, "getCountData"):
                items[i] = item.getCountData()
            elif hasattr(item, "subWriter"):
                item.subWriter._doneWriting(
                    internedTables, shareExtension=shareExtension
                )
                # At this point, all subwriters are hashable based on their items.
                # (See hash and comparison magic methods above.) So the ``setdefault``
                # call here will return the first writer object we've seen with
                # equal content, or store it in the dictionary if it's not been
                # seen yet. We therefore replace the subwriter object with an equivalent
                # object, which deduplicates the tree.
                if not dontShare:
                    items[i].subWriter = internedTables.setdefault(
                        item.subWriter, item.subWriter
                    )
        self.items = tuple(items)

    def _gatherTables(self, tables, extTables, done):
        # Convert table references in self.items tree to a flat
        # list of tables in depth-first traversal order.
        # "tables" are OTTableWriter objects.
        # We do the traversal in reverse order at each level, in order to
        # resolve duplicate references to be the last reference in the list of tables.
        # For extension lookups, duplicate references can be merged only within the
        # writer tree under the  extension lookup.

        done[id(self)] = True

        numItems = len(self.items)
        iRange = list(range(numItems))
        iRange.reverse()

        isExtension = hasattr(self, "Extension")

        selfTables = tables

        if isExtension:
            assert (
                extTables is not None
            ), "Program or XML editing error. Extension subtables cannot contain extensions subtables"
            tables, extTables, done = extTables, None, {}

        # add Coverage table if it is sorted last.
        sortCoverageLast = False
        if hasattr(self, "sortCoverageLast"):
            # Find coverage table
            for i in range(numItems):
                item = self.items[i]
                if (
                    hasattr(item, "subWriter")
                    and getattr(item.subWriter, "name", None) == "Coverage"
                ):
                    sortCoverageLast = True
                    break
            if id(item.subWriter) not in done:
                item.subWriter._gatherTables(tables, extTables, done)
            else:
                # We're a new parent of item
                pass

        for i in iRange:
            item = self.items[i]
            if not hasattr(item, "subWriter"):
                continue

            if (
                sortCoverageLast
                and (i == 1)
                and getattr(item.subWriter, "name", None) == "Coverage"
            ):
                # we've already 'gathered' it above
                continue

            if id(item.subWriter) not in done:
                item.subWriter._gatherTables(tables, extTables, done)
            else:
                # Item is already written out by other parent
                pass

        selfTables.append(self)

    def _gatherGraphForHarfbuzz(self, tables, obj_list, done, objidx, virtual_edges):
        real_links = []
        virtual_links = []
        item_idx = objidx

        # Merge virtual_links from parent
        for idx in virtual_edges:
            virtual_links.append((0, 0, idx))

        sortCoverageLast = False
        coverage_idx = 0
        if hasattr(self, "sortCoverageLast"):
            # Find coverage table
            for i, item in enumerate(self.items):
                if getattr(item, "name", None) == "Coverage":
                    sortCoverageLast = True
                    if id(item) not in done:
                        coverage_idx = item_idx = item._gatherGraphForHarfbuzz(
                            tables, obj_list, done, item_idx, virtual_edges
                        )
                    else:
                        coverage_idx = done[id(item)]
                    virtual_edges.append(coverage_idx)
                    break

        child_idx = 0
        offset_pos = 0
        for i, item in enumerate(self.items):
            if hasattr(item, "subWriter"):
                pos = offset_pos
            elif hasattr(item, "getCountData"):
                offset_pos += item.size
                continue
            else:
                offset_pos = offset_pos + len(item)
                continue

            if id(item.subWriter) not in done:
                child_idx = item_idx = item.subWriter._gatherGraphForHarfbuzz(
                    tables, obj_list, done, item_idx, virtual_edges
                )
            else:
                child_idx = done[id(item.subWriter)]

            real_edge = (pos, item.offsetSize, child_idx)
            real_links.append(real_edge)
            offset_pos += item.offsetSize

        tables.append(self)
        obj_list.append((real_links, virtual_links))
        item_idx += 1
        done[id(self)] = item_idx
        if sortCoverageLast:
            virtual_edges.pop()

        return item_idx

    def getAllDataUsingHarfbuzz(self, tableTag):
        """The Whole table is represented as a Graph.
        Assemble graph data and call Harfbuzz repacker to pack the table.
        Harfbuzz repacker is faster and retain as much sub-table sharing as possible, see also:
        https://github.com/harfbuzz/harfbuzz/blob/main/docs/repacker.md
        The input format for hb.repack() method is explained here:
        https://github.com/harfbuzz/uharfbuzz/blob/main/src/uharfbuzz/_harfbuzz.pyx#L1149
        """
        internedTables = {}
        self._doneWriting(internedTables, shareExtension=True)
        tables = []
        obj_list = []
        done = {}
        objidx = 0
        virtual_edges = []
        self._gatherGraphForHarfbuzz(tables, obj_list, done, objidx, virtual_edges)
        # Gather all data in two passes: the absolute positions of all
        # subtable are needed before the actual data can be assembled.
        pos = 0
        for table in tables:
            table.pos = pos
            pos = pos + table.getDataLength()

        data = []
        for table in tables:
            tableData = table.getDataForHarfbuzz()
            data.append(tableData)

        if hasattr(hb, "repack_with_tag"):
            return hb.repack_with_tag(str(tableTag), data, obj_list)
        else:
            return hb.repack(data, obj_list)

    def getAllData(self, remove_duplicate=True):
        """Assemble all data, including all subtables."""
        if remove_duplicate:
            internedTables = {}
            self._doneWriting(internedTables)
        tables = []
        extTables = []
        done = {}
        self._gatherTables(tables, extTables, done)
        tables.reverse()
        extTables.reverse()
        # Gather all data in two passes: the absolute positions of all
        # subtable are needed before the actual data can be assembled.
        pos = 0
        for table in tables:
            table.pos = pos
            pos = pos + table.getDataLength()

        for table in extTables:
            table.pos = pos
            pos = pos + table.getDataLength()

        data = []
        for table in tables:
            tableData = table.getData()
            data.append(tableData)

        for table in extTables:
            tableData = table.getData()
            data.append(tableData)

        return bytesjoin(data)

    # interface for gathering data, as used by table.compile()

    def getSubWriter(self):
        subwriter = self.__class__(self.localState, self.tableTag)
        subwriter.parent = (
            self  # because some subtables have idential values, we discard
        )
        # the duplicates under the getAllData method. Hence some
        # subtable writers can have more than one parent writer.
        # But we just care about first one right now.
        return subwriter

    def writeValue(self, typecode, value):
        self.items.append(struct.pack(f">{typecode}", value))

    def writeArray(self, typecode, values):
        a = array.array(typecode, values)
        if sys.byteorder != "big":
            a.byteswap()
        self.items.append(a.tobytes())

    def writeInt8(self, value):
        assert -128 <= value < 128, value
        self.items.append(struct.pack(">b", value))

    def writeInt8Array(self, values):
        self.writeArray("b", values)

    def writeShort(self, value):
        assert -32768 <= value < 32768, value
        self.items.append(struct.pack(">h", value))

    def writeShortArray(self, values):
        self.writeArray("h", values)

    def writeLong(self, value):
        self.items.append(struct.pack(">i", value))

    def writeLongArray(self, values):
        self.writeArray("i", values)

    def writeUInt8(self, value):
        assert 0 <= value < 256, value
        self.items.append(struct.pack(">B", value))

    def writeUInt8Array(self, values):
        self.writeArray("B", values)

    def writeUShort(self, value):
        assert 0 <= value < 0x10000, value
        self.items.append(struct.pack(">H", value))

    def writeUShortArray(self, values):
        self.writeArray("H", values)

    def writeULong(self, value):
        self.items.append(struct.pack(">I", value))

    def writeULongArray(self, values):
        self.writeArray("I", values)

    def writeUInt24(self, value):
        assert 0 <= value < 0x1000000, value
        b = struct.pack(">L", value)
        self.items.append(b[1:])

    def writeUInt24Array(self, values):
        for value in values:
            self.writeUInt24(value)

    def writeTag(self, tag):
        tag = Tag(tag).tobytes()
        assert len(tag) == 4, tag
        self.items.append(tag)

    def writeSubTable(self, subWriter, offsetSize):
        self.items.append(OffsetToWriter(subWriter, offsetSize))

    def writeCountReference(self, table, name, size=2, value=None):
        ref = CountReference(table, name, size=size, value=value)
        self.items.append(ref)
        return ref

    def writeStruct(self, format, values):
        data = struct.pack(*(format,) + values)
        self.items.append(data)

    def writeData(self, data):
        self.items.append(data)

    def getOverflowErrorRecord(self, item):
        LookupListIndex = SubTableIndex = itemName = itemIndex = None
        if self.name == "LookupList":
            LookupListIndex = item.repeatIndex
        elif self.name == "Lookup":
            LookupListIndex = self.repeatIndex
            SubTableIndex = item.repeatIndex
        else:
            itemName = getattr(item, "name", "<none>")
            if hasattr(item, "repeatIndex"):
                itemIndex = item.repeatIndex
            if self.name == "SubTable":
                LookupListIndex = self.parent.repeatIndex
                SubTableIndex = self.repeatIndex
            elif self.name == "ExtSubTable":
                LookupListIndex = self.parent.parent.repeatIndex
                SubTableIndex = self.parent.repeatIndex
            else:  # who knows how far below the SubTable level we are! Climb back up to the nearest subtable.
                itemName = ".".join([self.name, itemName])
                p1 = self.parent
                while p1 and p1.name not in ["ExtSubTable", "SubTable"]:
                    itemName = ".".join([p1.name, itemName])
                    p1 = p1.parent
                if p1:
                    if p1.name == "ExtSubTable":
                        LookupListIndex = p1.parent.parent.repeatIndex
                        SubTableIndex = p1.parent.repeatIndex
                    else:
                        LookupListIndex = p1.parent.repeatIndex
                        SubTableIndex = p1.repeatIndex

        return OverflowErrorRecord(
            (self.tableTag, LookupListIndex, SubTableIndex, itemName, itemIndex)
        )


class CountReference(object):
    """A reference to a Count value, not a count of references."""

    def __init__(self, table, name, size=None, value=None):
        self.table = table
        self.name = name
        self.size = size
        if value is not None:
            self.setValue(value)

    def setValue(self, value):
        table = self.table
        name = self.name
        if table[name] is None:
            table[name] = value
        else:
            assert table[name] == value, (name, table[name], value)

    def getValue(self):
        return self.table[self.name]

    def getCountData(self):
        v = self.table[self.name]
        if v is None:
            v = 0
        return {1: packUInt8, 2: packUShort, 4: packULong}[self.size](v)


def packUInt8(value):
    return struct.pack(">B", value)


def packUShort(value):
    return struct.pack(">H", value)


def packULong(value):
    assert 0 <= value < 0x100000000, value
    return struct.pack(">I", value)


def packUInt24(value):
    assert 0 <= value < 0x1000000, value
    return struct.pack(">I", value)[1:]


class BaseTable(object):
    """Generic base class for all OpenType (sub)tables."""

    def __getattr__(self, attr):
        reader = self.__dict__.get("reader")
        if reader:
            del self.reader
            font = self.font
            del self.font
            self.decompile(reader, font)
            return getattr(self, attr)

        raise AttributeError(attr)

    def ensureDecompiled(self, recurse=False):
        reader = self.__dict__.get("reader")
        if reader:
            del self.reader
            font = self.font
            del self.font
            self.decompile(reader, font)
        if recurse:
            for subtable in self.iterSubTables():
                subtable.value.ensureDecompiled(recurse)

    def __getstate__(self):
        # before copying/pickling 'lazy' objects, make a shallow copy of OTTableReader
        # https://github.com/fonttools/fonttools/issues/2965
        if "reader" in self.__dict__:
            state = self.__dict__.copy()
            state["reader"] = self.__dict__["reader"].copy()
            return state
        return self.__dict__

    @classmethod
    def getRecordSize(cls, reader):
        totalSize = 0
        for conv in cls.converters:
            size = conv.getRecordSize(reader)
            if size is NotImplemented:
                return NotImplemented
            countValue = 1
            if conv.repeat:
                if conv.repeat in reader:
                    countValue = reader[conv.repeat] + conv.aux
                else:
                    return NotImplemented
            totalSize += size * countValue
        return totalSize

    def getConverters(self):
        return self.converters

    def getConverterByName(self, name):
        return self.convertersByName[name]

    def populateDefaults(self, propagator=None):
        for conv in self.getConverters():
            if conv.repeat:
                if not hasattr(self, conv.name):
                    setattr(self, conv.name, [])
                countValue = len(getattr(self, conv.name)) - conv.aux
                try:
                    count_conv = self.getConverterByName(conv.repeat)
                    setattr(self, conv.repeat, countValue)
                except KeyError:
                    # conv.repeat is a propagated count
                    if propagator and conv.repeat in propagator:
                        propagator[conv.repeat].setValue(countValue)
            else:
                if conv.aux and not eval(conv.aux, None, self.__dict__):
                    continue
                if hasattr(self, conv.name):
                    continue  # Warn if it should NOT be present?!
                if hasattr(conv, "writeNullOffset"):
                    setattr(self, conv.name, None)  # Warn?
                # elif not conv.isCount:
                # 	# Warn?
                # 	pass
                if hasattr(conv, "DEFAULT"):
                    # OptionalValue converters (e.g. VarIndex)
                    setattr(self, conv.name, conv.DEFAULT)

    def decompile(self, reader, font):
        self.readFormat(reader)
        table = {}
        self.__rawTable = table  # for debugging
        for conv in self.getConverters():
            if conv.name == "SubTable":
                conv = conv.getConverter(reader.tableTag, table["LookupType"])
            if conv.name == "ExtSubTable":
                conv = conv.getConverter(reader.tableTag, table["ExtensionLookupType"])
            if conv.name == "FeatureParams":
                conv = conv.getConverter(reader["FeatureTag"])
            if conv.name == "SubStruct":
                conv = conv.getConverter(reader.tableTag, table["MorphType"])
            try:
                if conv.repeat:
                    if isinstance(conv.repeat, int):
                        countValue = conv.repeat
                    elif conv.repeat in table:
                        countValue = table[conv.repeat]
                    else:
                        # conv.repeat is a propagated count
                        countValue = reader[conv.repeat]
                    countValue += conv.aux
                    table[conv.name] = conv.readArray(reader, font, table, countValue)
                else:
                    if conv.aux and not eval(conv.aux, None, table):
                        continue
                    table[conv.name] = conv.read(reader, font, table)
                    if conv.isPropagated:
                        reader[conv.name] = table[conv.name]
            except Exception as e:
                name = conv.name
                e.args = e.args + (name,)
                raise

        if hasattr(self, "postRead"):
            self.postRead(table, font)
        else:
            self.__dict__.update(table)

        del self.__rawTable  # succeeded, get rid of debugging info

    def compile(self, writer, font):
        self.ensureDecompiled()
        # TODO Following hack to be removed by rewriting how FormatSwitching tables
        # are handled.
        # https://github.com/fonttools/fonttools/pull/2238#issuecomment-805192631
        if hasattr(self, "preWrite"):
            deleteFormat = not hasattr(self, "Format")
            table = self.preWrite(font)
            deleteFormat = deleteFormat and hasattr(self, "Format")
        else:
            deleteFormat = False
            table = self.__dict__.copy()

        # some count references may have been initialized in a custom preWrite; we set
        # these in the writer's state beforehand (instead of sequentially) so they will
        # be propagated to all nested subtables even if the count appears in the current
        # table only *after* the offset to the subtable that it is counting.
        for conv in self.getConverters():
            if conv.isCount and conv.isPropagated:
                value = table.get(conv.name)
                if isinstance(value, CountReference):
                    writer[conv.name] = value

        if hasattr(self, "sortCoverageLast"):
            writer.sortCoverageLast = 1

        if hasattr(self, "DontShare"):
            writer.DontShare = True

        if hasattr(self.__class__, "LookupType"):
            writer["LookupType"].setValue(self.__class__.LookupType)

        self.writeFormat(writer)
        for conv in self.getConverters():
            value = table.get(
                conv.name
            )  # TODO Handle defaults instead of defaulting to None!
            if conv.repeat:
                if value is None:
                    value = []
                countValue = len(value) - conv.aux
                if isinstance(conv.repeat, int):
                    assert len(value) == conv.repeat, "expected %d values, got %d" % (
                        conv.repeat,
                        len(value),
                    )
                elif conv.repeat in table:
                    CountReference(table, conv.repeat, value=countValue)
                else:
                    # conv.repeat is a propagated count
                    writer[conv.repeat].setValue(countValue)
                try:
                    conv.writeArray(writer, font, table, value)
                except Exception as e:
                    e.args = e.args + (conv.name + "[]",)
                    raise
            elif conv.isCount:
                # Special-case Count values.
                # Assumption: a Count field will *always* precede
                # the actual array(s).
                # We need a default value, as it may be set later by a nested
                # table. We will later store it here.
                # We add a reference: by the time the data is assembled
                # the Count value will be filled in.
                # We ignore the current count value since it will be recomputed,
                # unless it's a CountReference that was already initialized in a custom preWrite.
                if isinstance(value, CountReference):
                    ref = value
                    ref.size = conv.staticSize
                    writer.writeData(ref)
                    table[conv.name] = ref.getValue()
                else:
                    ref = writer.writeCountReference(table, conv.name, conv.staticSize)
                    table[conv.name] = None
                if conv.isPropagated:
                    writer[conv.name] = ref
            elif conv.isLookupType:
                # We make sure that subtables have the same lookup type,
                # and that the type is the same as the one set on the
                # Lookup object, if any is set.
                if conv.name not in table:
                    table[conv.name] = None
                ref = writer.writeCountReference(
                    table, conv.name, conv.staticSize, table[conv.name]
                )
                writer["LookupType"] = ref
            else:
                if conv.aux and not eval(conv.aux, None, table):
                    continue
                try:
                    conv.write(writer, font, table, value)
                except Exception as e:
                    name = value.__class__.__name__ if value is not None else conv.name
                    e.args = e.args + (name,)
                    raise
                if conv.isPropagated:
                    writer[conv.name] = value

        if deleteFormat:
            del self.Format

    def readFormat(self, reader):
        pass

    def writeFormat(self, writer):
        pass

    def toXML(self, xmlWriter, font, attrs=None, name=None):
        tableName = name if name else self.__class__.__name__
        if attrs is None:
            attrs = []
        if hasattr(self, "Format"):
            attrs = attrs + [("Format", self.Format)]
        xmlWriter.begintag(tableName, attrs)
        xmlWriter.newline()
        self.toXML2(xmlWriter, font)
        xmlWriter.endtag(tableName)
        xmlWriter.newline()

    def toXML2(self, xmlWriter, font):
        # Simpler variant of toXML, *only* for the top level tables (like GPOS, GSUB).
        # This is because in TTX our parent writes our main tag, and in otBase.py we
        # do it ourselves. I think I'm getting schizophrenic...
        for conv in self.getConverters():
            if conv.repeat:
                value = getattr(self, conv.name, [])
                for i in range(len(value)):
                    item = value[i]
                    conv.xmlWrite(xmlWriter, font, item, conv.name, [("index", i)])
            else:
                if conv.aux and not eval(conv.aux, None, vars(self)):
                    continue
                value = getattr(
                    self, conv.name, None
                )  # TODO Handle defaults instead of defaulting to None!
                conv.xmlWrite(xmlWriter, font, value, conv.name, [])

    def fromXML(self, name, attrs, content, font):
        try:
            conv = self.getConverterByName(name)
        except KeyError:
            raise  # XXX on KeyError, raise nice error
        value = conv.xmlRead(attrs, content, font)
        if conv.repeat:
            seq = getattr(self, conv.name, None)
            if seq is None:
                seq = []
                setattr(self, conv.name, seq)
            seq.append(value)
        else:
            setattr(self, conv.name, value)

    def __ne__(self, other):
        result = self.__eq__(other)
        return result if result is NotImplemented else not result

    def __eq__(self, other):
        if type(self) != type(other):
            return NotImplemented

        self.ensureDecompiled()
        other.ensureDecompiled()

        return self.__dict__ == other.__dict__

    class SubTableEntry(NamedTuple):
        """See BaseTable.iterSubTables()"""

        name: str
        value: "BaseTable"
        index: Optional[int] = None  # index into given array, None for single values

    def iterSubTables(self) -> Iterator[SubTableEntry]:
        """Yield (name, value, index) namedtuples for all subtables of current table.

        A sub-table is an instance of BaseTable (or subclass thereof) that is a child
        of self, the current parent table.
        The tuples also contain the attribute name (str) of the of parent table to get
        a subtable, and optionally, for lists of subtables (i.e. attributes associated
        with a converter that has a 'repeat'), an index into the list containing the
        given subtable value.
        This method can be useful to traverse trees of otTables.
        """
        for conv in self.getConverters():
            name = conv.name
            value = getattr(self, name, None)
            if value is None:
                continue
            if isinstance(value, BaseTable):
                yield self.SubTableEntry(name, value)
            elif isinstance(value, list):
                yield from (
                    self.SubTableEntry(name, v, index=i)
                    for i, v in enumerate(value)
                    if isinstance(v, BaseTable)
                )

    # instance (not @class)method for consistency with FormatSwitchingBaseTable
    def getVariableAttrs(self):
        return getVariableAttrs(self.__class__)


class FormatSwitchingBaseTable(BaseTable):
    """Minor specialization of BaseTable, for tables that have multiple
    formats, eg. CoverageFormat1 vs. CoverageFormat2."""

    @classmethod
    def getRecordSize(cls, reader):
        return NotImplemented

    def getConverters(self):
        try:
            fmt = self.Format
        except AttributeError:
            # some FormatSwitchingBaseTables (e.g. Coverage) no longer have 'Format'
            # attribute after fully decompiled, only gain one in preWrite before being
            # recompiled. In the decompiled state, these hand-coded classes defined in
            # otTables.py lose their format-specific nature and gain more high-level
            # attributes that are not tied to converters.
            return []
        return self.converters.get(self.Format, [])

    def getConverterByName(self, name):
        return self.convertersByName[self.Format][name]

    def readFormat(self, reader):
        self.Format = reader.readUShort()

    def writeFormat(self, writer):
        writer.writeUShort(self.Format)

    def toXML(self, xmlWriter, font, attrs=None, name=None):
        BaseTable.toXML(self, xmlWriter, font, attrs, name)

    def getVariableAttrs(self):
        return getVariableAttrs(self.__class__, self.Format)


class UInt8FormatSwitchingBaseTable(FormatSwitchingBaseTable):
    def readFormat(self, reader):
        self.Format = reader.readUInt8()

    def writeFormat(self, writer):
        writer.writeUInt8(self.Format)


formatSwitchingBaseTables = {
    "uint16": FormatSwitchingBaseTable,
    "uint8": UInt8FormatSwitchingBaseTable,
}


def getFormatSwitchingBaseTableClass(formatType):
    try:
        return formatSwitchingBaseTables[formatType]
    except KeyError:
        raise TypeError(f"Unsupported format type: {formatType!r}")


# memoize since these are parsed from otData.py, thus stay constant
@lru_cache()
def getVariableAttrs(cls: BaseTable, fmt: Optional[int] = None) -> Tuple[str]:
    """Return sequence of variable table field names (can be empty).

    Attributes are deemed "variable" when their otData.py's description contain
    'VarIndexBase + {offset}', e.g. COLRv1 PaintVar* tables.
    """
    if not issubclass(cls, BaseTable):
        raise TypeError(cls)
    if issubclass(cls, FormatSwitchingBaseTable):
        if fmt is None:
            raise TypeError(f"'fmt' is required for format-switching {cls.__name__}")
        converters = cls.convertersByName[fmt]
    else:
        converters = cls.convertersByName
    # assume if no 'VarIndexBase' field is present, table has no variable fields
    if "VarIndexBase" not in converters:
        return ()
    varAttrs = {}
    for name, conv in converters.items():
        offset = conv.getVarIndexOffset()
        if offset is not None:
            varAttrs[name] = offset
    return tuple(sorted(varAttrs, key=varAttrs.__getitem__))


#
# Support for ValueRecords
#
# This data type is so different from all other OpenType data types that
# it requires quite a bit of code for itself. It even has special support
# in OTTableReader and OTTableWriter...
#

valueRecordFormat = [
    # 	Mask	 Name		isDevice signed
    (0x0001, "XPlacement", 0, 1),
    (0x0002, "YPlacement", 0, 1),
    (0x0004, "XAdvance", 0, 1),
    (0x0008, "YAdvance", 0, 1),
    (0x0010, "XPlaDevice", 1, 0),
    (0x0020, "YPlaDevice", 1, 0),
    (0x0040, "XAdvDevice", 1, 0),
    (0x0080, "YAdvDevice", 1, 0),
    # 	reserved:
    (0x0100, "Reserved1", 0, 0),
    (0x0200, "Reserved2", 0, 0),
    (0x0400, "Reserved3", 0, 0),
    (0x0800, "Reserved4", 0, 0),
    (0x1000, "Reserved5", 0, 0),
    (0x2000, "Reserved6", 0, 0),
    (0x4000, "Reserved7", 0, 0),
    (0x8000, "Reserved8", 0, 0),
]


def _buildDict():
    d = {}
    for mask, name, isDevice, signed in valueRecordFormat:
        d[name] = mask, isDevice, signed
    return d


valueRecordFormatDict = _buildDict()


class ValueRecordFactory(object):
    """Given a format code, this object convert ValueRecords."""

    def __init__(self, valueFormat):
        format = []
        for mask, name, isDevice, signed in valueRecordFormat:
            if valueFormat & mask:
                format.append((name, isDevice, signed))
        self.format = format

    def __len__(self):
        return len(self.format)

    def readValueRecord(self, reader, font):
        format = self.format
        if not format:
            return None
        valueRecord = ValueRecord()
        for name, isDevice, signed in format:
            if signed:
                value = reader.readShort()
            else:
                value = reader.readUShort()
            if isDevice:
                if value:
                    from . import otTables

                    subReader = reader.getSubReader(value)
                    value = getattr(otTables, name)()
                    value.decompile(subReader, font)
                else:
                    value = None
            setattr(valueRecord, name, value)
        return valueRecord

    def writeValueRecord(self, writer, font, valueRecord):
        for name, isDevice, signed in self.format:
            value = getattr(valueRecord, name, 0)
            if isDevice:
                if value:
                    subWriter = writer.getSubWriter()
                    writer.writeSubTable(subWriter, offsetSize=2)
                    value.compile(subWriter, font)
                else:
                    writer.writeUShort(0)
            elif signed:
                writer.writeShort(value)
            else:
                writer.writeUShort(value)


class ValueRecord(object):
    # see ValueRecordFactory

    def __init__(self, valueFormat=None, src=None):
        if valueFormat is not None:
            for mask, name, isDevice, signed in valueRecordFormat:
                if valueFormat & mask:
                    setattr(self, name, None if isDevice else 0)
            if src is not None:
                for key, val in src.__dict__.items():
                    if not hasattr(self, key):
                        continue
                    setattr(self, key, val)
        elif src is not None:
            self.__dict__ = src.__dict__.copy()

    def getFormat(self):
        format = 0
        for name in self.__dict__.keys():
            format = format | valueRecordFormatDict[name][0]
        return format

    def getEffectiveFormat(self):
        format = 0
        for name, value in self.__dict__.items():
            if value:
                format = format | valueRecordFormatDict[name][0]
        return format

    def toXML(self, xmlWriter, font, valueName, attrs=None):
        if attrs is None:
            simpleItems = []
        else:
            simpleItems = list(attrs)
        for mask, name, isDevice, format in valueRecordFormat[:4]:  # "simple" values
            if hasattr(self, name):
                simpleItems.append((name, getattr(self, name)))
        deviceItems = []
        for mask, name, isDevice, format in valueRecordFormat[4:8]:  # device records
            if hasattr(self, name):
                device = getattr(self, name)
                if device is not None:
                    deviceItems.append((name, device))
        if deviceItems:
            xmlWriter.begintag(valueName, simpleItems)
            xmlWriter.newline()
            for name, deviceRecord in deviceItems:
                if deviceRecord is not None:
                    deviceRecord.toXML(xmlWriter, font, name=name)
            xmlWriter.endtag(valueName)
            xmlWriter.newline()
        else:
            xmlWriter.simpletag(valueName, simpleItems)
            xmlWriter.newline()

    def fromXML(self, name, attrs, content, font):
        from . import otTables

        for k, v in attrs.items():
            setattr(self, k, int(v))
        for element in content:
            if not isinstance(element, tuple):
                continue
            name, attrs, content = element
            value = getattr(otTables, name)()
            for elem2 in content:
                if not isinstance(elem2, tuple):
                    continue
                name2, attrs2, content2 = elem2
                value.fromXML(name2, attrs2, content2, font)
            setattr(self, name, value)

    def __ne__(self, other):
        result = self.__eq__(other)
        return result if result is NotImplemented else not result

    def __eq__(self, other):
        if type(self) != type(other):
            return NotImplemented
        return self.__dict__ == other.__dict__
