# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#

import os
import bpy
import struct
import math
import bmesh
from mathutils import Vector
from mathutils import Quaternion
from . import kex_utils
from . import turok_map
from . import turok_import_model
from . import turok_import_anim
from . import turok_object_panel
from bpy_extras.wm_utils.progress_report import (
    ProgressReport,
    ProgressReportSubstep,
)

# -----------------------------------------------------------------------------
# returns obj
def create_sectors_obj(map):
    mesh = bpy.data.meshes.new('mesh')
    if len(map.collisionVertices) > 0 and len(map.collisionSectors) > 0:
        #create verts and tris
        verts = [None] * len(map.collisionVertices)
        for i, v in enumerate(map.collisionVertices):
            verts[i] = Vector((v[0], v[1], v[2]))
        tris = [None] * len(map.collisionSectors)
        for i, s in enumerate(map.collisionSectors):
            tris[i] = (s.indices[0], s.indices[1], s.indices[2])
            
        mesh.from_pydata(verts, [], tris)
        mesh.validate(clean_customdata=False)
        mesh.update(calc_edges=True)
        mesh.calc_normals()
        
    #end if
    obj = kex_utils.create_turok_object("Sectors", mesh, "MAP SECTORS", "XYZ")
    #obj.show_in_front = True
    obj.lock_location = (True, True, True)
    obj.lock_rotation = (True, True, True)
    obj.lock_scale = (True, True, True)
    obj.show_wire = True
    obj.display.show_shadows = False
    modDis = obj.modifiers.new("Displacement", "DISPLACE")
    modDis.direction = 'NORMAL'
    modDis.mid_level = 0.0
    modDis.strength = 2.56
    modDis.show_in_editmode = False
    modDis.show_viewport = True
    modDis.show_on_cage = False
    
    #setup materials with shader nodes that use alpha
    for sectorMatInfo in kex_utils.T1_MATS_SECTORS:
        mesh.materials.append(bpy.data.materials[sectorMatInfo[0]])
    
    #set mesh polygons t1 data
    #apply material based on sector flags
    ceiling_verts = [] #array of mathutils.vector
    ceiling_tris = []
    ceiling_indice_dict = {}
    last_ceiling_index = -1
    bm = bmesh.new()
    bm.from_mesh(mesh)
    kex_utils.create_BMLayers(bm)
    for v in bm.verts:
        kex_utils.bmvert_to_map_sector(map, v)
    #end for
    for f in bm.faces:
        kex_utils.bmface_to_map_sector(map, f)
        kex_utils.bmface_update_material_index(mesh, f)
        
        #get the verts and tris used (faces that have ceiling flag)
        if kex_utils.bmface_has_ceiling(f):
            tri_indices = []
            for face_vert in f.verts:
                ceiling_index = ceiling_indice_dict.get(face_vert.index)
                if ceiling_index is None:
                    last_ceiling_index += 1
                    map_vert = map.collisionVertices[face_vert.index]
                    ceiling_verts.append(Vector((face_vert.co.x, face_vert.co.y, map_vert[3])))
                    ceiling_index = last_ceiling_index
                    ceiling_indice_dict[face_vert.index] = last_ceiling_index
                #end if
                tri_indices.append(ceiling_index)
            #end for
            ceiling_tris.append((tri_indices[1], tri_indices[0], tri_indices[2])) #flipped indices 0,1
        #end if
    #end if
    bm.to_mesh(mesh)
    bm.free()
    
    ceilingMesh = bpy.data.meshes.new('mesh_ceiling')
    if len(ceiling_verts) > 0 and len(ceiling_tris) > 0:
        # ceilingMesh.from_pydata(ceiling_verts, [], ceiling_tris)
        # ceilingMesh.validate(clean_customdata=False)
        # ceilingMesh.update(calc_edges=True)
        ceilingBM = bmesh.new()
        ceilingBM.from_mesh(ceilingMesh)
        kex_utils.create_BMLayers(ceilingBM)
        
        sortedKeys = sorted(ceiling_indice_dict, key=ceiling_indice_dict.__getitem__)
        bVerts = []
        for orgVertIndex in sortedKeys:
            map_vert = map.collisionVertices[orgVertIndex]
            bVert = ceilingBM.verts.new((map_vert[0], map_vert[1], map_vert[3]))
            bVert[kex_utils.VL_CEILINGLINK] = orgVertIndex
            bVert.index = ceiling_indice_dict[orgVertIndex] #should start at zero and increase by 1 every vert
            bVerts.append(bVert)
        #end for
        
        for tri in ceiling_tris:
            ceilingBM.faces.new((bVerts[tri[0]], bVerts[tri[1]], bVerts[tri[2]]))
        #end for
        
        ceilingBM.to_mesh(ceilingMesh)
        ceilingBM.free()
    #end if
    ceiling_indice_dict.clear()
    ceilingMesh.materials.append(bpy.data.materials[kex_utils.mat_sector_ceiling])
    ceilingObj = kex_utils.create_turok_object("Ceiling", ceilingMesh, "MAP CEILING SECTORS", "XYZ")
    ceilingObj.parent = obj
    ceilingObj.lock_location = (True, True, True)
    ceilingObj.lock_rotation = (True, True, True)
    ceilingObj.lock_scale = (True, True, True)
    ceilingObj.show_wire = True
    ceilingObj.display.show_shadows = False
    
    return obj
