# Copyright (c) 2018 The Android Open Source Project
# Copyright (c) 2018 Google Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from generator import noneStr

from copy import copy

# Holds information about core Vulkan objects
# and the API calls that are used to create/destroy each one.
class HandleInfo(object):
    def __init__(self, name, createApis, destroyApis):
        self.name = name
        self.createApis = createApis
        self.destroyApis = destroyApis

    def isCreateApi(self, apiName):
        return apiName == self.createApis or (apiName in self.createApis)

    def isDestroyApi(self, apiName):
        if self.destroyApis is None:
            return False
        return apiName == self.destroyApis or (apiName in self.destroyApis)

DISPATCHABLE_HANDLE_TYPES = [
    "VkInstance",
    "VkPhysicalDevice",
    "VkDevice",
    "VkQueue",
    "VkCommandBuffer",
]

NON_DISPATCHABLE_HANDLE_TYPES = [
    "VkDeviceMemory",
    "VkBuffer",
    "VkBufferView",
    "VkImage",
    "VkImageView",
    "VkShaderModule",
    "VkDescriptorPool",
    "VkDescriptorSetLayout",
    "VkDescriptorSet",
    "VkSampler",
    "VkPipeline",
    "VkPipelineLayout",
    "VkRenderPass",
    "VkFramebuffer",
    "VkPipelineCache",
    "VkCommandPool",
    "VkFence",
    "VkSemaphore",
    "VkEvent",
    "VkQueryPool",
    "VkSamplerYcbcrConversion",
    "VkSamplerYcbcrConversionKHR",
    "VkDescriptorUpdateTemplate",
    "VkSurfaceKHR",
    "VkSwapchainKHR",
    "VkDisplayKHR",
    "VkDisplayModeKHR",
    "VkObjectTableNVX",
    "VkIndirectCommandsLayoutNVX",
    "VkValidationCacheEXT",
    "VkDebugReportCallbackEXT",
    "VkDebugUtilsMessengerEXT",
]

CUSTOM_HANDLE_CREATE_TYPES = [
    "VkPhysicalDevice",
    "VkQueue",
    "VkPipeline",
    "VkDeviceMemory",
    "VkDescriptorSet",
    "VkCommandBuffer",
]

HANDLE_TYPES = list(sorted(list(set(DISPATCHABLE_HANDLE_TYPES +
                                    NON_DISPATCHABLE_HANDLE_TYPES + CUSTOM_HANDLE_CREATE_TYPES))))

HANDLE_INFO = {}

for h in HANDLE_TYPES:
    if h in CUSTOM_HANDLE_CREATE_TYPES:
        if h == "VkPhysicalDevice":
            HANDLE_INFO[h] = \
                HandleInfo(
                    "VkPhysicalDevice",
                    "vkEnumeratePhysicalDevices", None)
        if h == "VkQueue":
            HANDLE_INFO[h] = \
                HandleInfo(
                    "VkQueue",
                    "vkGetDeviceQueue", None)
        if h == "VkPipeline":
            HANDLE_INFO[h] = \
                HandleInfo(
                    "VkPipeline",
                    ["vkCreateGraphicsPipelines", "vkCreateComputePipelines"],
                    "vkDestroyPipeline")
        if h == "VkDeviceMemory":
            HANDLE_INFO[h] = \
                HandleInfo("VkDeviceMemory",
                           "vkAllocateMemory", "vkFreeMemory")
        if h == "VkDescriptorSet":
            HANDLE_INFO[h] = \
                HandleInfo("VkDescriptorSet", "vkAllocateDescriptorSets",
                           "vkFreeDescriptorSets")
        if h == "VkCommandBuffer":
            HANDLE_INFO[h] = \
                HandleInfo("VkCommandBuffer", "vkAllocateCommandBuffers",
                           "vkFreeCommandBuffers")
    else:
        HANDLE_INFO[h] = \
            HandleInfo(h, "vkCreate" + h[2:], "vkDestroy" + h[2:])

