"""
This file generates a whole list of resources for the TerraFirmaCraft mod.
Any resource files generated by this script should set a root JSON tag:
    "__comment": "Generated by generateResources.py function: model"

This is a modified version from the original TFC repository to use in TFCompat.
"""

import json
import os
import time
import zipfile


def zipfolder(zip_name, target_dir):
    zipobj = zipfile.ZipFile(zip_name, 'w', zipfile.ZIP_DEFLATED)
    rootlen = len(target_dir) + 1
    for base, dirs, files in os.walk(target_dir):
        for file in files:
            fn = os.path.join(base, file)
            zipobj.write(fn, fn[rootlen:])


if not os.path.isdir('assets_backups'):
    os.mkdir('assets_backups')
    with open('assets_backups/.gitignore', 'w') as f:
        print(
            '# This folder does not belong on git. Not even as an empty folder, so we ignore everything, incl. this file.',
            file=f)
        print('*', file=f)

zipfolder('assets_backups/{}.zip'.format(int(time.time())), 'src/main/resources/assets/tfc')

os.chdir('src/main/resources/assets/tfc/')

# True - Generate Tools
# False - Generate only non tools (ingot, double ingot, sheet, etc..)

METAL_TYPES = {
	'soulforged_steel':False,
	'signalum':True,
	'lumium':True,
	'enderium':True,
	'refined_obsidian':False,
	'refined_glowstone':False,
	'thaumium':True,
	'void_metal':False,
}

OTHER_METAl_TYPE = {
    'chromium':True,
	'kanthal':False,
	'solder':False,
	'aluminium_steel':True,
	'weak_aluminium_steel':False,
    'bismuth_steel':True,
	'weak_bismuth_steel':False,
    'damascus_steel':True,
	'weak_damascus_steel':False,
    'stainless_steel':False,
	'weak_stainless_steel':False,
	'rose_alloy':False,
	'ferrochrome':False,
	'cadmium':False,
    'nichrome':True,
    'alnico':False,
    'vanadium':False,
    'rhodium':False,
    'palladium':False,
    'antimony': False,
    'constantan': False,
    'electrum': False,
    'red_alloy': False,
    'mithril': True,
    'nickel_silver': True,
    'invar': True,
    'aluminium': True,
    'aluminium_brass': False,
    'ardite': False,
    'cobalt': True,
    'manyullyn': True,
    'osmium': True,
    'titanium': True,
    'tungsten': True,
    'tungsten_steel': True,
    'boron': True,
    'thorium': False,
    'manganese': False,
    'magnesium': False,
    'lithium': False,
    'zirconium': False,
    'zircaloy': True,
    'beryllium': False,
    'beryllium_copper': True,
    'hsla_steel': False,
    'ferroboron': False,
    'tough': False,
    'magnesium_diboride': False,
    'uranium': False,
    'soulforged_steel':False,
	'signalum':True,
	'lumium':True,
	'enderium':True,
	'refined_obsidian':False,
	'refined_glowstone':False,
	'thaumium':True,
	'void_metal':False,
    'bismuth': False,
    'bismuth_bronze': True,
    'black_bronze': True,
    'brass': False,
    'bronze': True,
    'copper': True,
    'gold': False,
    'lead': False,
    'nickel': False,
    'rose_gold': False,
    'silver': False,
    'tin': False,
    'zinc': False,
    'sterling_silver': False,
    'wrought_iron': True,
    'pig_iron': False,
    'steel': True,
    'platinum': False,
    'black_steel': True,
    'blue_steel': True,
    'red_steel': True
}

METAL_ITEMS = {
    # 'unshaped': False, Special
    'ingot': False,
    'double_ingot': False,
    'scrap': False,
    'dust': False,
    'nugget': False,
    'sheet': False,
    'double_sheet': False,
    'anvil': True,
    'trapdoor': False,
    'tuyere': True,
    'lamp': False,
    'pick': True,
    'pick_head': True,
    'shovel': True,
    'shovel_head': True,
    'axe': True,
    'axe_head': True,
    'hoe': True,
    'hoe_head': True,
    'chisel': True,
    'chisel_head': True,
    'sword': True,
    'sword_blade': True,
    'mace': True,
    'mace_head': True,
    'saw': True,
    'saw_blade': True,
    'javelin': True,
    'javelin_head': True,
    'hammer': True,
    'hammer_head': True,
    'propick': True,
    'propick_head': True,
    'knife': True,
    'knife_blade': True,
    'scythe': True,
    'scythe_blade': True,
    'shears': True,
    'unfinished_chestplate': True,
    'chestplate': True,
    'unfinished_greaves': True,
    'greaves': True,
    'unfinished_boots': True,
    'boots': True,
    'unfinished_helmet': True,
    'helmet': True,
}