#end func

# -----------------------------------------------------------------------------
# 
def recreate_sector_ceiling_edit_mesh(sectorObj):
    ceiling_tris = []
    ceiling_indice_dict = {}
    ceiling_vertpos_dict = {}
    last_ceiling_index = -1
    sectorMesh = sectorObj.data
    sectorBM = bmesh.new()
    sectorBM.from_edit_mesh(sectorMesh)
    kex_utils.create_BMLayers(sectorBM)
    for f in sectorBM.faces:
        #get the verts and tris used (faces that have ceiling flag)
        if kex_utils.bmface_has_ceiling(f):
            tri_indices = []
            for face_vert in f.verts:
                ceiling_index = ceiling_indice_dict.get(face_vert.index)
                if ceiling_index is None:
                    last_ceiling_index += 1
                    ceiling_index = last_ceiling_index
                    ceiling_indice_dict[face_vert.index] = last_ceiling_index
                    vertWorldPos = sectorObj.matrix_world @ Vector((face_vert.co.x, face_vert.co.y, 0.0))
                    vertWorldPos.z = face_vert[kex_utils.VL_CEILINGZ]
                    ceiling_vertpos_dict[last_ceiling_index] = vertWorldPos
                #end if
                tri_indices.append(ceiling_index)
            #end for
            ceiling_tris.append((tri_indices[1], tri_indices[0], tri_indices[2])) #flipped indices 0,1
        #end if
    #end if
    sectorBM.to_mesh(sectorMesh)
    sectorBM.free()

    ceilingObj = next((x for x in sectorObj.children if x.type == "MESH" and x.t1.objType == "MAP CEILING SECTORS"), None)
        
    if ceilingObj is None:
        return
    
    ceilingMesh = ceilingObj.data
    ceilingBM = bmesh.new()
    ceilingBM.from_mesh(ceilingMesh)
    ceilingBM.clear()
    kex_utils.create_BMLayers(ceilingBM)
    sortedKeys = sorted(ceiling_indice_dict, key=ceiling_indice_dict.__getitem__)
    bVerts = []
    for orgVertIndex in sortedKeys:
        local_pos = ceilingObj.matrix_world.inverted() @ ceiling_vertpos_dict[ceiling_verts[orgVertIndex]]
        bVert = ceilingBM.verts.new(local_pos)
        bVert[kex_utils.VL_CEILINGLINK] = orgVertIndex
        bVert.index = ceiling_indice_dict[orgVertIndex] #should start at zero and increase by 1 every vert
        bVerts.append(bVert)
    #end for
    
    for tri in ceiling_tris:
        ceilingBM.faces.new((bVerts[tri[0]], bVerts[tri[1]], bVerts[tri[2]]))
    #end for
    
    ceilingBM.to_mesh(ceilingMesh)
    ceilingBM.free()
#end func