EXCLUDED_APIS = [
    "vkEnumeratePhysicalDeviceGroups",
]

EXPLICITLY_ABI_PORTABLE_TYPES = [
    "VkResult",
    "VkBool32",
    "VkSampleMask",
    "VkFlags",
    "VkDeviceSize",
]

EXPLICITLY_ABI_NON_PORTABLE_TYPES = [
    "size_t"
]

NON_ABI_PORTABLE_TYPE_CATEGORIES = [
    "handle",
    "funcpointer",
]

DEVICE_MEMORY_INFO_KEYS = [
    "devicememoryhandle",
    "devicememoryoffset",
    "devicememorysize",
    "devicememorytypeindex",
    "devicememorytypebits",
]

TRANSFORMED_TYPES = [
    "VkExternalMemoryProperties",
    "VkPhysicalDeviceExternalImageFormatInfo",
    "VkPhysicalDeviceExternalBufferInfo",
    "VkExternalMemoryImageCreateInfo",
    "VkExternalMemoryBufferCreateInfo",
    "VkExportMemoryAllocateInfo",
    "VkExternalImageFormatProperties",
    "VkExternalBufferProperties",
]

# Holds information about a Vulkan type instance (i.e., not a type definition).
# Type instances are used as struct field definitions or function parameters,
# to be later fed to code generation.
# VulkanType instances can be constructed in two ways:
# 1. From an XML tag with <type> / <param> tags in vk.xml,
#    using makeVulkanTypeFromXMLTag
# 2. User-defined instances with makeVulkanTypeSimple.
class VulkanType(object):

    def __init__(self):
        self.parent = None
        self.typeName = ""

        self.isTransformed = False

        self.paramName = None

        self.lenExpr = None
        self.isOptional = False

        self.isConst = False

        self.staticArrExpr = ""  # "" means not static array
        # 0 means the array size is not a numeric literal
        self.staticArrCount = 0
        self.pointerIndirectionLevels = 0  # 0 means not pointer
        self.isPointerToConstPointer = False

        self.primitiveEncodingSize = None

        # self.deviceMemoryAttrib/Val stores
        # device memory info attributes from the XML.
        # devicememoryhandle
        # devicememoryoffset
        # devicememorysize
        # devicememorytypeindex
        # devicememorytypebits
        self.deviceMemoryAttrib = None
        self.deviceMemoryVal = None

    def __str__(self,):
        return ("(vulkantype %s %s paramName %s len %s optional? %s "
                "staticArrExpr %s %s)") % (
            self.typeName + ("*" * self.pointerIndirectionLevels) +
            ("ptr2constptr" if self.isPointerToConstPointer else ""), "const"
            if self.isConst else "nonconst", self.paramName, self.lenExpr,
            self.isOptional, self.staticArrExpr, self.staticArrCount)

    def isString(self,):
        return self.pointerIndirectionLevels == 1 and (self.typeName == "char")

    def isArrayOfStrings(self,):
        return self.isPointerToConstPointer and (self.typeName == "char")

    def primEncodingSize(self,):
        return self.primitiveEncodingSize

    # Utility functions to make codegen life easier.
    # This method derives the correct "count" expression if possible.
    # Otherwise, returns None or "null-terminated" if a string.
    def getLengthExpression(self,):
        if self.staticArrExpr != "":
            return self.staticArrExpr
        if self.lenExpr:
            return self.lenExpr
        return None

    # Can we just pass this to functions expecting T*
    def accessibleAsPointer(self,):
        if self.staticArrExpr != "":
            return True
        if self.pointerIndirectionLevels > 0:
            return True
        return False

    # Rough attempt to infer where a type could be an output.
    # Good for inferring which things need to be marshaled in
    # versus marshaled out for Vulkan API calls
    def possiblyOutput(self,):
        return self.pointerIndirectionLevels > 0 and (not self.isConst)

    def isVoidWithNoSize(self,):
        return self.typeName == "void" and self.pointerIndirectionLevels == 0

    def getCopy(self,):
        return copy(self)

    def getTransformed(self, isConstChoice=None, ptrIndirectionChoice=None):
        res = self.getCopy()

        if isConstChoice is not None:
            res.isConst = isConstChoice
        if ptrIndirectionChoice is not None:
            res.pointerIndirectionLevels = ptrIndirectionChoice

        return res

    def getWithCustomName(self):
        return self.getTransformed(
            ptrIndirectionChoice=self.pointerIndirectionLevels + 1)

    def getForAddressAccess(self):
        return self.getTransformed(
            ptrIndirectionChoice=self.pointerIndirectionLevels + 1)

    def getForValueAccess(self):
        if self.typeName == "void" and self.pointerIndirectionLevels == 1:
            asUint8Type = self.getCopy()
            asUint8Type.typeName = "uint8_t"
            return asUint8Type.getForValueAccess()
        return self.getTransformed(
            ptrIndirectionChoice=self.pointerIndirectionLevels - 1)

    def getForNonConstAccess(self):
        return self.getTransformed(isConstChoice=False)

    def withModifiedName(self, newName):
        res = self.getCopy()
        res.paramName = newName
        return res

    def isNextPointer(self):
        if self.paramName == "pNext":
            return True
        return False

    # Only deals with 'core' handle types here.
    def isDispatchableHandleType(self):
        return self.typeName in DISPATCHABLE_HANDLE_TYPES

    def isNonDispatchableHandleType(self):
        return self.typeName in NON_DISPATCHABLE_HANDLE_TYPES

    def isHandleType(self):
        return self.isDispatchableHandleType() or \
               self.isNonDispatchableHandleType()

    def isCreatedBy(self, api):
        if self.typeName in HANDLE_INFO.keys():
            nonKhrRes = HANDLE_INFO[self.typeName].isCreateApi(api.name)
            if nonKhrRes:
                return True
            if len(api.name) > 3 and "KHR" == api.name[-3:]:
                return HANDLE_INFO[self.typeName].isCreateApi(api.name[:-3])

        return False

    def isDestroyedBy(self, api):
        if self.typeName in HANDLE_INFO.keys():
            nonKhrRes = HANDLE_INFO[self.typeName].isDestroyApi(api.name)
            if nonKhrRes:
                return True
            if len(api.name) > 3 and "KHR" == api.name[-3:]:
                return HANDLE_INFO[self.typeName].isDestroyApi(api.name[:-3])
            
        return False

    def isSimpleValueType(self, typeInfo):
        if typeInfo.isCompoundType(self.typeName):
            return False
        if self.isString() or self.isArrayOfStrings():
            return False
        if self.staticArrExpr or self.pointerIndirectionLevels > 0:
            return False
        return True

    def getStructEnumExpr(self,):
        return None

