# 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 .common.codegen import CodeGen
from .common.vulkantypes import \
        VulkanCompoundType, VulkanAPI, makeVulkanTypeSimple, vulkanTypeNeedsTransform, vulkanTypeGetNeededTransformTypes, VulkanTypeIterator, iterateVulkanType, vulkanTypeforEachSubType, TRIVIAL_TRANSFORMED_TYPES, NON_TRIVIAL_TRANSFORMED_TYPES, TRANSFORMED_TYPES

from .wrapperdefs import VulkanWrapperGenerator
from .wrapperdefs import STRUCT_EXTENSION_PARAM, STRUCT_EXTENSION_PARAM_FOR_WRITE

def deviceMemoryTransform(resourceTrackerVarName, structOrApiInfo, getExpr, getLen, cgen, variant="tohost"):
    paramIndices = \
        structOrApiInfo.deviceMemoryInfoParameterIndices

    for _, info in paramIndices.items():
        orderedKeys = [
            "handle",
            "offset",
            "size",
            "typeIndex",
            "typeBits",]
        
        casts = {
            "handle" : "VkDeviceMemory*",
            "offset" : "VkDeviceSize*",
            "size" : "VkDeviceSize*",
            "typeIndex" : "uint32_t*",
            "typeBits" : "uint32_t*",
        }

        accesses = {
            "handle" : "nullptr",
            "offset" : "nullptr",
            "size" : "nullptr",
            "typeIndex" : "nullptr",
            "typeBits" : "nullptr",
        }

        lenAccesses = {
            "handle" : "0",
            "offset" : "0",
            "size" : "0",
            "typeIndex" : "0",
            "typeBits" : "0",
        }

        def doParam(i, vulkanType):
            access = getExpr(vulkanType)
            lenAccess = getLen(vulkanType)

            for k in orderedKeys:
                if i == info.__dict__[k]:
                    accesses[k] = access
                    if lenAccess is not None:
                        lenAccesses[k] = lenAccess
                    else:
                        lenAccesses[k] = "1"

        vulkanTypeforEachSubType(structOrApiInfo, doParam)

        callParams = ", ".join( \
            ["(%s)%s, %s" % (casts[k], accesses[k], lenAccesses[k]) \
                for k in orderedKeys])

        if variant == "tohost":
            cgen.stmt("%s->deviceMemoryTransform_tohost(%s)" % \
                (resourceTrackerVarName, callParams))
        else:
            cgen.stmt("%s->deviceMemoryTransform_fromhost(%s)" % \
                (resourceTrackerVarName, callParams))

def directTransform(resourceTrackerVarName, vulkanType, getExpr, getLen, cgen, variant="tohost"):
    access = getExpr(vulkanType)
    lenAccess = getLen(vulkanType)

    if lenAccess:
        finalLenAccess = lenAccess
    else:
        finalLenAccess = "1"

    cgen.stmt("%s->transformImpl_%s_%s(%s, %s)" % (resourceTrackerVarName,
                                                   vulkanType.typeName, variant, access, finalLenAccess))

def genTransformsForVulkanType(resourceTrackerVarName, structOrApiInfo, getExpr, getLen, cgen, variant="tohost"):
    for transform in vulkanTypeGetNeededTransformTypes(structOrApiInfo):
        if transform == "devicememory":
            deviceMemoryTransform( \
                resourceTrackerVarName,
                structOrApiInfo,
                getExpr, getLen, cgen, variant=variant)