# -----------------------------------------------------------------------------
# returns obj
def create_mesh_object(objName, turokObjType, tris, vertsCO, vertsUV, vertsNormals):
    mesh = bpy.data.meshes.new('mesh')
    #create mesh from tris and verts
    if len(tris) > 0 and len(vertsCO) > 0:
        mesh.from_pydata(vertsCO, [], tris)
        mesh.validate(clean_customdata=False)
        mesh.update(calc_edges=True)

        if len(vertsNormals) > 0:
            #set custom normals
            mesh.use_auto_smooth = True
            mesh.normals_split_custom_set_from_vertices(vertsNormals)
            mesh.calc_normals_split()
            for vert in mesh.vertices:
                vert.normal = vertsNormals[vert.index]
            for loop in mesh.loops:
                loop.normal = vertsNormals[loop.vertex_index]
        else:
            mesh.calc_normals()
        #end if

        if len(vertsUV) > 0:
            # create uv layer
            uv_layer = mesh.uv_layers.new()
            for loop in mesh.loops:
                uv_layer.data[loop.index].uv = vertsUV[loop.index]
            #end for
        #end if
    #end if

    # create mesh scene object
    obj = kex_utils.create_turok_object(objName, mesh, turokObjType, "XYZ")
    #bpy.context.view_layer.objects.active = obj
    
    return obj
#end func

# -----------------------------------------------------------------------------
# 
def setup_actor_object(actor, modelObj):
    if modelObj is not None:
        #when writing back to the Map class remember to do: actor.yaw -= math.pi
        #actor.sightRange = math.pow(actor.sightRange, 2)
        
        modelObj.t1.ignoreUpdateFuncs = True
        modelObj.rotation_euler = (0.0, 0.0, math.pi - actor.yaw)
        modelObj.lock_rotation = (True, True, False)
        modelObj.location = actor.origin
        modelObj.scale = actor.scale
        modelObj.t1.actorType = actor.actorID
        modelObj.t1.actorModelPath = actor.modelPath
        modelObj.t1.actorAnimPath = actor.animPath
        modelObj.t1.actorSpeciesMask = actor.speciesMask
        modelObj.t1.actorSectorIndex = actor.sectorIndex
        modelObj.t1.actorBoundsMin = actor.boundsMin
        modelObj.t1.actorBoundsMax = actor.boundsMax
        modelObj.t1.actorSightRange = math.sqrt(actor.sightRange)
        modelObj.t1.actorSightFOV = actor.sightFOV
        modelObj.t1.actorLoudRange = math.sqrt(actor.loudRange)
        modelObj.t1.actorQuietRange = math.sqrt(actor.quietRange)
        modelObj.t1.actorAttackRange = math.sqrt(actor.attackRange)
        modelObj.t1.actorFlyHeight = math.sqrt(actor.flyHeight)
        modelObj.t1.actorWidth = actor.width
        modelObj.t1.actorWallWidth = actor.wallWidth
        modelObj.t1.actorHeight = actor.height
        modelObj.t1.actorDeadHeight = actor.deadHeight
        modelObj.t1.actorMeleeRange = math.sqrt(actor.meleeRange)
        modelObj.t1.actorLeashRadius = math.sqrt(actor.leashRadius)
        modelObj.t1.actorTriggerDelay = actor.triggerDelay
        modelObj.t1.actorSpawnFlags1 = kex_utils.int_to_flags(turok_object_panel.T1ActorSpawnFlags1Items, actor.spawnFlags1)
        modelObj.t1.actorSpawnFlags2 = kex_utils.int_to_flags(turok_object_panel.T1ActorSpawnFlags2Items, actor.spawnFlags2)
        modelObj.t1.actorSpawnFlags3 = kex_utils.int_to_flags(turok_object_panel.T1ActorSpawnFlags3Items, actor.spawnFlags3)
        modelObj.t1.actorHealth = actor.health
        modelObj.t1.actorTID = actor.TID
        modelObj.t1.actorTargetTID = actor.targetTID
        modelObj.t1.actorMaxRegenerations = actor.maxRegenerations
        modelObj.t1.actorAttackChance = actor.attackChance
        modelObj.t1.actorTriggerAnim = actor.triggerAnim
        modelObj.t1.actorVariant = actor.variant
        modelObj.t1.actorTexture = actor.texture
        modelObj.t1.actorParams1 = actor.params1
        modelObj.t1.actorParams2 = actor.params2
        kex_utils.set_obj_material_tex_index(modelObj, actor.texture)
        modelObj.t1.ignoreUpdateFuncs = False
    #end if