def makeVulkanTypeFromXMLTag(typeInfo, tag):
    res = VulkanType()

    # Process the length expression

    if tag.attrib.get("len") is not None:
        lengths = tag.attrib.get("len").split(",")
        res.lenExpr = lengths[0]

    # Calculate static array expression

    nametag = tag.find("name")
    enumtag = tag.find("enum")

    if enumtag is not None:
        res.staticArrExpr = enumtag.text
    elif nametag is not None:
        res.staticArrExpr = noneStr(nametag.tail)[1:-1]
        if res.staticArrExpr != "":
            res.staticArrCount = int(res.staticArrExpr)

    # Determine const

    beforeTypePart = noneStr(tag.text)

    if "const" in beforeTypePart:
        res.isConst = True

    # Calculate type and pointer info

    for elem in tag:
        if elem.tag == "name":
            res.paramName = elem.text
        if elem.tag == "type":
            duringTypePart = noneStr(elem.text)
            afterTypePart = noneStr(elem.tail)
            # Now we know enough to fill some stuff in
            res.typeName = duringTypePart

            if res.typeName in TRANSFORMED_TYPES:
                res.isTransformed = True

            # This only handles pointerIndirectionLevels == 2
            # along with optional constant pointer for the inner part.
            for c in afterTypePart:
                if c == "*":
                    res.pointerIndirectionLevels += 1
            if "const" in afterTypePart and res.pointerIndirectionLevels == 2:
                res.isPointerToConstPointer = True

            # If void*, treat like it's not a pointer
            # if duringTypePart == "void":
            # res.pointerIndirectionLevels -= 1

    # Calculate optionality (based on validitygenerator.py)
    if tag.attrib.get("optional") is not None:
        res.isOptional = True

    # If no validity is being generated, it usually means that
    # validity is complex and not absolute, so let's say yes.
    if tag.attrib.get("noautovalidity") is not None:
        res.isOptional = True

    # If this is a structure extension, it is optional.
    if tag.attrib.get("structextends") is not None:
        res.isOptional = True

    # If this is a pNext pointer, it is optional.
    if res.paramName == "pNext":
        res.isOptional = True

    res.primitiveEncodingSize = \
        typeInfo.getPrimitiveEncodingSize(res.typeName)

    # it is assumed only one such key
    # applies to any field.
    for k in DEVICE_MEMORY_INFO_KEYS:
        if tag.attrib.get(k) is not None:
            res.deviceMemoryAttrib = k
            res.deviceMemoryVal = \
                tag.attrib.get(k)
            break;

    return res


