# 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

class HandleMapCodegen(VulkanTypeIterator):
    def __init__(self, cgen, inputVar, handlemapVarName, prefix, isHandleFunc):
        self.cgen = cgen
        self.inputVar = inputVar
        self.prefix = prefix
        self.handlemapVarName = handlemapVarName

        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.isHandleFunc = isHandleFunc

    def needSkip(self, vulkanType):
        return False

    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):

        if self.needSkip(vulkanType):
            self.cgen.line("// TODO: Unsupported : %s" %
                           self.cgen.makeCTypeDecl(vulkanType))
            return
        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)
        self.cgen.funcCall(None, self.prefix + vulkanType.typeName,
                           [self.handlemapVarName, 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):
        if not self.isHandleFunc(vulkanType):
            return

        accessLhs = self.exprAccessor(vulkanType)
        lenAccess = self.lenAccessor(vulkanType)

        self.cgen.stmt("%s->mapHandles_%s(%s%s, %s)" % \
            (self.handlemapVarName, vulkanType.typeName,
             self.makeCastExpr(vulkanType.getForAddressAccess().getForNonConstAccess()),
             accessLhs, lenAccess))

    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.handlemapVarName, castedAccessExpr])
        self.cgen.endIf()

    def onPointer(self, vulkanType):
        if self.needSkip(vulkanType):
            return

        if not self.isHandleFunc(vulkanType):
            return

        access = self.exprAccessor(vulkanType)
        lenAccess = self.lenAccessor(vulkanType)
        lenAccess = "1" if lenAccess is None else lenAccess

        self.cgen.beginIf(access)

        self.cgen.stmt( \
            "%s->mapHandles_%s(%s%s, %s)" % \
            (self.handlemapVarName,
             vulkanType.typeName,
             self.makeCastExpr(vulkanType.getForNonConstAccess()),
             access,
             lenAccess))

        self.cgen.endIf()

    def onValue(self, vulkanType):
        if not self.isHandleFunc(vulkanType):
            return
        access = self.exprAccessor(vulkanType)
        self.cgen.stmt(
            "%s->mapHandles_%s(%s%s)" % \
            (self.handlemapVarName, vulkanType.typeName,
             self.makeCastExpr(vulkanType.getForAddressAccess().getForNonConstAccess()),
             access))

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

        self.codegen = CodeGen()

        self.handlemapPrefix = "handlemap_"
        self.toMapVar = "toMap"
        self.handlemapVarName = "handlemap"
        self.handlemapParam = \
            makeVulkanTypeSimple(False, "VulkanHandleMapping", 1,
                                 self.handlemapVarName)
        self.voidType = makeVulkanTypeSimple(False, "void", 0)

        self.handlemapCodegen = \
            HandleMapCodegen(
                None,
                self.toMapVar,
                self.handlemapVarName,
                self.handlemapPrefix,
                lambda vtype : typeInfo.isHandleType(vtype.typeName))

        self.knownDefs = {}

        self.extensionHandlemapPrototype = \
            VulkanAPI(self.handlemapPrefix + "extension_struct",
                      self.voidType,
                      [self.handlemapParam, STRUCT_EXTENSION_PARAM_FOR_WRITE])

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

    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.handlemapPrefix + name,
                                           self.handlemapPrefix + alias))

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

            structInfo = self.typeInfo.structs[name]

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

            handlemapParams = \
                [self.handlemapParam] + \
                list(map(typeFromName, [self.toMapVar]))

            handlemapPrototype = \
                VulkanAPI(self.handlemapPrefix + name,
                          self.voidType,
                          handlemapParams)

            def funcDefGenerator(cgen):
                self.handlemapCodegen.cgen = cgen
                for p in handlemapParams:
                    cgen.stmt("(void)%s" % p.paramName)
                for member in structInfo.members:
                    iterateVulkanType(self.typeInfo, member,
                                      self.handlemapCodegen)

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

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

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

        def forEachExtensionHandlemap(ext, castedAccess, cgen):
            cgen.funcCall(None, self.handlemapPrefix + ext.name,
                          [self.handlemapVarName, castedAccess])

        self.module.appendImpl(
            self.codegen.makeFuncImpl(
                self.extensionHandlemapPrototype,
                lambda cgen: self.emitForEachStructExtension(
                    cgen,
                    self.voidType,
                    STRUCT_EXTENSION_PARAM_FOR_WRITE,
                    forEachExtensionHandlemap)))
