# World.gd
# ─────────────────────────────────────────────────────────────────────────────
# Spielwelt-Controller
#
# Verantwortlichkeiten:
#   • Prozeduraler Boden-Shader (Schachbrettmuster, world-space stabil)
#   • Prozeduraler Himmel (ProceduralSkyMaterial + WorldEnvironment)
#   • Hauptmenü → Klassenauswahl → Spielinitialisierung
#   • Startausrüstung je nach Klasse
#   • Gegner-Setup, Loot-Weiterleitung, Respawn nach Tod
# ─────────────────────────────────────────────────────────────────────────────
extends Node3D

const ENEMY_SCENE = preload("res://enemy.tscn")
const MAIN_MENU = preload("res://main_menu.tscn")
const CLASS_SELECTION_MENU = preload("res://class_selection_menu.tscn")
const RESPAWN_TIME = 5.0

# Startausrüstung
const STARTER_SWORD = preload("res://equipment/iron_sword.tres")
const STARTER_STAFF = preload("res://equipment/wooden_staff.tres")
const STARTER_CHEST = preload("res://equipment/leather_chest.tres")

# Loot Tables
const GOBLIN_LOOT = preload("res://loot_tables/goblin_loot.tres")

@onready var player = $Player
@onready var floor_mesh = $Boden/MeshInstance3D

func _ready():
	_setup_floor_material()
	_setup_sky()
	# Hauptmenü anzeigen
	var main_menu = MAIN_MENU.instantiate()
	add_child(main_menu)
	main_menu.start_game.connect(_on_start_game)

func _setup_sky():
	var sky_mat = ProceduralSkyMaterial.new()
	sky_mat.sky_top_color        = Color(0.15, 0.35, 0.75)
	sky_mat.sky_horizon_color    = Color(0.55, 0.75, 1.0)
	sky_mat.ground_horizon_color = Color(0.35, 0.30, 0.25)
	sky_mat.ground_bottom_color  = Color(0.1,  0.1,  0.1)
	sky_mat.sun_angle_max        = 30.0
	sky_mat.sun_curve            = 0.15

	var sky = Sky.new()
	sky.sky_material = sky_mat

	var env = Environment.new()
	env.background_mode        = Environment.BG_SKY
	env.sky                    = sky
	env.ambient_light_source   = Environment.AMBIENT_SOURCE_SKY
	env.ambient_light_energy   = 0.6
	env.tonemap_mode           = Environment.TONE_MAPPER_FILMIC

	var world_env = WorldEnvironment.new()
	world_env.environment = env
	add_child(world_env)

func _setup_floor_material():
	var shader = Shader.new()
	shader.code = """
shader_type spatial;
uniform float grid_size : hint_range(0.5, 10.0) = 2.0;
uniform vec4 color_a : source_color = vec4(0.22, 0.22, 0.22, 1.0);
uniform vec4 color_b : source_color = vec4(0.38, 0.38, 0.38, 1.0);

void fragment() {
	vec3 world_pos = (INV_VIEW_MATRIX * vec4(VERTEX, 1.0)).xyz;
	vec2 cell = floor(world_pos.xz / grid_size);
	float checker = mod(cell.x + cell.y, 2.0);
	ALBEDO = mix(color_a.rgb, color_b.rgb, checker);
	ROUGHNESS = 0.85;
	METALLIC = 0.0;
}
"""
	var mat = ShaderMaterial.new()
	mat.shader = shader
	floor_mesh.material_override = mat

# Nach Hauptmenü: Klassenauswahl anzeigen
func _on_start_game():
	var menu = CLASS_SELECTION_MENU.instantiate()
	add_child(menu)
	menu.class_selected.connect(_on_class_selected)
	# Spiel wieder pausieren für Klassenauswahl
	get_tree().paused = true

# Klasse ausgewählt: Spieler initialisieren
func _on_class_selected(character_class: CharacterClass):
	player.character_class = character_class

	# Skills klassenabhängig aufbauen
	player._init_class_skills()
	for i in range(9):
		player._refresh_action_slot(i)

	# Startausrüstung klassenabhängig
	if character_class.resource_type == CharacterClass.ResourceType.MANA:
		player.equip_item(STARTER_STAFF)
	else:
		player.equip_item(STARTER_SWORD)
	player.equip_item(STARTER_CHEST)

	player._calculate_stats()
	player.current_hp = player.max_hp
	player.current_resource = player.max_resource
	player.hud.update_health(player.current_hp, player.max_hp)
	player.hud.update_resource(player.current_resource, player.max_resource, player.get_resource_name())
	print("Klasse gewählt: ", character_class.class_name_de)

	# Jetzt Gegner initialisieren
	for child in get_children():
		if child.has_method("take_damage") and child != player:
			_setup_enemy(child)

# Gegner initialisieren und Signal verbinden
func _setup_enemy(enemy):
	if enemy and player:
		enemy.target = player
		if enemy.loot_table == null:
			enemy.loot_table = GOBLIN_LOOT
		if not enemy.enemy_died.is_connected(_on_enemy_died):
			enemy.enemy_died.connect(_on_enemy_died)
		if not enemy.enemy_dropped_loot.is_connected(_on_enemy_dropped_loot):
			enemy.enemy_dropped_loot.connect(_on_enemy_dropped_loot)
	else:
		print("Fehler: Player oder Enemy nicht gefunden!")

# Loot-Drop an Spieler weiterleiten
func _on_enemy_dropped_loot(loot: Dictionary, world_pos: Vector3):
	if player:
		player.receive_loot(loot, world_pos)

# Gegner gestorben: Nach 5 Sekunden respawnen
func _on_enemy_died(spawn_position: Vector3, xp_reward: int):
	if player:
		player.gain_xp(xp_reward)
	print("Respawn in ", RESPAWN_TIME, " Sekunden...")
	await get_tree().create_timer(RESPAWN_TIME).timeout
	_spawn_enemy(spawn_position)

# Neuen Gegner an Position spawnen
func _spawn_enemy(position: Vector3):
	var new_enemy = ENEMY_SCENE.instantiate()
	add_child(new_enemy)
	new_enemy.global_position = position
	_setup_enemy(new_enemy)
	print("Gegner respawned!")
