# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at https://mozilla.org/MPL/2.0/.

# fmt: off

from __future__ import annotations

import functools
import os
from typing import Any, TypeVar

from WebIDL import (
    IDLExternalInterface,
    IDLSequenceType,
    IDLWrapperType,
    WebIDLError,
    IDLEnum,
    IDLObject,
    IDLObjectWithIdentifier,
    IDLType,
    IDLTypedef,
    IDLInterfaceOrNamespace,
    IDLDictionary,
    IDLCallback,
    IDLAttribute,
    IDLMethod,
    IDLInterfaceMember,
)

TargetType = TypeVar('TargetType')
def assert_type(object: Any, cls: type[TargetType]) -> TargetType:
    assert isinstance(object, cls)
    return object

FilterItemsType = TypeVar('FilterItemsType', bound=IDLObjectWithIdentifier)
class Configuration:
    """
    Represents global configuration state based on IDL parse data and
    the configuration file.
    """
    glbl: dict[str, Any]
    enumConfig: dict[str, Any]
    dictConfig: dict[str, Any]
    unionConfig: dict[str, Any]
    descriptors: list[Descriptor]
    interfaces: dict[str, IDLInterfaceOrNamespace]
    enums: list[IDLEnum]
    typedefs: list[IDLTypedef]
    dictionaries: list[IDLDictionary]
    callbacks: list[IDLCallback]

    def __init__(self, filename: str, parseData: list[IDLObjectWithIdentifier]) -> None:
        # Read the configuration file.
        glbl = {}
        exec(compile(open(filename).read(), filename, 'exec'), glbl)
        config = glbl['DOMInterfaces']
        self.enumConfig = glbl['Enums']
        self.dictConfig = glbl['Dictionaries']
        self.unionConfig = glbl['Unions']

        # Build descriptors for all the interfaces we have in the parse data.
        # This allows callers to specify a subset of interfaces by filtering
        # |parseData|.
        self.descriptors = []
        self.interfaces = {}
        self.maxProtoChainLength = 0
        for thing in parseData:
            # Servo does not support external interfaces.
            if isinstance(thing, IDLExternalInterface):
                raise WebIDLError("Servo does not support external interfaces.",
                                  [thing.location])

            assert not thing.isType()

            if not thing.isInterface() and not thing.isNamespace():
                continue

            iface = thing
            assert isinstance(iface, IDLInterfaceOrNamespace)
            self.interfaces[iface.identifier.name] = iface
            if iface.identifier.name not in config:
                entry = {}
            else:
                entry = config[iface.identifier.name]
            if not isinstance(entry, list):
                assert isinstance(entry, dict)
                entry = [entry]
            self.descriptors.extend(
                [Descriptor(self, iface, x) for x in entry])

        # Mark the descriptors for which only a single nativeType implements
        # an interface.
        for descriptor in self.descriptors:
            interfaceName = descriptor.interface.identifier.name
            otherDescriptors = [d for d in self.descriptors
                                if d.interface.identifier.name == interfaceName]
            descriptor.uniqueImplementation = len(otherDescriptors) == 1

        self.enums = [assert_type(e, IDLEnum) for e in parseData if e.isEnum()]
        self.typedefs = [assert_type(e, IDLTypedef) for e in parseData if e.isTypedef()]
        self.dictionaries = [assert_type(d, IDLDictionary) for d in parseData if d.isDictionary()]
        self.callbacks = [assert_type(c, IDLCallback) for c in parseData if
                          c.isCallback() and not c.isInterface()]

        # Keep the descriptor list sorted for determinism.
        def cmp(x: str, y: str) -> int:
            return (x > y) - (x < y)
        self.descriptors.sort(key=functools.cmp_to_key(lambda x, y: cmp(x.name, y.name)))

    def getInterface(self, ifname: str) -> IDLInterfaceOrNamespace:
        return self.interfaces[ifname]

    def getDescriptors(self, **filters: Any) -> list[Descriptor]:
        """Gets the descriptors that match the given filters."""
        curr = self.descriptors
        for key, val in filters.items():
            if key == 'webIDLFile':
                def getter(x: Descriptor) -> str:
                    return x.interface.location.filename
            elif key == 'hasInterfaceObject':
                def getter(x: Descriptor) -> bool:
                    return x.interface.hasInterfaceObject()
            elif key == 'isCallback':
                def getter(x: Descriptor) -> bool:
                    return x.interface.isCallback()
            elif key == 'isNamespace':
                def getter(x: Descriptor) -> bool:
                    return x.interface.isNamespace()
            elif key == 'isJSImplemented':
                def getter(x: Descriptor) -> bool:
                    return x.interface.isJSImplemented()
            elif key == 'isGlobal':
                def getter(x: Descriptor) -> bool:
                    return x.isGlobal()
            elif key == 'isInline':
                def getter(x: Descriptor) -> bool:
                    return x.interface.getExtendedAttribute('Inline') is not None
            elif key == 'isExposedConditionally':
                def getter(x: Descriptor) -> bool:
                    return x.interface.isExposedConditionally()
            elif key == 'isIteratorInterface':
                def getter(x: Descriptor) -> bool:
                    return x.interface.isIteratorInterface()
            else:
                def getter(x: Descriptor) -> Any:
                    return getattr(x, key)
            curr = [x for x in curr if getter(x) == val]
        return curr

    def getEnums(self, webIDLFile: str) -> list[IDLEnum]:
        return [e for e in self.enums if e.filename == webIDLFile]

    def getEnumConfig(self, name: str) -> dict[str, Any]:
        return self.enumConfig.get(name, {})

    def getTypedefs(self, webIDLFile: str) -> list[IDLTypedef]:
        return [e for e in self.typedefs if e.filename == webIDLFile]

    @staticmethod
    def _filterForFile(items: list[FilterItemsType], webIDLFile: str = "") -> list[FilterItemsType]:
        """Gets the items that match the given filters."""
        if not webIDLFile:
            return items

        return [x for x in items if x.filename == webIDLFile]

    def getUnionConfig(self, name: str) -> dict[str, Any]:
        return self.unionConfig.get(name, {})

    def getDictionaries(self, webIDLFile: str = "") -> list[IDLDictionary]:
        return self._filterForFile(self.dictionaries, webIDLFile=webIDLFile)

    def getDictConfig(self, name: str) -> dict[str, Any]:
        return self.dictConfig.get(name, {})

    def getCallbacks(self, webIDLFile: str = "") -> list[IDLCallback]:
        return self._filterForFile(self.callbacks, webIDLFile=webIDLFile)

    def getDescriptor(self, interfaceName: str) -> Descriptor:
        """
        Gets the appropriate descriptor for the given interface name.
        """
        iface = self.getInterface(interfaceName)
        descriptors = self.getDescriptors(interface=iface)

        # We should have exactly one result.
        if len(descriptors) != 1:
            raise NoSuchDescriptorError("For " + interfaceName + " found "
                                        + str(len(descriptors)) + " matches")
        return descriptors[0]

    def getDescriptorProvider(self) -> DescriptorProvider:
        """
        Gets a descriptor provider that can provide descriptors as needed.
        """
        return DescriptorProvider(self)


