# 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 \
        VulkanAPI, makeVulkanTypeSimple, iterateVulkanType, VulkanTypeIterator

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

class DeepcopyCodegen(VulkanTypeIterator):
    def __init__(self, cgen, inputVars, poolVarName, rootVarName, prefix, skipValues=False):
        self.cgen = cgen
        self.inputVars = inputVars
        self.prefix = prefix
        self.poolVarName = poolVarName
        self.rootVarName = rootVarName
        self.skipValues = skipValues

        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.exprAccessorLhs = makeAccess(self.inputVars[0])
        self.exprAccessorRhs = makeAccess(self.inputVars[1])

        self.exprAccessorValueLhs = makeAccess(self.inputVars[0], asPtr = False)
        self.exprAccessorValueRhs = makeAccess(self.inputVars[1], asPtr = False)

        self.lenAccessorLhs = makeLengthAccess(self.inputVars[0])
        self.lenAccessorRhs = makeLengthAccess(self.inputVars[1])

        self.lenAccessorGuardLhs = makeLengthAccessGuard(self.inputVars[0])
        self.lenAccessorGuardRhs = makeLengthAccessGuard(self.inputVars[1])

        self.checked = False

    def needSkip(self, vulkanType):
        return False

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

    def makeNonConstCastForCopy(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 makeAllocBytesExpr(self, lenAccess, vulkanType):
        sizeof = self.cgen.sizeofExpr( \
                     vulkanType.getForValueAccess())
        if lenAccess:
            bytesExpr = "%s * %s" % (lenAccess, sizeof)
        else:
            bytesExpr = sizeof

        return bytesExpr

    def onCheck(self, vulkanType):
        pass

    def endCheck(self, vulkanType):
        pass

    def onCompoundType(self, vulkanType):

        if self.needSkip(vulkanType):
            self.cgen.line("// TODO: Unsupported : %s" %
                           self.cgen.makeCTypeDecl(vulkanType))
            return

        accessLhs = self.exprAccessorLhs(vulkanType)
        accessRhs = self.exprAccessorRhs(vulkanType)

        lenAccessLhs = self.lenAccessorLhs(vulkanType)
        lenAccessRhs = self.lenAccessorRhs(vulkanType)

        lenAccessorGuardLhs = self.lenAccessorGuardLhs(vulkanType)
        lenAccessorGuardRhs = self.lenAccessorGuardRhs(vulkanType)

        isPtr = vulkanType.pointerIndirectionLevels > 0

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

        if isPtr:
            self.cgen.stmt("%s = nullptr" % accessRhs)
            self.cgen.beginIf(accessLhs)

            self.cgen.stmt( \
                "%s = %s%s->alloc(%s)" % \
                (accessRhs, self.makeCastExpr(vulkanType.getForNonConstAccess()),
                 self.poolVarName, self.makeAllocBytesExpr(lenAccessLhs, vulkanType)))

        if lenAccessLhs is not None:

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

            if isPtr:
                # Avoid generating a self-assign.
                if lenAccessRhs != lenAccessLhs:
                    self.cgen.stmt("%s = %s" % (lenAccessRhs, lenAccessLhs))

            accessRhs = "%s + %s" % (accessRhs, loopVar)
            self.cgen.beginFor(forInit, forCond, forIncr)


        accessRhsCasted = self.makeNonConstCastForCopy(accessRhs, vulkanType)

        self.cgen.funcCall(None, self.prefix + vulkanType.typeName,
                           [self.poolVarName, self.rootVarName, accessLhs, accessRhsCasted])

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

        if isPtr:
            self.cgen.endIf()

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

    def onString(self, vulkanType):
        accessLhs = self.exprAccessorLhs(vulkanType)
        accessRhs = self.exprAccessorRhs(vulkanType)

        self.cgen.stmt("%s = nullptr" % accessRhs)
        self.cgen.beginIf(accessLhs)

        self.cgen.stmt( \
            "%s = %s->strDup(%s)" % \
            (accessRhs,
             self.poolVarName,
             accessLhs))

        self.cgen.endIf()

    def onStringArray(self, vulkanType):
        accessLhs = self.exprAccessorLhs(vulkanType)
        accessRhs = self.exprAccessorRhs(vulkanType)

        lenAccessLhs = self.lenAccessorLhs(vulkanType)

        self.cgen.stmt("%s = nullptr" % accessRhs)
        self.cgen.beginIf("%s && %s" % (accessLhs, lenAccessLhs))

        self.cgen.stmt( \
            "%s = %s->strDupArray(%s, %s)" % \
            (accessRhs,
             self.poolVarName,
             accessLhs,
             lenAccessLhs))

        self.cgen.endIf()

    def onStaticArr(self, vulkanType):
        accessLhs = self.exprAccessorValueLhs(vulkanType)
        accessRhs = self.exprAccessorValueRhs(vulkanType)

        lenAccessLhs = self.lenAccessorLhs(vulkanType)

        bytesExpr = self.makeAllocBytesExpr(lenAccessLhs, vulkanType)
        self.cgen.stmt("memcpy(%s, %s, %s)" % (accessRhs, accessLhs, bytesExpr))

    def onStructExtension(self, vulkanType):

        lhs = self.exprAccessorLhs(vulkanType)
        rhs = self.exprAccessorRhs(vulkanType)

        rhsExpr = "(%s)(%s)" % ("void*", rhs)

        nextVar = "from_%s" % vulkanType.paramName
        sizeVar = "%s_size" % vulkanType.paramName

        self.cgen.beginIf("%s == VK_STRUCTURE_TYPE_MAX_ENUM" %
                          self.rootVarName)
        self.cgen.stmt("%s = from->sType" % self.rootVarName)
        self.cgen.endIf()

        self.cgen.stmt("const void* %s = %s" % (nextVar, self.inputVars[0]))
        self.cgen.stmt("size_t %s = 0u" % sizeVar)
        self.cgen.beginWhile("!%s && %s" % (sizeVar, nextVar))
        self.cgen.stmt("%s = static_cast<const vk_struct_common*>(%s)->%s" % (
            nextVar, nextVar, vulkanType.paramName
        ))
        self.cgen.stmt("%s = %s(%s, %s)" % (
            sizeVar, EXTENSION_SIZE_API_NAME, self.rootVarName, nextVar))
        self.cgen.endWhile()
        
        self.cgen.stmt("%s = nullptr" % rhs)

        self.cgen.beginIf(sizeVar)

        self.cgen.stmt( \
            "%s = %s%s->alloc(%s)" % \
            (rhs, self.makeCastExpr(vulkanType.getForNonConstAccess()), self.poolVarName, sizeVar))

        self.cgen.funcCall(None, self.prefix + "extension_struct",
                           [self.poolVarName, self.rootVarName, nextVar, rhsExpr])

        self.cgen.endIf()

    def onPointer(self, vulkanType):

        accessLhs = self.exprAccessorLhs(vulkanType)
        accessRhs = self.exprAccessorRhs(vulkanType)

        if self.needSkip(vulkanType):
            self.cgen.stmt("%s = nullptr" % accessRhs)
            return

        lenAccessLhs = self.lenAccessorLhs(vulkanType)

        self.cgen.stmt("%s = nullptr" % accessRhs)
        self.cgen.beginIf(accessLhs)

        bytesExpr = self.makeAllocBytesExpr(lenAccessLhs, vulkanType)

        self.cgen.stmt( \
            "%s = %s%s->dupArray(%s, %s)" % \
            (accessRhs,
             self.makeCastExpr(vulkanType.getForNonConstAccess()),
             self.poolVarName,
             accessLhs,
             bytesExpr))

        self.cgen.endIf()

    def onValue(self, vulkanType):
        if self.skipValues:
            return

        accessLhs = self.exprAccessorValueLhs(vulkanType)
        accessRhs = self.exprAccessorValueRhs(vulkanType)

        self.cgen.stmt("%s = %s" % (accessRhs, accessLhs))

class VulkanDeepcopy(VulkanWrapperGenerator):

    def __init__(self, module, typeInfo):
        VulkanWrapperGenerator.__init__(self, module, typeInfo)

        self.codegen = CodeGen()

        self.deepcopyPrefix = "deepcopy_"
        self.deepcopyVars = ["from", "to"]
        self.deepcopyAllocatorVarName = "alloc"
        self.deepcopyAllocatorParam = \
            makeVulkanTypeSimple(False, "Allocator", 1,
                                 self.deepcopyAllocatorVarName)
        self.deepcopyRootVarName = "rootType"
        self.deepcopyRootParam = \
            makeVulkanTypeSimple(False, "VkStructureType",
                                 0, self.deepcopyRootVarName)
        self.voidType = makeVulkanTypeSimple(False, "void", 0)

        self.deepcopyCodegen = \
            DeepcopyCodegen(
                None,
                self.deepcopyVars,
                self.deepcopyAllocatorVarName,
                self.deepcopyRootVarName,
                self.deepcopyPrefix,
                skipValues=True)

        self.knownDefs = {}

        self.extensionDeepcopyPrototype = \
            VulkanAPI(self.deepcopyPrefix + "extension_struct",
                      self.voidType,
                      [self.deepcopyAllocatorParam,
                       self.deepcopyRootParam,
                       STRUCT_EXTENSION_PARAM,
                       STRUCT_EXTENSION_PARAM_FOR_WRITE])

    def onBegin(self,):
        VulkanWrapperGenerator.onBegin(self)
        self.module.appendImpl(self.codegen.makeFuncDecl(
            self.extensionDeepcopyPrototype))

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

        if name in self.knownDefs:
            return

        category = self.typeInfo.categoryOf(name)

        if category in ["struct", "union"] and alias:
            self.module.appendHeader(
                self.codegen.makeFuncAlias(self.deepcopyPrefix + name,
                                           self.deepcopyPrefix + alias))

        if category in ["struct", "union"] and not alias:

            structInfo = self.typeInfo.structs[name]

            typeFromName = \
                lambda varname: \
                    makeVulkanTypeSimple(varname == "from", name, 1, varname)

            deepcopyParams = \
                [self.deepcopyAllocatorParam, self.deepcopyRootParam] + \
                 list(map(typeFromName, self.deepcopyVars))

            deepcopyPrototype = \
                VulkanAPI(self.deepcopyPrefix + name,
                          self.voidType,
                          deepcopyParams)

            def structDeepcopyDef(cgen):
                self.deepcopyCodegen.cgen = cgen
                canSimplyAssign = True
                for member in structInfo.members:
                    if not member.isSimpleValueType(self.typeInfo):
                        canSimplyAssign = False

                cgen.stmt("(void)%s" % self.deepcopyAllocatorVarName)
                cgen.stmt("(void)%s" % self.deepcopyRootVarName)
                cgen.stmt("*to = *from")
                if canSimplyAssign:
                    pass
                else:
                    for member in structInfo.members:
                        iterateVulkanType(self.typeInfo, member,
                                          self.deepcopyCodegen)

            self.module.appendHeader(
                self.codegen.makeFuncDecl(deepcopyPrototype))
            self.module.appendImpl(
                self.codegen.makeFuncImpl(deepcopyPrototype, structDeepcopyDef))

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

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

        def deepcopyDstExpr(cgen, typeName):
            return cgen.makeReinterpretCast( \
                       STRUCT_EXTENSION_PARAM_FOR_WRITE.paramName,
                       typeName, const=False)

        def forEachExtensionDeepcopy(ext, castedAccess, cgen):
            cgen.funcCall(None, self.deepcopyPrefix + ext.name,
                          [self.deepcopyAllocatorVarName,
                           self.deepcopyRootVarName,
                           castedAccess, deepcopyDstExpr(cgen, ext.name)])

        self.module.appendImpl(
            self.codegen.makeFuncImpl(
                self.extensionDeepcopyPrototype,
                lambda cgen: self.emitForEachStructExtension(
                    cgen,
                    self.voidType,
                    STRUCT_EXTENSION_PARAM,
                    forEachExtensionDeepcopy,
                    rootTypeVar=self.deepcopyRootParam)))
