#This will take a folder full of map files ripped from the game and create a blender asset library from them

#  Usage instructions:
#  Export koikatsu fbx animation files using https://www.youtube.com/watch?v=PeryYTsAN6E
#  put all the map folders you exported into one folder
#  any subfolder names in that folder will be used to tag them
#       (i.e. /Desktop/all maps/map1/map1 fbx files + textures, then /Desktop/all maps/map2/map2 fbx files + textures, etc )

#  Run this button from the kkbp extras section of the panel
#  You can also do it in small batches and rotate out the already imported fbx files for new ones
#  Or you can put a large list and kill blender when you want to pause the import process (it will resume from where it left off next time you run the script)
#  remember to save the library file when it's done

import bpy, os, time, pathlib
from bpy.props import StringProperty
from .importstudio import import_studio_objects
from .. import common as c
from ..importing.modifymaterial import modify_material
from ..interface.dictionary_en import t

def better_fbx_map_import(directory):
    already_loaded_images = [image.name for image in bpy.data.images]
    #import
    path = pathlib.Path(directory).rglob('*')
    obj_list = []
    for item in path:
        if '.fbx' in str(item):
            obj_list.append(str(item))
    for obj in obj_list:
        bpy.ops.better_import.fbx(filepath = obj, my_scale = 1.0)
    
    #if nothing was imported, skip
    if len(bpy.data.objects) < 2:
        return

    #delete duplicate objects and sky mesh
    objs_to_delete = [obj for obj in bpy.data.objects if '.001' in obj.name or '.002' in obj.name or '_koi_sky_' in obj.name]
    for obj in objs_to_delete:
        data_name = obj.data.name
        bpy.data.objects.remove(obj)
        bpy.data.meshes.remove(bpy.data.meshes[data_name])
    
    #remove all unused slots
    bpy.ops.object.select_all(action='SELECT')
    bpy.context.view_layer.objects.active = bpy.data.objects[1]
    bpy.ops.object.material_slot_remove_unused()
    bpy.ops.object.origin_set(type='ORIGIN_GEOMETRY', center='MEDIAN')
    
    #setup simple toon shader for all objects
    for obj in [mesh for mesh in bpy.data.objects if mesh.type == 'MESH' and mesh.material_slots[0].material]:
        #if the material already exists, use that, else create it
        try:
            obj.material_slots[0].material = bpy.data.materials['KK ' + obj.material_slots[0].material.name]
            c.kklog('Material already exists: ' + obj.material_slots[0].material.name)
        except:
            try:
                template = bpy.data.materials['KK Simple'].copy()
            except:
                script_dir=pathlib.Path(__file__).parent.parent
                template_path=(script_dir / '../KK Shader V8.0.blend').resolve()
                filepath = str(template_path)

                innerpath = 'Material'
                templateList = ['KK Simple']

                for template in templateList:
                    bpy.ops.wm.append(
                        filepath=os.path.join(filepath, innerpath, template),
                        directory=os.path.join(filepath, innerpath),
                        filename=template,
                        set_fake=False
                        )
                template = bpy.data.materials['KK Simple'].copy()
            if obj.material_slots[0].material:
                template.name = 'KK ' + obj.material_slots[0].material.name
                new_node = template.node_tree.nodes['Gentex'].node_tree.copy()
                template.node_tree.nodes['Gentex'].node_tree = new_node
                new_node.name = template.name
                main_image_link = [node for node in obj.material_slots[0].material.node_tree.nodes if node.type == 'BSDF_PRINCIPLED'][0].inputs[0]
                if main_image_link.is_linked:
                    main_image = main_image_link.links[0].from_node.image
                    #replace the dds image with a png version
                    new_path = main_image.filepath.replace(".dds", ".png").replace(".DDS", ".png")
                    new_image_name = main_image.name.replace(".dds", ".png").replace(".DDS", ".png")
                    main_image.save_render(bpy.path.abspath(new_path))
                    bpy.data.images.load(filepath=bpy.path.abspath(new_path))
                    bpy.data.images[new_image_name].pack()

                    #create darktex
                    bpy.context.scene.kkbp.import_dir = os.path.dirname(bpy.data.filepath) + '\\'
                    main_image = bpy.data.images[new_image_name]
                    dark_image = modify_material.create_darktex(main_image, [.764, .880, 1])
                    bpy.context.scene.kkbp.import_dir = ''

                    #saturate both with color code
                    lut_light = 'Lut_TimeDay.png'
                    lut_dark = 'Lut_TimeDay.png'
                    modify_material.load_luts(lut_light, lut_dark)

                    for image in [main_image, dark_image]:
                        print('converting ' + image.name)
                        image.save()
                        image.reload()
                        image.colorspace_settings.name = 'sRGB'
                        modify_material.image_to_KK(image, lut_light) #run twice because of bug
                        new_pixels, width, height = modify_material.image_to_KK(image, lut_light)
                        image.pixels = new_pixels
                    
                    #then load it in
                    new_node.nodes['light'].image = main_image
                    new_node.nodes['dark'].image = dark_image
                
                norm_image_link = [node for node in obj.material_slots[0].material.node_tree.nodes if node.type == 'BSDF_PRINCIPLED'][0].inputs[22]

                if norm_image_link.is_linked:
                    norm_image = norm_image_link.links[0].from_node.inputs[2].links[0].from_node.image
                    new_node.nodes['norm'].image == norm_image
                obj.material_slots[0].material = template