class NoSuchDescriptorError(TypeError):
    def __init__(self, str: str) -> None:
        TypeError.__init__(self, str)


class DescriptorProvider:
    """
    A way of getting descriptors for interface names
    """
    def __init__(self, config: Configuration) -> None:
        self.config = config

    def getDescriptor(self, interfaceName: str) -> Descriptor:
        """
        Gets the appropriate descriptor for the given interface name given the
        context of the current descriptor.
        """
        return self.config.getDescriptor(interfaceName)


def MemberIsLegacyUnforgeable(member: IDLAttribute | IDLMethod, descriptor: Descriptor) -> bool:
    return ((member.isAttr() or member.isMethod())
            and not member.isStatic()
            and (member.isLegacyUnforgeable()
                 or bool(descriptor.interface.getExtendedAttribute("LegacyUnforgeable"))))


class Descriptor(DescriptorProvider):
    """
    Represents a single descriptor for an interface. See Bindings.conf.
    """
    interface: IDLInterfaceOrNamespace
    uniqueImplementation: bool

    def __init__(self, config: Configuration, interface: IDLInterfaceOrNamespace, desc: dict[str, Any]) -> None:
        DescriptorProvider.__init__(self, config)
        self.interface = interface

        if not self.isExposedConditionally():
            if interface.parent and interface.parent.isExposedConditionally():
                raise TypeError("%s is not conditionally exposed but inherits from "
                                "%s which is" %
                                (interface.identifier.name, interface.parent.identifier.name))

        # Read the desc, and fill in the relevant defaults.
        ifaceName = self.interface.identifier.name
        nativeTypeDefault = ifaceName

        # For generated iterator interfaces for other iterable interfaces, we
        # just use IterableIterator as the native type, templated on the
        # nativeType of the iterable interface. That way we can have a
        # templated implementation for all the duplicated iterator
        # functionality.
        prefix = "D::"
        if self.interface.isIteratorInterface():
            assert self.interface.iterableInterface is not None
            itrName = self.interface.iterableInterface.identifier.name
            itrDesc = self.getDescriptor(itrName)
            nativeTypeDefault = iteratorNativeType(itrDesc)
            prefix = ""

        typeName = desc.get('nativeType', nativeTypeDefault)

        spiderMonkeyInterface = desc.get('spiderMonkeyInterface', False)

        # Callback and SpiderMonkey types do not use JS smart pointers, so we should not use the
        # built-in rooting mechanisms for them.
        if spiderMonkeyInterface:
            self.returnType = 'Rc<%s>' % typeName
            self.argumentType = '&%s' % typeName
            self.nativeType = typeName
            pathDefault = 'crate::dom::types::%s' % typeName
        elif self.interface.isCallback():
            ty = 'crate::codegen::GenericBindings::%sBinding::%s' % (ifaceName, ifaceName)
            pathDefault = ty
            self.returnType = "Rc<%s<D>>" % ty
            self.argumentType = "???"
            self.nativeType = ty
        else:
            self.returnType = "DomRoot<%s%s>" % (prefix, typeName)
            self.argumentType = "&%s%s" % (prefix, typeName)
            self.nativeType = "*const %s%s" % (prefix, typeName)
            if self.interface.isIteratorInterface():
                pathDefault = 'crate::iterable::IterableIterator'
            else:
                pathDefault = 'crate::dom::types::%s' % MakeNativeName(typeName)

        self.concreteType = "%s%s" % (prefix, typeName)
        self.register = desc.get('register', True)
        self.path = desc.get('path', pathDefault)
        self.inRealmMethods = [name for name in desc.get('inRealms', [])]
        self.canGcMethods = [name for name in desc.get('canGc', [])]
        self.additionalTraits = [name for name in desc.get('additionalTraits', [])]
        self.bindingPath = f"{getModuleFromObject(self.interface)}::{ifaceName}_Binding"
        self.outerObjectHook = desc.get('outerObjectHook', 'None')
        self.proxy = False
        self.weakReferenceable = desc.get('weakReferenceable', False)
        self.useSystemCompartment = desc.get('useSystemCompartment', False)

        # If we're concrete, we need to crawl our ancestor interfaces and mark
        # them as having a concrete descendant.
        self.concrete = (not self.interface.isCallback()
                         and not self.interface.isNamespace()
                         and not self.interface.getExtendedAttribute("Abstract")
                         and not self.interface.getExtendedAttribute("Inline")
                         and not spiderMonkeyInterface)
        self.hasLegacyUnforgeableMembers = (self.concrete
                                            and any(MemberIsLegacyUnforgeable(m, self) for m in
                                                    self.interface.members))

        self.operations: dict[str, IDLMethod | None] = {
            'IndexedGetter': None,
            'IndexedSetter': None,
            'IndexedDeleter': None,
            'NamedGetter': None,
            'NamedSetter': None,
            'NamedDeleter': None,
            'Stringifier': None,
        }

        self.hasDefaultToJSON = False

        def addOperation(operation: str, m: IDLMethod) -> None:
            if not self.operations[operation]:
                self.operations[operation] = m

        # Since stringifiers go on the prototype, we only need to worry
        # about our own stringifier, not those of our ancestor interfaces.
        for m in self.interface.members:
            if m.isMethod() and m.isStringifier():
                addOperation('Stringifier', m)
            if m.isMethod() and m.isDefaultToJSON():
                self.hasDefaultToJSON = True

        if self.concrete:
            iface: IDLInterfaceOrNamespace | None = self.interface
            while iface:
                for m in iface.members:
                    if not m.isMethod():
                        continue

                    def addIndexedOrNamedOperation(operation: str, m: IDLMethod) -> None:
                        if not self.isGlobal():
                            self.proxy = True
                        if m.isIndexed():
                            operation = 'Indexed' + operation
                        else:
                            assert m.isNamed()
                            operation = 'Named' + operation
                        addOperation(operation, m)

                    if m.isGetter():
                        addIndexedOrNamedOperation('Getter', m)
                    if m.isSetter():
                        addIndexedOrNamedOperation('Setter', m)
                    if m.isDeleter():
                        addIndexedOrNamedOperation('Deleter', m)

                iface = iface.parent
                if iface:
                    iface.setUserData('hasConcreteDescendant', True)

            if self.isMaybeCrossOriginObject():
                self.proxy = True

            if self.proxy:
                iface = self.interface
                while iface.parent:
                    iface = iface.parent
                    iface.setUserData('hasProxyDescendant', True)

        self.name = interface.identifier.name

        # self.extendedAttributes is a dict of dicts, keyed on
        # all/getterOnly/setterOnly and then on member name. Values are an
        # array of extended attributes.
        self.extendedAttributes = {'all': {}, 'getterOnly': {}, 'setterOnly': {}}

        def addExtendedAttribute(attribute: dict[str, Any], config: Configuration) -> None:
            def add(key: str, members: list[str], attribute: dict[str, Any]) -> None:
                for member in members:
                    self.extendedAttributes[key].setdefault(member, []).append(attribute)

            if isinstance(config, dict):
                for key in ['all', 'getterOnly', 'setterOnly']:
                    add(key, config.get(key, []), attribute)
            elif isinstance(config, list):
                add('all', config, attribute)
            else:
                assert isinstance(config, str)
                if config == '*':
                    iface: IDLInterfaceOrNamespace | None = self.interface
                    while iface:
                        add('all', [m.name for m in iface.members], attribute)
                        iface = iface.parent
                else:
                    add('all', [config], attribute)

        self._binaryNames = desc.get('binaryNames', {})
        self._binaryNames.setdefault(('__legacycaller', False), 'LegacyCall')
        self._binaryNames.setdefault(('__stringifier', False), 'Stringifier')

        self._internalNames = desc.get('internalNames', {})

        for member in self.interface.members:
            if not member.isAttr() and not member.isMethod():
                continue
            binaryName = member.getExtendedAttribute("BinaryName")
            if binaryName:
                assert isinstance(binaryName, list)
                assert len(binaryName) == 1
                self._binaryNames.setdefault((member.identifier.name, member.isStatic()),
                                             binaryName[0])
            self._internalNames.setdefault(member.identifier.name,
                                           member.identifier.name.replace('-', '_'))

        # Build the prototype chain.
        self.prototypeChain = []
        parent: IDLInterfaceOrNamespace | None = interface
        while parent:
            self.prototypeChain.insert(0, parent.identifier.name)
            parent = parent.parent
        self.prototypeDepth = len(self.prototypeChain) - 1
        config.maxProtoChainLength = max(config.maxProtoChainLength,
                                         len(self.prototypeChain))

    def maybeGetSuperModule(self) -> str | None:
        """
        Returns name of super module if self is part of it
        """
        filename = getIdlFileName(self.interface)
        # if interface name is not same as webidl file
        # webidl is super module for interface
        if filename.lower() != self.interface.identifier.name.lower():
            return filename
        return None

    def binaryNameFor(self, name: str, isStatic: bool) -> str:
        return self._binaryNames.get((name, isStatic), name)

    def internalNameFor(self, name: str) -> str:
        return self._internalNames.get(name, name)

    def hasNamedPropertiesObject(self) -> bool:
        if self.interface.isExternal():
            return False

        return self.isGlobal() and self.supportsNamedProperties()

    def supportsNamedProperties(self) -> bool:
        return self.operations['NamedGetter'] is not None

    def getExtendedAttributes(self, member: IDLInterfaceMember, getter: bool = False, setter: bool = False) -> list[str]:
        def maybeAppendInfallibleToAttrs(attrs: list[str], throws: bool | None) -> None:
            if throws is None:
                attrs.append("infallible")
            elif throws is True:
                pass
            else:
                raise TypeError("Unknown value for 'Throws'")

        name = member.identifier.name
        if member.isMethod():
            attrs = self.extendedAttributes['all'].get(name, [])
            throws = member.getExtendedAttribute("Throws")
            maybeAppendInfallibleToAttrs(attrs, throws)
            return attrs

        assert member.isAttr()
        assert bool(getter) != bool(setter)
        key = 'getterOnly' if getter else 'setterOnly'
        attrs = self.extendedAttributes['all'].get(name, []) + self.extendedAttributes[key].get(name, [])
        throws = member.getExtendedAttribute("Throws")
        if throws is None:
            throwsAttr = "GetterThrows" if getter else "SetterThrows"
            throws = member.getExtendedAttribute(throwsAttr)
        maybeAppendInfallibleToAttrs(attrs, throws)
        return attrs

    def getParentName(self) -> str | None:
        parent = self.interface.parent
        while parent:
            if not parent.getExtendedAttribute("Inline"):
                return parent.identifier.name
            parent = parent.parent
        return None

    def supportsIndexedProperties(self) -> bool:
        return self.operations['IndexedGetter'] is not None

    def isMaybeCrossOriginObject(self) -> bool:
        # If we're isGlobal and have cross-origin members, we're a Window, and
        # that's not a cross-origin object.  The WindowProxy is.
        return self.concrete and self.interface.hasCrossOriginMembers and not self.isGlobal()

    def hasDescendants(self) -> bool:
        return (self.interface.getUserData("hasConcreteDescendant", False)
                or self.interface.getUserData("hasProxyDescendant", False) or False)

    def hasHTMLConstructor(self) -> bool:
        ctor = self.interface.ctor()
        return (ctor and ctor.isHTMLConstructor()) or False

    def shouldHaveGetConstructorObjectMethod(self) -> bool:
        assert self.interface.hasInterfaceObject()
        if self.interface.getExtendedAttribute("Inline"):
            return False
        return (self.interface.isCallback() or self.interface.isNamespace()
                or self.hasDescendants() or self.hasHTMLConstructor() or False)

    def shouldCacheConstructor(self) -> bool:
        return self.hasDescendants() or self.hasHTMLConstructor()

    def isExposedConditionally(self) -> bool:
        return self.interface.isExposedConditionally()

    def isGlobal(self) -> bool:
        """
        Returns true if this is the primary interface for a global object
        of some sort.
        """
        return bool(self.interface.getExtendedAttribute("Global")
                    or self.interface.getExtendedAttribute("PrimaryGlobal"))