RECIPE_ITEMS = {
    'pick_head': 'pick',
    'shovel_head': 'shovel',
    'axe_head': 'axe',
    'hoe_head': 'hoe',
    'chisel_head': 'chisel',
    'sword_blade': 'sword',
    'mace_head': 'mace',
    'saw_blade': 'saw',
    'javelin_head': 'javelin',
    'hammer_head': 'hammer',
    'propick_head': 'propick',
    'knife_blade': 'knife',
    'scythe_blade': 'scythe',
}

TOOLS = [
    'pick', 'propick', 'shovel', 'axe', 'hoe', 'chisel', 'sword', 'mace', 'saw', 'shears', 'javelin', 'hammer', 'knife',
    'scythe'
]


def del_none(d):
    """
    https://stackoverflow.com/a/4256027/4355781
    Modifies input!
    """
    for key, value in list(d.items()):
        if value is None:
            del d[key]
        elif isinstance(value, dict):
            del_none(value)
    return d


def blockstate(filename_parts, model, textures, variants=None):
    """
    Magic.
    :param filename_parts: Iterable of strings.
    :param model: String or None
    :param textures: Dict of <string>:<string> OR <iterable of strings>:<string>
    :param variants: Dict of <string>:<variant> OR "normal":None (to disable the normal default)
    """
    _variants = {
        'normal': [{}]
    }
    if variants:
        _variants.update(variants)

    # Unpack any tuple keys to simple string->string pairs
    _textures = {}
    for key, val in textures.items():
        if isinstance(key, str):
            _textures[key] = val
        else:
            for x in key:
                _textures[x] = val

    p = os.path.join('blockstates', *filename_parts) + '.json'
    os.makedirs(os.path.dirname(p), exist_ok=True)
    with open(p, 'w') as file:
        json.dump(del_none({
            '__comment': 'Generated by generateResources.py function: blockstate',
            'forge_marker': 1,
            'defaults': {
                'model': model,
                'textures': _textures,
            },
            'variants': _variants,
        }), file, indent=2)


def cube_all(filename_parts, texture, variants=None, model='cube_all'):
    blockstate(filename_parts, model, textures={'all': texture}, variants=variants)


def model(filename_parts, parent, textures):
    p = os.path.join('models', *filename_parts) + '.json'
    os.makedirs(os.path.dirname(p), exist_ok=True)
    with open(p, 'w') as file:
        json.dump(del_none({
            '__comment': 'Generated by generateResources.py function: model',
            'parent': parent,
            'textures': textures,
        }), file, indent=2)


def item(filename_parts, *layers, parent='item/generated'):
    model(('item', *filename_parts), parent,
          None if len(layers) == 0 else {'layer%d' % i: v for i, v in enumerate(layers)})

def itemHandHeld(filename_parts, *layers, parent='item/handheld'):
    model(('item', *filename_parts), parent,
          None if len(layers) == 0 else {'layer%d' % i: v for i, v in enumerate(layers)})
          
def tool_recipe(filename_parts, pattern, key, result):
    p = os.path.join('recipes', *filename_parts) + '.json'
    os.makedirs(os.path.dirname(p), exist_ok=True)
    with open(p, 'w') as file:
        json.dump(del_none({
            '__comment': 'Generated by generateResources.py function: tool_recipe',
            'type': 'tfc:shaped_skill',
            'pattern': pattern,
            'key': key,
            'result': result,
        }), file, indent=2)

def backpackStorageModel(filename_parts, metal) :
    model(filename_parts, parent="item/generated", textures={
        "layer0": "tfcompat:items/metal/backpack_base/%s" % metal,
        "layer1": "tfcompat:items/metal/backpack_border/%s" % metal,
        "layer2": "tfcompat:items/metal/backpack_latch_light/%s" % metal
    })
def backpackUpgradeModel(filename_parts, metal) :
    model(filename_parts, parent="item/generated", textures={
        "layer0": "tfcompat:items/metal/backpack_base/%s" % metal,
        "layer1": "tfcompat:items/metal/backpack_border/%s" % metal,
        "layer2": "tfcompat:items/metal/backpack_latch_dark/%s" % metal
    })


#   ____  _            _        _        _
#  |  _ \| |          | |      | |      | |
#  | |_) | | ___   ___| | _____| |_ __ _| |_ ___  ___
#  |  _ <| |/ _ \ / __| |/ / __| __/ _` | __/ _ \/ __|
#  | |_) | | (_) | (__|   <\__ \ || (_| | ||  __/\__ \
#  |____/|_|\___/ \___|_|\_\___/\__\__,_|\__\___||___/
#
# BLOCKSTATES

# METAL FLUIDS
for name in METAL_TYPES.keys():
    blockstate(('fluid', name), 'forge:fluid', {}, {
        'normal': {
            'transform': "forge:default-item",
            'custom': {
                'fluid': name
            }
        }
    })

# ANVILS
for key in METAL_TYPES:
    if METAL_TYPES[key]:
        blockstate(('anvil', key), 'tfc:anvil', textures={
            ('all', 'particle'): 'tfc:blocks/metal/%s' % key
        }, variants={
            'axis': {
                'north': {'y': 180},
                'east': {'y': 270},
                'south': {},
                'west': {'y': 90}
            }
        })

