extends Area2D

# GLOBAL CFG

@onready var fade_rect: ColorRect = get_node("../Fader/ColorRect")

func fade_out(duration := 1.0):
	fade_rect.visible = true
	fade_rect.modulate.a = 0.0
	var tween = get_tree().create_tween()
	tween.tween_property(fade_rect, "modulate:a", 1.0, duration)

func fade_in(duration := 1.0):
	fade_rect.visible = true
	fade_rect.modulate.a = 1.0
	var tween = get_tree().create_tween()
	tween.tween_property(fade_rect, "modulate:a", 0.0, duration)
	tween.tween_callback(Callable(self, "_on_fade_in_complete"))

func wait(seconds: float) -> void:
	await get_tree().create_timer(seconds).timeout

func _on_fade_in_complete():
	fade_rect.visible = false



const scalef = 3;
const textsize = 16;

func load_json(path: String): # stolen from reddit then updated to godot 4 lmao
	var file := FileAccess.open(path, FileAccess.READ)
	var content = file.get_as_text()
	file.close()
	var parsed_json = JSON.parse_string(content)
	return parsed_json
	
func loadstring(path: String): # stolen from reddit then updated to godot 4 lmao
	var file := FileAccess.open(path, FileAccess.READ)
	var content = file.get_as_text()
	file.close()
	return content

var rng = RandomNumberGenerator.new()

# Called when the node enters the scene tree for the first time.
func _ready() -> void:
	await fade_in(1.0)
	get_node("../Player").set_meta("can_walk",true)
	for child in get_children(): child.queue_free()
	var root = get_node("../")
	var world = load_json("res://worlds/"+self.get_meta("world")+".json");
	if world.has("mapscript"):
		var script = loadstring("res://worlds/"+self.get_meta("world")+".lua")
		get_node("../LuaEnv").reset_env()
		get_node("../LuaEnv").run_script(script,self)
	var assetcfg = load_json("res://assetcfg.json")
	var texturespace = root.get_meta("resourcepack");
	var worldassemble = {};
	var plr = get_node("../Player")
	plr.position = Vector2(world["pspawn"]["w"]*(16*scalef),world["pspawn"]["h"]*(16*scalef))

	for y in range(world["height"]+1):
		for x in range(world["width"]+1):
			if not worldassemble.has(y):
				worldassemble[y] = {}
			worldassemble[y][x] = {"thing":world["fill"],"action":"none"}
	for modifier in world["features"]:
		var x = int(modifier["w"])
		var y = int(modifier["h"])
		worldassemble[y][x] = modifier["t"]
	# assuming this script extends Node2D or Area2D that builds the world
	for y in range(worldassemble.size()):
		for x in range(worldassemble[y].size()):
			var along = worldassemble[y][x]
			var walpole = along["thing"]
			var cfg = assetcfg[walpole]

			# combine base data from cfg and instance-specific data from along
			var tile_type = along.get("action", cfg.get("action", "default"))
			var is_collidable = along.get("collidable", cfg.get("collidable", false))
			var tex_path = "res://%s/text/%s" % [texturespace, cfg["textname"]]
			var tex = load(tex_path)

			# --- choose node type
			var tile_node: Node2D
			if tile_type == "tp":
				tile_node = Area2D.new()  # teleporter
			elif is_collidable:
				tile_node = StaticBody2D.new()  # solid
			else:
				tile_node = Area2D.new()  # non-collidable sensor/decor

			add_child(tile_node)
			tile_node.position = Vector2(x * (scalef * textsize), y * (scalef * textsize))
			tile_node.name = "tile_%s_%s" % [x, y]
			tile_node.set_meta("collidable", is_collidable)

			# --- sprite
			var sprite = Sprite2D.new()
			sprite.texture = tex
			sprite.scale = Vector2(scalef, scalef)
			tile_node.add_child(sprite)

			# optional random rotation
			if cfg.get("allowRandRot", false):
				sprite.rotation_degrees = 90 * rng.randi_range(0, 3)

			# --- collision shape for solids and sensors
			if is_collidable or tile_type == "tp":
				var col = CollisionShape2D.new()
				var shape = RectangleShape2D.new()
				shape.size = Vector2(16 * scalef, 16 * scalef)
				col.shape = shape
				col.position = Vector2.ZERO
				tile_node.add_child(col)

			# --- teleporter setup
			if tile_type == "tp":
				var target_world = along.get("target_world", cfg.get("target_world", "default"))
				tile_node.set_meta("world", target_world)
				tile_node.connect("body_entered", Callable(self, "_on_tp_entered").bind(tile_node))
	_add_world_borders(world["width"], world["height"])
# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta: float) -> void:
	pass
	
	
func _on_tp_entered(body: Node, source: Node) -> void:
	if not body.is_in_group("player"):
		return

	print("Teleport triggered by:", body.name)
	await fade_out(1.0)
	get_node("../Player").set_meta("can_walk",false)
	await wait(1.0)
	if body.has_method("set_velocity"):
		body.set_velocity(Vector2.ZERO)

	if source.has_meta("world"):
		var new_world = source.get_meta("world")
		print("Teleporting to world:", new_world)

		set_meta("world", new_world)
		call_deferred("_ready")  # safely rebuild
	else:
		print("⚠️ Teleporter node has no 'world' meta set!")

func _add_world_borders(width: int, height: int) -> void:
	var border_thickness = 32.0 * scalef
	var w_px = width * (textsize * scalef)
	var h_px = height * (textsize * scalef)

	var positions = {
		"top": Vector2(w_px / 2, -border_thickness / 2),
		"bottom": Vector2(w_px / 2, h_px + border_thickness / 2),
		"left": Vector2(-border_thickness / 2, h_px / 2),
		"right": Vector2(w_px + border_thickness / 2, h_px / 2)
	}

	for name in positions.keys():
		var wall = StaticBody2D.new()
		wall.name = "border_%s" % name
		var shape = RectangleShape2D.new()
		if name in ["top", "bottom"]:
			shape.size = Vector2(w_px + border_thickness, border_thickness)
		else:
			shape.size = Vector2(border_thickness, h_px + border_thickness)
		var col = CollisionShape2D.new()
		col.shape = shape
		wall.position = positions[name]
		wall.add_child(col)
		add_child(wall)

@onready var label: RichTextLabel = null
@onready var uitypebox: ColorRect = null
var typing_speed := 0.03  # seconds between characters
var typing = false        # to prevent overlapping animations

func ui_showmesg(t: String) -> void:
	label = get_node("../UI/bg/RichTextLabel")
	uitypebox = get_node("../UI/bg")
	if typing:
		return  # skip if already typing (optional safeguard)
	uitypebox.visible = true
	typing = true
	print(label, " valid? ", is_instance_valid(label))

	label.text = t
	label.visible_characters = 0
	await _type_text(t)
	await wait(4)
	label = get_node("../UI/bg/RichTextLabel")
	uitypebox = get_node("../UI/bg")
	label.visible_characters = 0
	uitypebox.visible = false
	typing = false


func _type_text(t: String) -> void:
	var i := 0
	while i < t.length():
		i += 1
		label.visible_characters = i
		await wait(typing_speed)
