
"""
Plugin for making an asset library of all  blender file found in a folder
"""


from .scan_folder import ScanFolder
from ..core.bl_utils import load_datablocks
from ..core.template import Template

import bpy
from bpy.props import (StringProperty, IntProperty, BoolProperty)
import re
from pathlib import Path
from itertools import groupby
import uuid
import os
import shutil
import json
import time
from pprint import pprint


class Conform(ScanFolder):

    name = "Conform"
    source_directory : StringProperty(subtype='DIR_PATH')

    target_template_file : StringProperty()
    target_template_info : StringProperty()
    target_template_image : StringProperty()
    target_template_video : StringProperty()

    def draw_prefs(self, layout):
        layout.prop(self, "source_directory", text="Source :  Directory")

        col = layout.column(align=True)
        col.prop(self, "source_template_file", icon='COPY_ID', text='Template file')
        col.prop(self, "source_template_image", icon='COPY_ID', text='Template image')
        col.prop(self, "source_template_video", icon='COPY_ID', text='Template video')
        col.prop(self, "source_template_info", icon='COPY_ID', text='Template info')

        col = layout.column(align=True)
        col.prop(self, "target_template_file", icon='COPY_ID', text='Target :  Template file')
        col.prop(self, "target_template_image", icon='COPY_ID', text='Template image')
        col.prop(self, "target_template_video", icon='COPY_ID', text='Template video')
        col.prop(self, "target_template_info", icon='COPY_ID', text='Template info')

    def get_asset_bundle_path(self, asset_data):
        """Template file are relative"""

        src_directory = Path(self.source_directory).resolve()
        src_template_file = Template(self.source_template_file)

        asset_path = Path(asset_data['filepath']).as_posix()
        asset_path = self.format_path(asset_path)

        rel_path = asset_path.relative_to(src_directory).as_posix()
        field_data = src_template_file.parse(rel_path)
        #field_data = {f"catalog_{k}": v for k, v in field_data.items()}

        # Change the int in the template by string to allow format
        #target_template_file = re.sub(r'{(\d+)}', r'{cat\1}', self.target_template_file)

        format_data = self.format_asset_data(asset_data)
        #format_data['asset_name'] = format_data['asset_name'].lower().replace(' ', '_')

        path = Template(self.target_template_file).format(format_data, **field_data).with_suffix('.blend')
        path = Path(self.bundle_directory, path).resolve()

        return path

    def set_asset_preview(self, asset, asset_data):
        '''Load an externalize image as preview for an asset using the target template'''

        image_template = self.target_template_image
        if not image_template:
            return

        asset_path = self.get_asset_bundle_path(asset_data)            
        image_path = self.find_path(image_template, asset_data, filepath=asset_path)

        if image_path:
            with bpy.context.temp_override(id=asset):
                bpy.ops.ed.lib_id_load_custom_preview(
                    filepath=str(image_path)
                )
        else:
            print(f'No image found for {image_template} on {asset.name}')
        
        if asset.preview:
            return asset.preview

    def generate_previews(self, cache_diff):
        
        print('Generate previews...')

        # if cache in (None, ''):
        #     cache = self.fetch()
        # elif isinstance(cache, (Path, str)):
        #     cache = self.read_cache(cache)

        if isinstance(cache, (Path, str)):
            cache_diff = LibraryCacheDiff(cache_diff)



        #TODO Support all multiple data_type
        for asset_info in cache:

            if asset_info.get('type', self.data_type) == 'FILE':
                self.generate_blend_preview(asset_info)
            else:
                self.generate_asset_preview(asset_info)

    def generate_asset_preview(self, asset_info):
        """Only generate preview when conforming a library"""

        #print('\ngenerate_preview', asset_info['filepath'])
        
        scn = bpy.context.scene
        vl = bpy.context.view_layer
        #Creating the preview for collection, object or material
        #camera = scn.camera

        data_type = self.data_type #asset_info['data_type']
        asset_path = self.format_path(asset_info['filepath'])

        # Check if a source video exists and if so copying it in the new directory
        if self.source_template_video and self.target_template_video:
            for asset_data in asset_info['assets']:
                asset_data = dict(asset_data, filepath=asset_path)

                dst_asset_path = self.get_asset_bundle_path(asset_data)
                dst_video_path = self.format_path(self.target_template_video, asset_data, filepath=dst_asset_path)
                if dst_video_path.exists():
                    print(f'The dest video {dst_video_path} already exist')
                    continue
                
                src_video_path = self.find_path(self.source_template_video, asset_data)
                if src_video_path:
                    print(f'Copy video from {src_video_path} to {dst_video_path}')
                    self.copy_file(src_video_path, dst_video_path)
                    
        # Check if asset as a preview image or need it to be generated
        asset_data_names = {}

        if self.target_template_image:
            for asset_data in asset_info['assets']:
                asset_data = dict(asset_data, filepath=asset_path)
                name = asset_data['name']
                dst_asset_path = self.get_asset_bundle_path(asset_data)

                dst_image_path = self.format_path(self.target_template_image, asset_data, filepath=dst_asset_path)
                if dst_image_path.exists():
                    print(f'The dest image {dst_image_path} already exist')
                    continue
                
                # Check if a source image exists and if so copying it in the new directory
                if self.source_template_image:
                    src_image_path = self.find_path(self.source_template_image, asset_data)

                    if src_image_path:
                        if src_image_path.suffix == dst_image_path.suffix:
                            self.copy_file(src_image_path, dst_image_path)
                        else:

                            print(src_image_path)
                            self.save_image(src_image_path, dst_image_path, remove=True)

                        continue

                #Store in a dict all asset_data that does not have preview
                asset_data_names[name] = dict(asset_data, image_path=dst_image_path)
        

        if not asset_data_names:# No preview to generate
            return
        
        print('Making Preview for', list(asset_data_names.keys()))

        asset_names = list(asset_data_names.keys())
        assets = self.load_datablocks(asset_path, names=asset_names, link=True, type=data_type)

        for asset in assets:
            if not asset:
                continue

            asset_data = asset_data_names[asset.name]
            image_path = asset_data['image_path']

            if asset.preview:
                print(f'Writing asset preview to {image_path}')
                self.write_preview(asset.preview, image_path)
                continue

            if data_type == 'COLLECTION':

                bpy.ops.object.collection_instance_add(name=asset.name)
                
                bpy.ops.view3d.camera_to_view_selected()
                instance = vl.objects.active

                #scn.collection.children.link(asset)
                
                scn.render.filepath = str(image_path)

                print(f'Render asset {asset.name} to {image_path}')
                bpy.ops.render.render(write_still=True)

                #instance.user_clear()
                asset.user_clear()

                bpy.data.objects.remove(instance)

                bpy.ops.outliner.orphans_purge(do_local_ids=True, do_linked_ids=True, do_recursive=True)