def main(folder):
    #Use the Better FBX importer addon if installed, else fallback to internal fbx importer
    use_better_fbx_importer = 'better_fbx' in [addon.module for addon in bpy.context.preferences.addons]

    c.toggle_console()
    start = time.time()

    #delete the default scene if present
    if len(bpy.data.objects) == 3:
        for obj in ['Camera', 'Light', 'Cube']:
            if bpy.data.objects.get(obj):
                bpy.data.objects.remove(bpy.data.objects[obj])

    #Set the view transform 
    bpy.context.scene.view_settings.view_transform = 'Standard'
    
    #import the fbx files
    fbx_folders = [(folder + sub) for sub in os.listdir(folder) if '.blend' not in sub] 
    print(fbx_folders)
    for map in fbx_folders:
        category = map.replace(folder, '')
        filename = map
        blend_filepath = map.replace(category,'') + category + '.blend'

        #if a .blend file already exists, don't process this fbx file
        if os.path.exists(blend_filepath):
            continue

        collection = bpy.data.collections.new(category)
        bpy.context.scene.collection.children.link(collection)
        layer_collection = bpy.context.view_layer.layer_collection
        #Recursivly transverse layer_collection for a particular name
        def recurLayerCollection(layerColl, collName):
            found = None
            if (layerColl.name == collName):
                return layerColl
            for layer in layerColl.children:
                found = recurLayerCollection(layer, collName)
                if found:
                    return found
                            
        layerColl = recurLayerCollection(layer_collection, collection.name)
        bpy.context.view_layer.active_layer_collection = layerColl

        #import map object based on Better FBX availability
        if use_better_fbx_importer:
            better_fbx_map_import(map)
        else:
            import_studio_objects(map)

        #skip if this was an empty folder
        if len(bpy.data.objects) < 2:
            bpy.data.collections.remove(collection)
            continue
        
        #apply all armature transforms
        arm = bpy.data.objects['Armature']
        bpy.ops.object.select_all(action='SELECT')
        bpy.context.view_layer.objects.active = arm
        bpy.ops.object.transform_apply(location=True, rotation=True, scale=False)
        #delete armature because the asset browser sucks
        bpy.data.objects.remove(arm)
        bpy.context.view_layer.objects.active = bpy.data.objects[1]
        bpy.ops.object.origin_set(type='ORIGIN_GEOMETRY', center='MEDIAN')

        #mark the collection as an asset and mark each object as an asset as long as it's not a wall, floor, ceiling or sky mesh
        collection.asset_mark()
        collection.asset_data.description = filename
        collection.asset_data.tags.new(filename)
        collection.asset_data.tags.new(category)

        reject_list = [
            '_yuka',
            '_wall',
            '_kabe',
            '_ten',
            '_black',
            '_yuka',
            'Armature',
            '_sotokabe',
            '_yane',
            '_hana',
            '_kuki',
            '_kusa',
            '_enkei',
            'fensu',
            'gura',
            '_kage',
            '_kmichi',
            '_kmichi',
            '_ie0',
            '_seimon',
            '_shadow',
            'hana_0',
            'kuki_0',
            'kusa_0',
            '_kyusui',
            '_saku',
            '_kumo',
            '_kaidan',
            '_nav',
            'nob',
            '_bushitu',
            'map20_kk00',
            '_styuka00',
            '_ueki0',
            '_kousya',
            '_kanten',
            'map21_light',
            'sky_hoshi',
            '_over',
            '_suido',
            '_kagamiwaku',
            'o_koi_map100h_00_0',
            'o_koi_map100_shawer00_00_0',
            '_kar0',
            'm00_o_box1__0',
            '_reef_tga',
            '_sky_star',
            '_o_tree',
            'o_ikegaki_0',
            'i_stu_kiha',
            'kouen_kakiwari_',
            'kouen_road',
            'kouen_pole',
            'kouen_sibahu',
            'mob_swimclub_',
            'map34_kk0',
            'p34_pool',
            'ap36_kikai',
            '_shitugaiki0',
            '_tatemono',
            'o_koi_map36_03_0',
            'i_mizukri',
            'koi_map17_kk00',
            '_karten',
            'i_gabyou',
            '_pos0',
            '_highyuka',
            'map70_mob',
            '_tesuri',
            'o_soto_doa',
            'o_soto_glass',
            'o_soto_mado',
            'o_koi_map80_00_s_0',
        ]
        for obj in collection.all_objects:
            mark_it = True
            for item in reject_list:
                if item in obj.name:
                    mark_it = False
                    break
            if mark_it:
                #apply transform then mark as asset
                #bpy.ops.object.select_all(action='DESELECT')
                #obj.select_set(True)
                #bpy.context.view_layer.objects.active = obj
                #bpy.ops.object.transform_apply(location=True, rotation=True, scale=False)
                obj.asset_mark()
                obj.asset_data.description = filename
                obj.asset_data.tags.new(obj.name)
                obj.asset_data.tags.new(category)

        #hide the collection afterwards
        bpy.context.scene.view_layers[0].active_layer_collection.exclude = True

        #load a script into the layout tab