def makeVulkanTypeSimple(isConst,
                         typeName,
                         ptrIndirectionLevels,
                         paramName=None):
    res = VulkanType()

    res.typeName = typeName
    res.isConst = isConst
    res.pointerIndirectionLevels = ptrIndirectionLevels
    res.isPointerToConstPointer = False
    res.paramName = paramName
    res.primitiveEncodingSize = None

    return res

# A class for holding the parameter indices corresponding to various
# attributes about a VkDeviceMemory, such as the handle, size, offset, etc.
class DeviceMemoryInfoParameterIndices(object):
    def __init__(self, handle, offset, size, typeIndex, typeBits):
        self.handle = handle
        self.offset = offset
        self.size = size
        self.typeIndex = typeIndex
        self.typeBits = typeBits

# initializes DeviceMemoryInfoParameterIndices for each
# abstract VkDeviceMemory encountered over |parameters|
def initDeviceMemoryInfoParameterIndices(parameters):

    use = False
    deviceMemoryInfoById = {}

    for (i, p) in enumerate(parameters):
        a = p.deviceMemoryAttrib
        if not a:
            continue

        if a in DEVICE_MEMORY_INFO_KEYS:
            use = True
            deviceMemoryInfoById[
                p.deviceMemoryVal] = \
                    DeviceMemoryInfoParameterIndices(
                        None, None, None, None, None)

    for (i, p) in enumerate(parameters):
        a = p.deviceMemoryAttrib
        if not a:
            continue

        info = \
            deviceMemoryInfoById[p.deviceMemoryVal]

        if a == "devicememoryhandle":
            info.handle = i
        if a == "devicememoryoffset":
            info.offset = i
        if a == "devicememorysize":
            info.size = i
        if a == "devicememorytypeindex":
            info.typeIndex = i
        if a == "devicememorytypebits":
            info.typeBits = i

    if not use:
        return None

    return deviceMemoryInfoById

# Classes for describing aggregate types (unions, structs) and API calls.
class VulkanCompoundType(object):

    def __init__(self, name, members, isUnion=False, structEnumExpr=None, structExtendsExpr=None, feature=None):
        self.name = name
        self.typeName = name
        self.members = members

        self.isUnion = isUnion
        self.structEnumExpr = structEnumExpr
        self.structExtendsExpr = structExtendsExpr
        self.feature = feature

        self.deviceMemoryInfoParameterIndices = \
            initDeviceMemoryInfoParameterIndices(self.members)

        self.isTransformed = name in TRANSFORMED_TYPES

        self.copy = None

    def initCopies(self):
        self.copy = self

        for m in self.members:
            m.parent = self.copy

    def getMember(self, memberName):
        for m in self.members:
            if m.paramName == memberName:
                return m
        return None

    def getStructEnumExpr(self,):
        return self.structEnumExpr