#end func

# -----------------------------------------------------------------------------
# 
def setup_staticmesh_object(staticMesh, modelObj):
    if modelObj is not None:
        modelObj.t1.ignoreUpdateFuncs = True
        modelObj.location = staticMesh.origin
        modelObj.scale = staticMesh.scale
        modelObj.rotation_mode = "QUATERNION"
        modelObj.rotation_quaternion = staticMesh.rotation
        modelObj.rotation_mode = "XYZ"
        modelObj.t1.staticmeshModelPath = staticMesh.modelPath
        modelObj.t1.staticmeshFlags = kex_utils.int_to_flags(turok_object_panel.T1StaticMeshFlags, staticMesh.flags)
        modelObj.t1.staticmeshRadius = staticMesh.collisionWidth
        modelObj.t1.staticmeshHeight = staticMesh.collisionHeight
        modelObj.t1.staticmeshTexture = staticMesh.texIndex
        modelObj.t1.staticmeshCullBits = staticMesh.cullBits
        modelObj.t1.staticmeshSectorIndex = staticMesh.sectorIndex
        modelObj.t1.staticmeshBoundsMin = staticMesh.boundsMin
        modelObj.t1.staticmeshBoundsMax = staticMesh.boundsMax
        kex_utils.set_obj_material_tex_index(modelObj, staticMesh.texIndex)
        modelObj.t1.ignoreUpdateFuncs = False
    #end if
