
import argparse
import sys
import json
from pathlib import Path
import bpy
import re
import uuid
from itertools import groupby

from asset_library.constants import ASSETLIB_FILENAME, MODULE_DIR
from asset_library.common.bl_utils import thumbnail_blend_file
from asset_library.common.functions import command




@command
def bundle_library(source_directory, bundle_directory, template_info, thumbnail_template, 
        template=None, data_file=None):

    field_pattern = r'{(\w+)}'
    asset_data_path = Path(bundle_directory) / ASSETLIB_FILENAME

    glob_pattern = re.sub(field_pattern, '*', template)
    re_pattern = re.sub(field_pattern, r'([\\w -_.]+)', template)
    re_pattern = re_pattern.replace('?', '.')

    field_names = re.findall(field_pattern, template)

    asset_file_datas = []
    for f in sorted(Path(source_directory).glob(glob_pattern)):
        rel_path = f.relative_to(source_directory).as_posix()

        field_values = re.findall(re_pattern, rel_path)[0]
        field_data = {k:v for k,v in zip(field_names, field_values)}

        name = field_data.get('name', f.stem)
        thumbnail = (f / thumbnail_template.format(name=name)).resolve()
        asset_data = (f / template_info.format(name=name)).resolve()

        catalogs = sorted([v for k,v in sorted(field_data.items()) if re.findall('cat[0-9]+', k)])
        catalogs = [c.replace('_', ' ').title() for c in catalogs]

        if not thumbnail.exists():
            thumbnail_blend_file(f, thumbnail)

        asset_data = {
            'catalog' : '/'.join(catalogs),
            'preview' : thumbnail.as_posix(), #'./' + bpy.path.relpath(str(thumbnail), start=str(f))[2:],
            'filepath' : f.as_posix(), #'./' + bpy.path.relpath(str(f), start=str(asset_data_path))[2:],
            'name': name,
            'tags': [],
            'metadata': {'filepath': f.as_posix()}
        }

        asset_file_datas.append(asset_data)

    # Write json data file to store all asset found
    print(f'Writing asset data file to, {asset_data_path}')
    asset_data_path.write_text(json.dumps(asset_file_datas, indent=4))

    #script = MODULE_DIR / 'common' / 'bundle_blend.py'
    #cmd = [bpy.app.binary_path, '--python', str(script), '--', '--filepath', str(filepath)]
    #print(cmd)
    #subprocess.call(cmd)

@command
def bundle_blend(filepath, depth=0):
    #print('Bundle Blend...')
    filepath = Path(filepath)

    #asset_data_path = get_asset_datas_file(filepath)

    asset_data_path = filepath / ASSETLIB_FILENAME
    blend_name = filepath.name.replace(' ', '_').lower()
    blend_path = (filepath / blend_name).with_suffix('.blend')

    if not asset_data_path.exists():
        raise Exception(f'The file {asset_data_path} not exist')

    catalog_path = get_catalog_path(filepath)
    catalog_data = read_catalog(catalog_path)

    asset_file_data = json.loads(asset_data_path.read_text())
    #asset_file_data = {i['catalog']:i for i in asset_file_data}

    if depth == 0:
        groups = [asset_file_data]
    else:
        asset_file_data.sort(key=lambda x :x['catalog'].split('/')[:depth])
        groups = groupby(asset_file_data, key=lambda x :x['catalog'].split('/')[:depth])

    #progress = 0
    total_assets = len(asset_file_data)

    i = 0
    for sub_path, asset_datas in groups:
        bpy.ops.wm.read_homefile(use_empty=True)

        for asset_data in asset_datas:
            blend_name = sub_path[-1].replace(' ', '_').lower()
            blend_path = Path(filepath, *sub_path, blend_name).with_suffix('.blend')

            if i % int(total_assets / 100) == 0:
                print(f'Progress: {int(i / total_assets * 100)}')

            col = bpy.data.collections.new(name=asset_data['name'])

            # Seems slow
            #bpy.context.scene.collection.children.link(col)
            col.asset_mark()

            with bpy.context.temp_override(id=col):
                bpy.ops.ed.lib_id_load_custom_preview(
                    filepath=asset_data['preview']
                )

            col.asset_data.description = asset_data.get('description', '')

            catalog_name = asset_data['catalog']
            catalog = catalog_data.get(catalog_name)
            if not catalog:
                catalog = {'id': str(uuid.uuid4()), 'name': catalog_name}
                catalog_data[catalog_name] = catalog

            col.asset_data.catalog_id = catalog['id']

            for k, v in asset_data.get('metadata', {}).items():
                col.asset_data[k] = v
            
            i += 1

        print(f'Saving Blend to {blend_path}')

        blend_path.mkdir(exist_ok=True, parents=True)
        bpy.ops.wm.save_as_mainfile(filepath=str(blend_path), compress=True)
        
    write_catalog(catalog_path, catalog_data)

    bpy.ops.wm.quit_blender()


if __name__ == '__main__' :
    parser = argparse.ArgumentParser(description='bundle_blend',
    formatter_class=argparse.ArgumentDefaultsHelpFormatter)

    parser.add_argument('--source-path')
    parser.add_argument('--bundle-path')
    parser.add_argument('--asset-data-template')
    parser.add_argument('--thumbnail-template')
    parser.add_argument('--template', default=None)
    parser.add_argument('--data-file', default=None)
    parser.add_argument('--depth', default=0, type=int)

    if '--' in sys.argv :
        index = sys.argv.index('--')
        sys.argv = [sys.argv[index-1], *sys.argv[index+1:]]

    args = parser.parse_args()

    bundle_library(
        source_directory=args.source_directory,
        bundle_directory=args.bundle_directory,
        template_info=args.template_info,
        thumbnail_template=args.thumbnail_template,
        template=args.template,
        data_file=args.data_file)

    bundle_blend(filepath=args.bundle_directory, depth=args.depth)