class TransformCodegen(VulkanTypeIterator):
    def __init__(self, cgen, inputVar, resourceTrackerVarName, prefix, variant):
        self.cgen = cgen
        self.inputVar = inputVar
        self.prefix = prefix
        self.resourceTrackerVarName = resourceTrackerVarName

        def makeAccess(varName, asPtr = True):
            return lambda t: self.cgen.generalAccess(t, parentVarName = varName, asPtr = asPtr)

        def makeLengthAccess(varName):
            return lambda t: self.cgen.generalLengthAccess(t, parentVarName = varName)

        def makeLengthAccessGuard(varName):
            return lambda t: self.cgen.generalLengthAccessGuard(t, parentVarName=varName)

        self.exprAccessor = makeAccess(self.inputVar)
        self.exprAccessorValue = makeAccess(self.inputVar, asPtr = False)
        self.lenAccessor = makeLengthAccess(self.inputVar)
        self.lenAccessorGuard = makeLengthAccessGuard(self.inputVar)

        self.checked = False

        self.variant = variant

    def makeCastExpr(self, vulkanType):
        return "(%s)" % (
            self.cgen.makeCTypeDecl(vulkanType, useParamName=False))

    def asNonConstCast(self, access, vulkanType):
        if vulkanType.staticArrExpr:
            casted = "%s(%s)" % (self.makeCastExpr(vulkanType.getForAddressAccess().getForNonConstAccess()), access)
        elif vulkanType.accessibleAsPointer():
            casted = "%s(%s)" % (self.makeCastExpr(vulkanType.getForNonConstAccess()), access)
        else:
            casted = "%s(%s)" % (self.makeCastExpr(vulkanType.getForAddressAccess().getForNonConstAccess()), access)
        return casted

    def onCheck(self, vulkanType):
        pass

    def endCheck(self, vulkanType):
        pass

    def onCompoundType(self, vulkanType):

        access = self.exprAccessor(vulkanType)
        lenAccess = self.lenAccessor(vulkanType)
        lenAccessGuard = self.lenAccessorGuard(vulkanType)

        isPtr = vulkanType.pointerIndirectionLevels > 0

        if lenAccessGuard is not None:
            self.cgen.beginIf(lenAccessGuard)

        if isPtr:
            self.cgen.beginIf(access)

        if lenAccess is not None:

            loopVar = "i"
            access = "%s + %s" % (access, loopVar)
            forInit = "uint32_t %s = 0" % loopVar
            forCond = "%s < (uint32_t)%s" % (loopVar, lenAccess)
            forIncr = "++%s" % loopVar

            self.cgen.beginFor(forInit, forCond, forIncr)

        accessCasted = self.asNonConstCast(access, vulkanType)

        if vulkanType.isTransformed:
            directTransform(self.resourceTrackerVarName, vulkanType, self.exprAccessor, self.lenAccessor, self.cgen, variant=self.variant)

        self.cgen.funcCall(None, self.prefix + vulkanType.typeName,
                           [self.resourceTrackerVarName, accessCasted])

        if lenAccess is not None:
            self.cgen.endFor()

        if isPtr:
            self.cgen.endIf()

        if lenAccessGuard is not None:
            self.cgen.endIf()

    def onString(self, vulkanType):
        pass

    def onStringArray(self, vulkanType):
        pass

    def onStaticArr(self, vulkanType):
        pass

    def onStructExtension(self, vulkanType):
        access = self.exprAccessor(vulkanType)

        castedAccessExpr = "(%s)(%s)" % ("void*", access)
        self.cgen.beginIf(access)
        self.cgen.funcCall(None, self.prefix + "extension_struct",
                           [self.resourceTrackerVarName, castedAccessExpr])
        self.cgen.endIf()

    def onPointer(self, vulkanType):
        pass

    def onValue(self, vulkanType):
        pass