#end func
# -----------------------------------------------------------------------------
# Returns true if successful
def load(operator, context, filepath, global_matrix, importType, importSectors, loadVis):
    with ProgressReport(context.window_manager) as progress:
        progress.enter_substeps(8)
        print("Importing Turok Map %r ..." % filepath)
        
        dir, fileName = os.path.split(filepath)
        fileNameNoExt, fileExt = os.path.splitext(fileName)
        scene = bpy.context.scene
        scene.cursor.location = (0.0, 0.0, 0.0) #need to have the cursor position at center
        
        #Load map
        map = turok_map.Map()
        with open(filepath, 'rb') as data:
            data.seek(0)
            map.read(data, loadVis)
        #end with
        
        # with open(filepath + "_out2", 'wb') as data:
            # map.write(data)
        # #end with
        
        #Progress Info on Map
        staticMeshCount = 0
        for i in range(len(map.gridBounds.sections)):
            staticMeshCount += len(map.gridBounds.sections[i].staticMeshes)
        progress.step("Loaded Map (sectors:%i staticmeshes:%i actors:%i)" % (len(map.collisionSectors), staticMeshCount, len(map.actors)))

        #create material colors if need to
        kex_utils.try_create_color_mats()
        
        #Load and Cache all unique StaticMeshes and Actors
        staticMeshObjCache = {}
        actorObjCache = {}
        actorObjEmptyCache = {}
        modelCache = {}
        animCache = {}
        unique_materials = None
        actorsObj = kex_utils.create_turok_object("Actors", None, "NONE", "XYZ")
        actorsObj.lock_location = (True, True, True)
        actorsObj.lock_rotation = (True, True, True)
        actorsObj.lock_scale = (True, True, True)
        lastModelCacheCount = 0
        lastMaterialCount = 0
        for ob in context.view_layer.objects.selected:
            ob.select_set(False)
            
        #Cache Actors
        if importType == "ALL" or importType == "ACTORS":
            for actorIndex, actor in enumerate(map.actors):
                modelObj = None
                key = "%s|%s" % (actor.modelPath, actor.animPath)
                if key not in actorObjCache:
                    modelFilePath = kex_utils.find_t1_file_path(actor.modelPath)
                    if modelFilePath is not None:
                        cachedModel = modelCache.get(modelFilePath)
                        modelObjs, model, unique_materials = turok_import_model.load(operator, None, context, modelFilePath, global_matrix, False, 2, cachedModel, unique_materials)
                        if model is not None and modelFilePath not in modelCache:
                            modelCache[modelFilePath] = model
                        #end if
                        
                        if modelObjs is not None:
                            modelObj = modelObjs[0]
                            if modelObj is not None:
                                #Get/Load First Anim
                                animFilePath = ""
                                if actor.animPath in animCache:
                                    cachedAnim = animCache[actor.animPath]
                                    if cachedAnim is not None:
                                        turok_import_anim.load_map_version(operator, context, modelObjs, cachedAnim, "", global_matrix)
                                    #end if
                                else:
                                    animFilePath = kex_utils.find_t1_file_path(actor.animPath)
                                    animData = None
                                    if animFilePath is not None:
                                        animData = turok_import_anim.load_map_version(operator, context, modelObjs, None, animFilePath, global_matrix)
                                    #end if
                                    animCache[actor.animPath] = animData
                                #end if
                                
                                #Join meshes and apply it's transform
                                if len(modelObjs) > 1:
                                    #check if meshes have verts
                                    meshWithVertsCount = 0
                                    for obj in modelObjs:
                                        if len(obj.data.vertices) > 0:
                                            meshWithVertsCount += 1
                                            if meshWithVertsCount > 1:
                                                break
                                        #end if
                                    #end for
                                    context.view_layer.objects.active = modelObj
                                    for ob in modelObjs:
                                        ob.select_set(True)
                                    if meshWithVertsCount > 1:
                                        bpy.ops.object.join()
                                        bpy.ops.object.transform_apply(location = True, scale = False, rotation = True, properties = False)
                                        #Make a copy and delete the old joined object because the join operator
                                        #makes the object corrupt (seems like a blender bug)
                                        oldObj = modelObj
                                        oldObjName = oldObj.name
                                        modelObj = kex_utils.create_turok_object(modelObj.name, modelObj.data, modelObj.t1.objType)
                                        bpy.data.objects.remove(oldObj, do_unlink=True)
                                        modelObj.name = oldObjName
                                    else:
                                        bpy.ops.object.transform_apply(location = True, scale = False, rotation = True, properties = False)
                                    #end if
                                    for ob in context.view_layer.objects.selected:
                                        ob.select_set(False)
                                    context.view_layer.objects.active = None
                                else:
                                    context.view_layer.objects.active = modelObj
                                    modelObj.select_set(True)
                                    bpy.ops.object.transform_apply(location = True, scale = False, rotation = True, properties = False)
                                    modelObj.select_set(False)
                                    context.view_layer.objects.active = None
                                #end if
                                modelObj.rotation_mode = "XYZ"
                                setup_actor_object(actor, modelObj)
                                modelObj.parent = actorsObj
                                actorObjCache[key] = [modelObj, actorIndex]
                            #endif
                        #endif
                    #end if
                    if modelObj is None:
                        #different empty actors may be look different with different icons
                        if actor.actorID not in actorObjEmptyCache:
                            #name should be from def type
                            cubeSize = 1.28 #20.48
                            modelObj = kex_utils.create_turok_object_cube("ActorType_%i" % (actor.actorID), "MAP ACTOR",
                                        Vector((-cubeSize, -cubeSize, -cubeSize)), Vector((cubeSize, cubeSize, cubeSize)), rotMode="XYZ")
                            modelObj.data.materials.append(bpy.data.materials[kex_utils.mat_color_red])
                            setup_actor_object(actor, modelObj)
                            modelObj.parent = actorsObj
                            actorObjEmptyCache[actor.actorID] = [modelObj, actorIndex]
                        #end if
                    #end if
                #end if
            #end for
            lastModelCacheCount = len(modelCache)
            lastMaterialCount = 0
            if unique_materials is not None:
                lastMaterialCount = len(unique_materials)
            progress.step("Cached %i Actor Objects, %i Models, %i Animations, %i Materials" % ((len(actorObjCache) + len(actorObjEmptyCache)), lastModelCacheCount, len(animCache), lastMaterialCount))
            animCache.clear()
        else:
            progress.step()
        #end if
        
        #Cache StaticMeshes
        staticMeshesObj = kex_utils.create_turok_object("StaticMeshes", None, "NONE", "XYZ")
        staticMeshesObj.lock_location = (True, True, True)
        staticMeshesObj.lock_rotation = (True, True, True)
        staticMeshesObj.lock_scale = (True, True, True)
        if importType == "ALL" or importType == "STATICMESHES":
            staticMeshIndex = -1
            for section in map.gridBounds.sections:
                for staticMesh in section.staticMeshes:
                    staticMeshIndex += 1
                    modelObj = None
                    if staticMesh.modelPath not in staticMeshObjCache:
                        modelFilePath = kex_utils.find_t1_file_path(staticMesh.modelPath)
                        if modelFilePath is not None:
                            cachedModel = modelCache.get(modelFilePath)
                            modelObjs, model, unique_materials = turok_import_model.load(operator, None, context, modelFilePath, global_matrix, False, 1, cachedModel, unique_materials)
                            if model is not None and modelFilePath not in modelCache:
                                modelCache[modelFilePath] = model
                            #end if
                            if modelObjs is not None:
                                modelObj = modelObjs[0]
                                if modelObj is not None:
                                    setup_staticmesh_object(staticMesh, modelObj)
                                    #modelObj.rotation_mode = "XYZ"
                                    modelObj.parent = staticMeshesObj
                                    staticMeshObjCache[staticMesh.modelPath] = [modelObj, staticMeshIndex]
                                #endif
                            #end if
                        #end if
                        
                        if modelObj is None:
                            modelDir, modelFileName = os.path.split(staticMesh.modelPath)
                            modelName, modelFileExt = os.path.splitext(modelFileName)
                            if modelName == "":
                                modelName = "StaticMesh"
                            #end if
                            cubeSize = 1.28 #20.48
                            modelObj = kex_utils.create_turok_object_cube(modelName, "MAP STATICMESH",
                                        Vector((-cubeSize, -cubeSize, -cubeSize)), Vector((cubeSize, cubeSize, cubeSize)), rotMode="XYZ")
                            modelObj.data.materials.append(bpy.data.materials[kex_utils.mat_color_green])
                            setup_staticmesh_object(staticMesh, modelObj)
                            modelObj.parent = staticMeshesObj
                            staticMeshObjCache[staticMesh.modelPath] = [modelObj, staticMeshIndex]
                        #end if
                    #end if
                #end for
            #end for
            progress.step("Cached %i StaticMesh Objects, %i Models, %i Materials" % (len(staticMeshObjCache), (len(modelCache) - lastModelCacheCount), (len(unique_materials) - lastMaterialCount)))
        else:
            progress.step()
        #end if

        #Create Root Map Object
        mapObj = kex_utils.create_turok_object(fileNameNoExt, None, "MAP ROOT", "XYZ")
        mapObj.lock_location = (True, True, True)
        mapObj.lock_rotation = (True, True, True)
        mapObj.lock_scale = (True, True, True)
        mapObj.t1.mapAmbientColor = map.worldInfo["ambientColor"]
        mapObj.t1.mapSkyMaterial = map.worldInfo["material"]
        mapObj.t1.mapSunlightDirection = map.worldInfo["sunlightDirection"]
        mapObj.t1.mapSunlightColor = map.worldInfo["sunlightColor"]
        actorsObj.parent = mapObj
        staticMeshesObj.parent = mapObj

        #Set Visibility Tables
        if map.visibilityCount > 0:
            imageName = "_%s_vis" % (fileNameNoExt)
            img = bpy.data.images.get(imageName, None)
            if img is None:
                img = bpy.data.images.new(imageName, 1, 1, is_data=True)
                if img.packed_file is None:
                    img.pack(data=bytes(map.visibility), data_len=len(map.visibility))
                #end if
            #end if
            mapObj.t1.mapVisCount = map.visibilityCount
            mapObj.t1.mapVisSize = map.visibilitySize
            mapObj.t1.mapVisImage = img
            progress.step("Created Visibility Tables (%f MB)" % (len(map.visibility)/1048576))
        else:
            progress.step()
        #end if
        
        # import bpy

        # byteData = bytearray(4)
        # byteData[0] = 7
        # imgName = "level12d_vis"
        # if imgName in bpy.data.images:
            # img = bpy.data.images[imgName]
        # else:
            # img = bpy.data.images.new(imgName, 16, 16, is_data=True)
        # #end if

        # print("img.packed_file: %s" % (img.packed_file))
        # if img.packed_file is None:
            # img.pack(data=bytes(byteData), data_len=len(byteData))
        # else:
            # print("size: %s, data: %s" % (img.packed_file.size, img.packed_file.data))
        # #end if

        
        
        # for i in range(len(map.visibility)):
            # if len(map.visibility[i]) == 0:
                # continue
            # sectorsTable = bytearray(len(map.visibility[i]))
            # mapObj.t1.mapVis.append(sectorsTable)
            # for i2 in range(len(map.visibility[i])):
                # sectorsTable[i2] = map.visibility[i][i2]
                # maskPropGroup = sectorsPropGroup.sectors.add()
                # maskPropGroup.staticMeshMask = map.visibility[i][i2]
                # visByteCount += 1
            # #end for
            
            # # sectorsPropGroup = mapObj.t1.mapVis.add()
            # # for i2 in range(len(map.visibility[i])):
                # # maskPropGroup = sectorsPropGroup.sectors.add()
                # # maskPropGroup.staticMeshMask = map.visibility[i][i2]
                # # visByteCount += 1
            # # #end for
        # #end for

        # if visByteCount > 0:
            # progress.step("Created Visibility Tables (%f Megabytes)" % (visByteCount/1048576))
        # else:
            # progress.step()
        #progress.step()
            
        #Create Sun
        # lightData = bpy.data.lights.new(name="Sun", type='SUN')
        # lightData.energy = 1.0
        # lightData.color = map.worldInfo["sunlightColor"]
        #lightData.color = map.worldInfo["sunlightDirection"]
        # sunObj = kex_utils.create_turok_object("Sun", lightData, "MAP SUN", "XYZ")
        # sunObj.parent = mapObj
        #sunObjDirVec = obj.rotation_quaternion @ Vector((0.0, 0.0, 1.0))
        
        #Create Sectors
        if importSectors:
            sectorsObj = create_sectors_obj(map)
            sectorsObj.parent = mapObj
            progress.step("Created Sectors Mesh Object")
        else:
            progress.step()
        #end if
        
        #Create Actors
        if importType == "ALL" or importType == "ACTORS":
            cacheObj = None
            cacheObjIndex = -1
            modelObj = None
            for actorIndex, actor in enumerate(map.actors):
                key = "%s|%s" % (actor.modelPath, actor.animPath)
                if key in actorObjCache:
                    cacheObj, cacheObjIndex = actorObjCache[key]
                else: #is actor with no valid model file path
                    cacheObj, cacheObjIndex = actorObjEmptyCache[actor.actorID]
                #end if
                
                #skip cached objects since they are already setup
                if cacheObjIndex == actorIndex:
                    # kex_utils.set_obj_material_tex_index(cacheObj, cacheObj.t1.actorTexture)
                    continue
                #end if
                modelObj = kex_utils.create_turok_object(cacheObj.name, cacheObj.data.copy(), cacheObj.t1.objType, "XYZ")
                setup_actor_object(actor, modelObj)
                modelObj.parent = actorsObj
            #end for
            actorObjCache.clear()
            actorObjEmptyCache.clear()
            progress.step("Created %i Actor Objects" % (len(map.actors)))
        else:
            progress.step()
        #end if

        #Create Staticmeshes
        if importType == "ALL" or importType == "STATICMESHES":
            staticMeshIndex = -1
            for section in map.gridBounds.sections:
                for staticMesh in section.staticMeshes:
                    staticMeshIndex += 1
                    cacheObj, cacheObjIndex = staticMeshObjCache[staticMesh.modelPath]
                    #skip cached objects since they are already setup
                    if cacheObjIndex == staticMeshIndex:
                        # kex_utils.set_obj_material_tex_index(cacheObj, cacheObj.t1.staticmeshTexture)
                        continue
                    #end if
                    modelObj = kex_utils.create_turok_object(cacheObj.name, cacheObj.data.copy(), cacheObj.t1.objType, "XYZ")
                    setup_staticmesh_object(staticMesh, modelObj)
                    modelObj.parent = staticMeshesObj
                #end for
            #end for
            progress.step("Created %i StaticMesh Objects" % (staticMeshCount))
        else:
            progress.step()
        #end if
                
        progress.leave_substeps("Map Successfully Imported!")
    #end with
    return True    
#end func