# LAMP
for key in METAL_TYPES:
    blockstate(('lamp', key), 'tfc:lamp/up', textures={
        ('sheet', 'particle') : 'tfc:blocks/metal/%s' % key,
        'lamp' : "tfc:blocks/lamp_unlit"
    }, variants={
        'lit': {
            'true': {
                "textures": {
                    'lamp': 'tfc:blocks/lamp_lit'
                }
            },
            'false': {}
        },
        'facing': {'up': {}, 'down': {'model': "tfc:lamp/down"}}
    })

# METAL SHEETS
for key in METAL_TYPES:
    blockstate(('sheet', key), 'tfc:empty', textures={
        ('all', 'particle'): 'tfc:blocks/metal/%s' % key
    }, variants={
        'normal': None,
        "north": {"true": {"submodel": {"north": {"model": "tfc:sheet", "x": 90}}}, "false": {}},
        "south": {"true": {"submodel": {"south": {"model": "tfc:sheet", "y": 180, "x": 90}}}, "false": {}},
        "east": {"true": {"submodel": {"east": {"model": "tfc:sheet", "y": 90, "x": 90}}}, "false": {}},
        "west": {"true": {"submodel": {"west": {"model": "tfc:sheet", "y": 270, "x": 90}}}, "false": {}},
        "up": {"true": {"submodel": {"up": {"model": "tfc:sheet"}}}, "false": {}},
        "down": {"true": {"submodel": {"down": {"model": "tfc:sheet", "x": 180}}}, "false": {}}
    })


# METALS
for item_type, tool_item in METAL_ITEMS.items():
    for metal, tool_metal in METAL_TYPES.items():
        if tool_item and not tool_metal:
            continue
        if item_type == 'anvil':
            model(('item', 'metal', 'anvil', metal), 'tfc:item/metal/anvil/transformations',
                  {'all': 'tfc:blocks/metal/%s' % metal})
        elif item_type == 'trapdoor':
            model(('item', 'metal', 'trapdoor', metal), 'block/trapdoor_bottom',
                  {'texture': 'tfc:blocks/trapdoor/%s' % metal})
        else:
            parent = 'item/handheld' if item_type in TOOLS else 'item/generated'
            if item_type in ['knife', 'javelin']:
                parent = 'tfc:item/handheld_flipped'
            item(('metal', item_type, metal), 'tfc:items/metal/%s/%s' % (item_type, metal),
                 parent=parent)


for metal, tool_metal in OTHER_METAl_TYPE.items() :
    if tool_metal :
        itemHandHeld(('%s_mallet' % metal), "firmalife:items/metal/mallet/%s" % metal)
        item(('%s_mallet_head'  % metal), "firmalife:items/metal/mallet_head/%s" % metal)

        if metal == 'copper': 
            backpackStorageModel(('item', 'backpack', metal, 'none'), metal)
        else :
            backpackStorageModel(('item', 'backpack', metal, 'storage'), metal)
            backpackUpgradeModel(('item', 'backpack', metal, 'upgrade'), metal)
				 
# TOOLS RECIPES
for tool_head, tool in RECIPE_ITEMS.items():
    for metal, tool_metal in METAL_TYPES.items():
            if not tool_metal:
                continue
            tool_recipe(('metal', metal, '%s_%s' % (metal, tool)), ('X', 'S'), key={
                'X': { 'item': 'tfc:metal/%s/%s' % (tool_head, metal)},
                'S': { 'type': 'forge:ore_dict', 'ore': 'stickWood' }
            }, result={
                'item': 'tfc:metal/%s/%s' % (tool, metal)
            })
            

# CERAMICS
_heads = [x + '_head' for x in TOOLS] + [x + '_blade' for x in TOOLS]
for item_type in METAL_ITEMS:
    if item_type not in _heads:
        continue
    # unfired molds
    item(('ceramics', 'unfired', 'mold', item_type), 'tfc:items/ceramics/unfired/mold/%s' % item_type)
    # fired, empty molds
    item(('ceramics', 'fired', 'mold', item_type, 'empty'), 'tfc:items/ceramics/fired/mold/%s/empty' % item_type)
    # fired, filled molds
    for metal in ('copper', 'bronze', 'black_bronze', 'bismuth_bronze'):
        item(('ceramics', 'fired', 'mold', item_type, metal),
             'tfc:items/ceramics/fired/mold/%s/%s' % (item_type, metal))
del _heads

# unfired ingot molds
item(('ceramics', 'unfired', 'mold', 'ingot'), 'tfc:items/ceramics/unfired/mold/ingot')
# fired ingot molds for all metals
_ingotMetals = {}  # metal name -> texture
for metal in METAL_TYPES.keys():
    _ingotMetals[metal] = metal

for metal, texture in _ingotMetals.items():
    item(('ceramics', 'fired', 'mold', 'ingot', metal), 'tfc:items/ceramics/fired/mold/ingot/' + texture)
del _ingotMetals