class VulkanAPI(object):

    def __init__(self, name, retType, parameters, origName=None):
        self.name = name
        self.origName = name
        self.retType = retType
        self.parameters = parameters

        self.deviceMemoryInfoParameterIndices = \
            initDeviceMemoryInfoParameterIndices(self.parameters)

        self.copy = None

        self.isTransformed = name in TRANSFORMED_TYPES

        if origName:
            self.origName = origName

    def initCopies(self):
        self.copy = self

        for m in self.parameters:
            m.parent = self.copy

    def getCopy(self,):
        return copy(self)

    def getParameter(self, parameterName):
        for p in self.parameters:
            if p.paramName == parameterName:
                return p
        return None

    def withModifiedName(self, newName):
        res = VulkanAPI(newName, self.retType, self.parameters)
        return res

    def getRetVarExpr(self):
        if self.retType.typeName == "void":
            return None
        return "%s_%s_return" % (self.name, self.retType.typeName)

    def getRetTypeExpr(self):
        return self.retType.typeName

    def withCustomParameters(self, customParams):
        res = self.getCopy()
        res.parameters = customParams
        return res

# Whether or not special handling of virtual elements
# such as VkDeviceMemory is needed.
def vulkanTypeNeedsTransform(structOrApi):
    return structOrApi.deviceMemoryInfoParameterIndices != None

def vulkanTypeGetNeededTransformTypes(structOrApi):
    res = []
    if structOrApi.deviceMemoryInfoParameterIndices != None:
        res.append("devicememory")
    return res

def vulkanTypeforEachSubType(structOrApi, f):
    toLoop = None
    if type(structOrApi) == VulkanCompoundType:
        toLoop = structOrApi.members
    if type(structOrApi) == VulkanAPI:
        toLoop = structOrApi.parameters

    for (i, x) in enumerate(toLoop):
        f(i, x)

