# Generates the necessary files for discs defined in discs.json (except the texture)
import json
from tinytag import TinyTag


from discs_load import *

# Terminal command to install tinytag:
#python -m pip install tinytag


MINECRAFT_MODELS_PATH = RESOURCEPACK_PATH + '/assets/minecraft/models/item/'.replace('/', os.sep)
MODELS_PATH = RESOURCEPACK_PATH + '/assets/murderdrones/models/item/'.replace('/', os.sep)

if __name__ == '__main__':
	with open(DISCS_PATH+'discs.json', encoding='UTF-8') as file:
		discs = json.load(file)

	with open(SOUNDS_PATH + 'sounds.json', 'r', encoding='UTF-8') as file:
		sounds = json.load(file)
	for disc in discs:
		disc_id = disc['id']
		sounds['music_disc.'+disc_id] = {
				"sounds": [
						{
								"name": f"murderdrones:records/{disc_id}",
								"stream": True
						}
				]
		} if 'sounds' not in disc else {
				"sounds": list([{
						"name": f"murderdrones:records/{sound['name']}",
						"stream": True,
						"weight": sound['weight']
				} 
				if sound.get('weight', 1) != 1 else {
						"name": f"murderdrones:records/{sound['name']}",
						"stream": True
				} 
				for sound in disc['sounds']])
		}
	with open(SOUNDS_PATH + 'sounds.json', 'w', encoding='UTF-8') as file:
		json.dump(sounds, file, indent=4, ensure_ascii=False)
	with open(MINECRAFT_MODELS_PATH+'music_disc_11.json', 'w', encoding='UTF-8') as file:
		json.dump({
				"parent": "item/generated",
				"textures": {
						"layer0": "item/music_disc_11"
				},
				"overrides": list([
						{
								"predicate": {
										"custom_model_data": CUSTOM_MODEL_DATA_ID + i
								},
								"model": f"murderdrones:item/{PREFIX}{disc['id']}"
						}
						for i, disc in enumerate(discs)
				])
		}, file, indent=4, ensure_ascii=False)
	for disc in discs:
		with open(MODELS_PATH + PREFIX + disc['id'] + '.json', 'w', encoding='UTF-8') as file:
			json.dump({
					"parent": "item/generated",
					"textures": {
							"layer0": f"murderdrones:item/{PREFIX}{disc['id']}"
					}
			}, file, indent=4, ensure_ascii=False)

	with open(DISCS_PATH + 'play_duration.mcfunction', 'w', encoding='UTF-8') as file:
			file.writelines([f'execute if score @s imd_disc_id matches {CUSTOM_MODEL_DATA_ID + i} run function murderdrones:discs/{disc["id"]}/play_duration\n' for i, disc in enumerate(discs)])
	with open(DISCS_PATH + 'play.mcfunction', 'w', encoding='UTF-8') as file:
			file.writelines([f'execute if score @e[type=marker,tag=imd_jukebox_marker,distance=..0.1,limit=1] imd_disc_id matches {CUSTOM_MODEL_DATA_ID + i} run function murderdrones:discs/{disc["id"]}/play\n' for i, disc in enumerate(discs)])
	with open(DISCS_PATH + 'stop.mcfunction', 'w', encoding='UTF-8') as file:
			file.writelines([f'execute if score @s imd_disc_id matches {CUSTOM_MODEL_DATA_ID + i} run function murderdrones:discs/{disc["id"]}/stop\n' for i, disc in enumerate(discs)])

	with open(DATA_PATH + 'loot_tables/all_discs.json', 'w', encoding='UTF-8') as file:
		json.dump({
			'pools': list([{
				"rolls": 1,
				"entries": [
					{
						"type": "loot_table",
						"name": f"murderdrones:items/{PREFIX}{disc['id']}"
					}
				]
			} for disc in discs])
		}, file, indent='\t', ensure_ascii=False)

	for i, disc in enumerate(discs):
		disc_id: str = disc['id']
		name: str | dict = disc['name']
		description: str | list[dict] = disc['description']
		nbt: str = disc.get('nbt', '{HideFlags:32}')[1:-1]
		nbt = f'{{CustomModelData:{CUSTOM_MODEL_DATA_ID + i}, {nbt}}}'

		if type(name) is dict and 'italic' not in name:
			name['italic'] = False

		duration: int = 0
		if 'sounds' in disc:
			sound_files = [s['name'] for s in disc['sounds']]
		else:
			sound_files = [disc_id]
		for sound_file in sound_files:
			audio_tag: TinyTag = TinyTag.get(RECORDS_PATH + sound_file + '.ogg')
			new_duration = int((audio_tag.duration*20) + 1)
			if new_duration > duration:
				duration = new_duration

		with open(LOOT_PATH + PREFIX + disc_id + '.json', 'w', encoding='UTF-8') as file:
			json.dump({
				"pools": [
					{
						"rolls": 1,
						"entries": [
							{
								"type": "item",
								"weight": 1,
								"name": "music_disc_11",
								"functions": [
									{
										"function": "set_nbt",
										"tag": nbt
									},
									{
										"function": "set_name",
										"name": {"text": name, "italic": False} if type(name) is str else name
									},
									{
										"function": "set_lore",
										"lore": [{"text": description, "color": "gray", "italic": False}] if type(description) is str else description
									}
								]
							}
						]
					}
				]
			}, file, indent='\t', ensure_ascii=False)

		disc_path = DISCS_PATH+disc_id+'/'
		if not os.path.exists(disc_path):
			os.mkdir(disc_path)
		
		with open(disc_path + 'play_duration.mcfunction', 'w', encoding='UTF-8') as file:
			file.write(f'scoreboard players set @s imd_play_time {duration}\n')
		with open(disc_path + 'play.mcfunction', 'w', encoding='UTF-8') as file:
			file.write(f'''title @s actionbar {{"translate": "record.nowPlaying", "with": [{{"text": "{description}"}}], "color":"green"}}
playsound murderdrones:music_disc.{disc_id} record @s ~ ~ ~ {VOLUME_OVERRIDES.get(disc_id, 4)} 1
''')
		with open(disc_path + 'stop.mcfunction', 'w', encoding='UTF-8') as file:
			file.write(f'''execute store result score @s imd_player_id run data get entity @s data.Listeners[0]
data remove entity @s data.Listeners[0]
execute as @a if score @s imd_player_id = @e[type=marker,tag=imd_jukebox_marker,distance=..0.1,limit=1] imd_player_id run stopsound @s record murderdrones:music_disc.{disc_id}
execute if data entity @s data.Listeners[0] run function murderdrones:discs/{disc_id}/stop
''')