# Some utility methods


def MakeNativeName(name: str) -> str:
    return name[0].upper() + name[1:]


def getIdlFileName(object: IDLObject) -> str:
    return os.path.basename(object.location.filename).split('.webidl')[0]


def getModuleFromObject(object: IDLObject) -> str:
    return ('crate::codegen::GenericBindings::' + getIdlFileName(object) + 'Binding')


def getTypesFromDescriptor(descriptor: Descriptor) -> list[IDLType]:
    """
    Get all argument and return types for all members of the descriptor
    """
    members = [m for m in descriptor.interface.members]
    if descriptor.interface.ctor():
        members.append(descriptor.interface.ctor())
    members.extend(descriptor.interface.legacyFactoryFunctions)
    signatures = [s for m in members if m.isMethod() for s in m.signatures()]
    types = []
    for s in signatures:
        assert len(s) == 2
        (returnType, arguments) = s
        types.append(returnType)
        types.extend(a.type for a in arguments)

    types.extend(a.type for a in members if a.isAttr())
    return types


def getTypesFromDictionary(dictionary: IDLWrapperType | IDLDictionary) -> list[IDLType]:
    """
    Get all member types for this dictionary
    """
    if isinstance(dictionary, IDLWrapperType):
        dictionary = dictionary.inner
    types = []
    curDict = dictionary
    while curDict:
        types.extend([getUnwrappedType(m.type) for m in curDict.members])
        curDict = curDict.parent
    return types


def getTypesFromCallback(callback: IDLCallback) -> list[IDLType]:
    """
    Get the types this callback depends on: its return type and the
    types of its arguments.
    """
    sig = callback.signatures()[0]
    types = [sig[0]]  # Return type
    types.extend(arg.type for arg in sig[1])  # Arguments
    return types


def getUnwrappedType(type: IDLType) -> IDLType:
    while isinstance(type, IDLSequenceType):
        type = type.inner
    return type


def iteratorNativeType(descriptor: Descriptor, infer: bool = False) -> str:
    assert descriptor.interface.maplikeOrSetlikeOrIterable is not None
    iterableDecl = descriptor.interface.maplikeOrSetlikeOrIterable
    assert (iterableDecl.isIterable() and iterableDecl.isPairIterator()) \
        or iterableDecl.isSetlike() or iterableDecl.isMaplike()
    res = "IterableIterator%s" % ("" if infer else '<D, D::%s>' % descriptor.interface.identifier.name)
    # todo: this hack is telling us that something is still wrong in codegen
    if iterableDecl.isSetlike() or iterableDecl.isMaplike():
        res = f"crate::iterable::{res}"
    return res