class VulkanTransform(VulkanWrapperGenerator):
    def __init__(self, module, typeInfo, resourceTrackerTypeName="ResourceTracker", resourceTrackerVarName="resourceTracker"):
        VulkanWrapperGenerator.__init__(self, module, typeInfo)

        self.codegen = CodeGen()

        self.transformPrefix = "transform_"

        self.tohostpart = "tohost"
        self.fromhostpart = "fromhost"
        self.variants = [self.tohostpart, self.fromhostpart]

        self.toTransformVar = "toTransform"
        self.resourceTrackerTypeName = resourceTrackerTypeName
        self.resourceTrackerVarName = resourceTrackerVarName
        self.transformParam = \
            makeVulkanTypeSimple(False, self.resourceTrackerTypeName, 1,
                                 self.resourceTrackerVarName)
        self.voidType = makeVulkanTypeSimple(False, "void", 0)

        self.extensionTransformPrototypes = []

        for variant in self.variants:
            self.extensionTransformPrototypes.append( \
                VulkanAPI(self.transformPrefix + variant + "_extension_struct",
                          self.voidType,
                          [self.transformParam, STRUCT_EXTENSION_PARAM_FOR_WRITE]))

        self.knownStructs = {}
        self.needsTransform = set([])

    def onBegin(self,):
        VulkanWrapperGenerator.onBegin(self)
        # Set up a convenience macro fro the transformed structs
        # and forward-declare the resource tracker class
        self.codegen.stmt("class %s" % self.resourceTrackerTypeName)
        self.codegen.line("#define LIST_TRIVIAL_TRANSFORMED_TYPES(f) \\")
        for name in TRIVIAL_TRANSFORMED_TYPES:
            self.codegen.line("f(%s) \\" % name)
        self.codegen.line("")

        self.codegen.line("#define LIST_NON_TRIVIAL_TRANSFORMED_TYPES(f) \\")
        for name in NON_TRIVIAL_TRANSFORMED_TYPES:
            self.codegen.line("f(%s) \\" % name)
        self.codegen.line("")

        self.codegen.line("#define LIST_TRANSFORMED_TYPES(f) \\")
        self.codegen.line("LIST_TRIVIAL_TRANSFORMED_TYPES(f) \\")
        self.codegen.line("LIST_NON_TRIVIAL_TRANSFORMED_TYPES(f) \\")
        self.codegen.line("")

        self.module.appendHeader(self.codegen.swapCode())

        for prototype in self.extensionTransformPrototypes:
            self.module.appendImpl(self.codegen.makeFuncDecl(
                prototype))

    def onGenType(self, typeXml, name, alias):
        VulkanWrapperGenerator.onGenType(self, typeXml, name, alias)

        if name in self.knownStructs:
            return

        category = self.typeInfo.categoryOf(name)

        if category in ["struct", "union"] and alias:
            for variant in self.variants:
                self.module.appendHeader(
                    self.codegen.makeFuncAlias(self.transformPrefix + variant + "_" + name,
                                               self.transformPrefix + variant + "_" + alias))

        if category in ["struct", "union"] and not alias:
            structInfo = self.typeInfo.structs[name]
            self.knownStructs[name] = structInfo

            for variant in self.variants:
                api = VulkanAPI( \
                    self.transformPrefix + variant + "_" + name,
                    self.voidType,
                    [self.transformParam] + \
                    [makeVulkanTypeSimple( \
                        False, name, 1, self.toTransformVar)])

                transformer = TransformCodegen(
                    None,
                    self.toTransformVar,
                    self.resourceTrackerVarName,
                    self.transformPrefix + variant + "_",
                    variant)

                def funcDefGenerator(cgen):
                    transformer.cgen = cgen
                    for p in api.parameters:
                        cgen.stmt("(void)%s" % p.paramName)

                    genTransformsForVulkanType(
                        self.resourceTrackerVarName,
                        structInfo,
                        transformer.exprAccessor,
                        transformer.lenAccessor,
                        cgen,
                        variant=variant)

                    for member in structInfo.members:
                        iterateVulkanType(
                            self.typeInfo, member,
                            transformer)

                self.module.appendHeader(
                    self.codegen.makeFuncDecl(api))
                self.module.appendImpl(
                    self.codegen.makeFuncImpl(api, funcDefGenerator))


    def onGenCmd(self, cmdinfo, name, alias):
        VulkanWrapperGenerator.onGenCmd(self, cmdinfo, name, alias)

    def onEnd(self,):
        VulkanWrapperGenerator.onEnd(self)

        for (variant, prototype) in zip(self.variants, self.extensionTransformPrototypes):
            def forEachExtensionTransform(ext, castedAccess, cgen):
                if ext.isTransformed:
                    directTransform(self.resourceTrackerVarName, ext, lambda _ : castedAccess, lambda _ : "1", cgen, variant);
                cgen.funcCall(None, self.transformPrefix + variant + "_" + ext.name,
                              [self.resourceTrackerVarName, castedAccess])

            self.module.appendImpl(
                self.codegen.makeFuncImpl(
                    prototype,
                    lambda cgen: self.emitForEachStructExtension(
                        cgen,
                        self.voidType,
                        STRUCT_EXTENSION_PARAM_FOR_WRITE,
                        forEachExtensionTransform)))