#         if bpy.data.screens.get('Layout'):
#             for area in bpy.data.screens['Layout'].areas:
#                 if area.type == 'DOPESHEET_EDITOR':
#                     area.ui_type = 'TEXT_EDITOR'
#                     area.spaces[0].text = bpy.data.texts.new(name='Generate previews, save and close')
#                     area.spaces[0].text.write(
# '''#stolen script to generate thumbnails for all objects
# import bpy, functools, time

# assets = [o for o in bpy.data.objects if o.asset_data]  # Select all object assets
# assets.extend([m for m in bpy.data.materials if m.asset_data])  # Select all material assets

# for asset in assets:
#     asset.asset_generate_preview()

# while bpy.app.is_job_running('RENDER_PREVIEW') == True:
#     time.sleep(5)

# bpy.ops.wm.save_as_mainfile(filepath=bpy.data.filepath)
# time.sleep(3)
# bpy.ops.wm.quit_blender()

# ''')

        print(blend_filepath)
        bpy.ops.wm.save_as_mainfile(filepath = blend_filepath)
        bpy.data.collections.remove(collection)
        for block in bpy.data.objects:
            bpy.data.objects.remove(block)
        for block in bpy.data.meshes:
            bpy.data.meshes.remove(block)
        for block in bpy.data.materials:
            bpy.data.materials.remove(block)
        for block in bpy.data.armatures:
            bpy.data.armatures.remove(block)
        for block in bpy.data.images:
            bpy.data.images.remove(block)
        for block in bpy.data.node_groups:
            bpy.data.node_groups.remove(block)
        
    print(str(time.time() - start))
    c.toggle_console()


class map_asset_lib(bpy.types.Operator):
    bl_idname = "kkbp.createmapassetlib"
    bl_label = "Create map asset library"
    bl_description = t('map_library_tt')
    bl_options = {'REGISTER', 'UNDO'}
    
    directory : StringProperty(maxlen=1024, default='', subtype='FILE_PATH', options={'HIDDEN'})
    filter_glob : StringProperty(default='', options={'HIDDEN'})
    data = None
    mats_uv = None
    structure = None
    
    def execute(self, context):        
        main(self.directory)
        return {'FINISHED'}
        
    def invoke(self, context, event):
        context.window_manager.fileselect_add(self)
        return {'RUNNING_MODAL'}
    
if __name__ == "__main__":
    bpy.utils.register_class(map_asset_lib)
    
    # test call
    print((bpy.ops.kkbp.createmapassetlib('INVOKE_DEFAULT')))