# Parses everything about Vulkan types into a Python readable format.
class VulkanTypeInfo(object):

    def __init__(self,):
        self.categories = set([])

        # Tracks what Vulkan type is part of what category.
        self.typeCategories = {}

        # Tracks the primitve encoding size for each type,
        # if applicable.
        self.encodingSizes = {}

        self.structs = {}
        self.apis = {}

        self.feature = None

    def initType(self, name, category):
        self.categories.add(category)
        self.typeCategories[name] = category
        self.encodingSizes[name] = self.setPrimitiveEncodingSize(name)

    def categoryOf(self, name):
        return self.typeCategories[name]

    def getPrimitiveEncodingSize(self, name):
        return self.encodingSizes[name]

    # Queries relating to categories of Vulkan types.
    def isHandleType(self, name):
        if name in self.typeCategories:
            return self.typeCategories[name] == "handle"
        return False

    def isCompoundType(self, name):
        if name in self.typeCategories:
            return self.typeCategories[name] in ["struct", "union"]
        else:
            return False

    # Gets the best size in bytes
    # for encoding/decoding a particular Vulkan type.
    # If not applicable, returns None.
    def setPrimitiveEncodingSize(self, name):
        baseEncodingSizes = {
            "void" : 8,
            "char" : 1,
            "float" : 4,
            "uint8_t" : 1,
            "uint16_t" : 2,
            "uint32_t" : 4,
            "uint64_t" : 8,
            "size_t" : 8,
            "ssize_t" : 8,
        }

        if name in baseEncodingSizes:
            return baseEncodingSizes[name]

        category = self.typeCategories[name]

        if category in [None, "api", "bitmask", "include", "define", "struct", "union"]:
            return None

        # Must be 8---handles are pointers and basetype includes VkDeviceSize
        # which is 8 bytes
        if category in ["handle", "basetype", "funcpointer"]:
            return 8

        # Most of the time, enums are only 4 bytes, but this is
        # vague enough to be the source of a future headache, and
        # it's easy to just stream 8 bytes there anyway.
        if category in ["enum"]:
            return 8

    def isNonAbiPortableType(self, typeName):
        if typeName in EXPLICITLY_ABI_PORTABLE_TYPES:
            return False

        if typeName in EXPLICITLY_ABI_NON_PORTABLE_TYPES:
            return True

        category = self.typeCategories[typeName]
        return category in NON_ABI_PORTABLE_TYPE_CATEGORIES

    def onBeginFeature(self, featureName):
        self.feature = featureName

    def onEndFeature(self):
        self.feature = None

    def onGenType(self, typeinfo, name, alias):
        category = typeinfo.elem.get("category")
        self.initType(name, category)

        if category in ["struct", "union"]:
            self.onGenStruct(typeinfo, name, alias)

    def onGenStruct(self, typeinfo, typeName, alias):
        if not alias:
            members = []

            structExtendsExpr = typeinfo.elem.get("structextends")

            structEnumExpr = None

            for member in typeinfo.elem.findall(".//member"):
                vulkanType = makeVulkanTypeFromXMLTag(self, member)
                members.append(vulkanType)
                if vulkanType.typeName == "VkStructureType" and \
                   member.get("values"):
                   structEnumExpr = member.get("values")

            self.structs[typeName] = \
                VulkanCompoundType( \
                    typeName,
                    members,
                    isUnion = self.categoryOf(typeName) == "union",
                    structEnumExpr = structEnumExpr,
                    structExtendsExpr = structExtendsExpr,
                    feature = self.feature)
            self.structs[typeName].initCopies()

    def onGenGroup(self, _groupinfo, groupName, _alias=None):
        self.initType(groupName, "enum")

    def onGenEnum(self, _enuminfo, name, _alias):
        self.initType(name, "enum")

    def onGenCmd(self, cmdinfo, name, _alias):
        self.initType(name, "api")

        proto = cmdinfo.elem.find("proto")
        params = cmdinfo.elem.findall("param")

        self.apis[name] = \
            VulkanAPI(
                name,
                makeVulkanTypeFromXMLTag(self, proto),
                list(map(lambda p: makeVulkanTypeFromXMLTag(self, p),
                         params)))
        self.apis[name].initCopies()

    def onEnd(self,):
        pass

# General function to iterate over a vulkan type and call code that processes
# each of its sub-components, if any.
def iterateVulkanType(typeInfo, vulkanType, forEachType):
    if not vulkanType.isArrayOfStrings():
        if vulkanType.isPointerToConstPointer:
            return False

    forEachType.registerTypeInfo(typeInfo)

    needCheck = \
        vulkanType.isOptional and \
        vulkanType.pointerIndirectionLevels > 0 and \
        (not vulkanType.isNextPointer())

    if typeInfo.isCompoundType(vulkanType.typeName) and not vulkanType.isNextPointer():

        if needCheck:
            forEachType.onCheck(vulkanType)

        forEachType.onCompoundType(vulkanType)

        if needCheck:
            forEachType.endCheck(vulkanType)

    else:

        if vulkanType.isString():

            forEachType.onString(vulkanType)

        elif vulkanType.isArrayOfStrings():

            forEachType.onStringArray(vulkanType)

        elif vulkanType.staticArrExpr:

            forEachType.onStaticArr(vulkanType)

        elif vulkanType.isNextPointer():

            if needCheck:
                forEachType.onCheck(vulkanType)
            forEachType.onStructExtension(vulkanType)
            if needCheck:
                forEachType.endCheck(vulkanType)

        elif vulkanType.pointerIndirectionLevels > 0:
            if needCheck:
                forEachType.onCheck(vulkanType)
            forEachType.onPointer(vulkanType)
            if needCheck:
                forEachType.endCheck(vulkanType)
        else:

            forEachType.onValue(vulkanType)

    return True

class VulkanTypeIterator(object):
    def __init__(self,):
        self.typeInfo = None

    def registerTypeInfo(self, typeInfo):
        self.typeInfo = typeInfo
