extends VBoxContainer

@export var frames_config: JSON
@export var frame_dir_name := ""
@export var mapping_name := ""
@export var frames_per_sec := 6
# empty string means no first frame mapping
@export var first_frame_mapping := ""
# empty string means no mirror mapping
@export var mirror_mapping := ""

@onready var animated_sprite := %AnimatedSprite2D as AnimatedSprite2D
@onready var frames_speed_line_edit := %FramesSpeedEdit as LineEdit
@onready var dir_line_edit := %DirLineEdit as LineEdit
@onready var mapping_line_edit := %MappingLineEdit as LineEdit

@onready var first_frame_mapping_edit = %FirstFrameMapping as LineEdit
@onready var mirror_mapping_edit = %MirrorMapping as LineEdit


func _ready() -> void:
	dir_line_edit.text = frame_dir_name
	mapping_line_edit.text = mapping_name
	frames_speed_line_edit.text = str(frames_per_sec)
	first_frame_mapping_edit.text = first_frame_mapping
	mirror_mapping_edit.text = mirror_mapping
	reload_frames()
	mapping_line_edit.text_submitted.connect(_on_mapping_submitted)
	frames_speed_line_edit.text_submitted.connect(_on_frames_speed_submitted)
	first_frame_mapping_edit.text_submitted.connect(_on_first_frame_mapping_submitted)
	mirror_mapping_edit.text_submitted.connect(_on_mirror_mapping_submitted)


func reload_frames():
	var sprite_frames = animated_sprite.sprite_frames as SpriteFrames
	# {"path": "", "frames": {}, "ids": []}
	var frames_data = frames_config.data.dirs[frame_dir_name]
	# clear all animations with either dir or mapping name
	if frame_dir_name != mapping_name and sprite_frames.has_animation(frame_dir_name):
		sprite_frames.remove_animation(frame_dir_name)
	if sprite_frames.has_animation(mapping_name):
		sprite_frames.clear(mapping_name)
	else:
		sprite_frames.add_animation(mapping_name)
	# clear first frame mapping and mirror mapping
	if first_frame_mapping != "":
		if sprite_frames.has_animation(first_frame_mapping):
			sprite_frames.clear(first_frame_mapping)
		else:
			sprite_frames.add_animation(first_frame_mapping)
		# add the first frame
		var first_frame_path = frames_data.frames[frames_data.ids[0]]
		sprite_frames.add_frame(first_frame_mapping, load(first_frame_path))
	if mirror_mapping != "":
		if sprite_frames.has_animation(mirror_mapping):
			sprite_frames.clear(mirror_mapping)
		else:
			sprite_frames.add_animation(mirror_mapping)
	var frame_duration = 12.0 / frames_per_sec
	for id in frames_data.ids:
		var frame_path = frames_data.frames[id]
		var frame_texture = load(frame_path) as Texture2D
		sprite_frames.add_frame(mapping_name, frame_texture, frame_duration)
		# mirror the frame
		if mirror_mapping != "":
			var mirrored_frame = frame_texture.duplicate() as Texture2D
			var flipped_image = mirrored_frame.get_image()
			flipped_image.flip_x()
			mirrored_frame = ImageTexture.create_from_image(flipped_image)
			sprite_frames.add_frame(mirror_mapping, mirrored_frame, frame_duration)
	animated_sprite.play(mapping_name)
	# scale down if the frame is too big
	var frame_size = sprite_frames.get_frame_texture(mapping_name, 0).get_size()
	if frame_size.x > 128 or frame_size.y > 128:
		var ratio = min(128 / frame_size.x, 128 / frame_size.y)
		animated_sprite.scale = Vector2(ratio, ratio)
	# save the sprite_frames
	ResourceSaver.save(sprite_frames)
	_save_and_update_frames_config()


func _on_mapping_submitted(new_text: String):
	# clear the old mapping
	var sprite_frames = animated_sprite.sprite_frames as SpriteFrames
	sprite_frames.remove_animation(mapping_name)
	mapping_name = new_text
	frames_config.data.mapping[frame_dir_name] = mapping_name
	reload_frames()
	mapping_line_edit.release_focus()
	_save_and_update_frames_config()


func _on_frames_speed_submitted(new_text: String):
	frames_per_sec = int(new_text)
	if frames_per_sec < 1:
		frames_per_sec = 1
		frames_speed_line_edit.text = str(frames_per_sec)
	frames_config.data.frames_per_second[frame_dir_name] = frames_per_sec
	reload_frames()
	frames_speed_line_edit.release_focus()
	_save_and_update_frames_config()


func _on_first_frame_mapping_submitted(new_text: String):
	# clear the old first frame mapping
	if first_frame_mapping != "":
		var sprite_frames = animated_sprite.sprite_frames as SpriteFrames
		sprite_frames.remove_animation(first_frame_mapping)
	first_frame_mapping = new_text
	frames_config.data.first_frame_mapping[frame_dir_name] = first_frame_mapping
	reload_frames()
	first_frame_mapping_edit.release_focus()
	_save_and_update_frames_config()


func _on_mirror_mapping_submitted(new_text: String):
	# clear the old mirror mapping
	if mirror_mapping != "":
		var sprite_frames = animated_sprite.sprite_frames as SpriteFrames
		sprite_frames.remove_animation(mirror_mapping)
	mirror_mapping = new_text
	frames_config.data.mirror_mapping[frame_dir_name] = mirror_mapping
	reload_frames()
	mirror_mapping_edit.release_focus()
	_save_and_update_frames_config()


func _save_and_update_frames_config():
	ResourceSaver.save(frames_config)
	#EditorInterface.get_resource_filesystem().update_file(frames_config.resource_path)
