class_name TableSetup
extends Node3D

## TableSetup - Sets up the 3D game table with all zones

signal card_clicked(card_instance: CardInstance, zone_type: Enums.ZoneType, player_index: int)

# Zone visuals for each player
var player_zones: Array[Dictionary] = [{}, {}]

# Deck indicators (simple card-back representation)
var deck_indicators: Array[MeshInstance3D] = [null, null]
var deck_count_labels: Array[Label3D] = [null, null]

# Table dimensions
const TABLE_WIDTH: float = 16.0
const TABLE_DEPTH: float = 12.0

# Zone positions (relative to table center)
const ZONE_POSITIONS = {
	"deck": Vector3(5.5, 0.1, 3.5),
	"damage": Vector3(3.5, 0.1, 3.5),
	"backups": Vector3(0.0, 0.1, 3.5),
	"break": Vector3(-3.5, 0.1, 3.5),
	"forwards": Vector3(0.0, 0.1, 1.5),
	"hand": Vector3(0.0, 0.5, 5.5)
}

# Components
var table_mesh: MeshInstance3D
var camera: TableCamera

func _ready() -> void:
	_create_table()
	_create_camera()
	_create_lighting()
	_create_zones()
	_create_deck_indicators()

func _create_table() -> void:
	table_mesh = MeshInstance3D.new()
	add_child(table_mesh)

	var plane = PlaneMesh.new()
	plane.size = Vector2(TABLE_WIDTH, TABLE_DEPTH)
	table_mesh.mesh = plane

	# Create table material
	var mat = StandardMaterial3D.new()
	mat.albedo_color = Color(0.15, 0.2, 0.15)  # Dark green felt

	# Try to load playmat texture
	if ResourceLoader.exists("res://assets/table/playmat.webp"):
		var texture = load("res://assets/table/playmat.webp")
		if texture:
			mat.albedo_texture = texture

	table_mesh.material_override = mat
	# PlaneMesh in Godot 4 is already horizontal (facing up), no rotation needed

func _create_camera() -> void:
	camera = TableCamera.new()
	add_child(camera)
	camera.current = true

func _create_lighting() -> void:
	# Main directional light
	var dir_light = DirectionalLight3D.new()
	add_child(dir_light)
	dir_light.position = Vector3(5, 10, 5)
	dir_light.rotation = Vector3(deg_to_rad(-45), deg_to_rad(45), 0)
	dir_light.light_energy = 0.8
	dir_light.shadow_enabled = true

	# Ambient light
	var env = WorldEnvironment.new()
	add_child(env)
	var environment = Environment.new()
	environment.ambient_light_source = Environment.AMBIENT_SOURCE_COLOR
	environment.ambient_light_color = Color(0.3, 0.3, 0.35)
	environment.ambient_light_energy = 0.5
	environment.background_mode = Environment.BG_COLOR
	environment.background_color = Color(0.1, 0.1, 0.15)
	env.environment = environment

func _create_zones() -> void:
	# Create zones for both players
	for player_idx in range(2):
		var flip = 1 if player_idx == 0 else -1
		var rot = 0 if player_idx == 0 else 180

		# Field - Forwards
		var forwards_zone = _create_zone(
			Enums.ZoneType.FIELD_FORWARDS, player_idx,
			ZONE_POSITIONS["forwards"] * Vector3(1, 1, flip), rot
		)
		player_zones[player_idx]["forwards"] = forwards_zone

		# Field - Backups
		var backups_zone = _create_zone(
			Enums.ZoneType.FIELD_BACKUPS, player_idx,
			ZONE_POSITIONS["backups"] * Vector3(1, 1, flip), rot
		)
		player_zones[player_idx]["backups"] = backups_zone

		# Damage Zone
		var damage_zone = _create_zone(
			Enums.ZoneType.DAMAGE, player_idx,
			ZONE_POSITIONS["damage"] * Vector3(flip, 1, flip), rot
		)
		player_zones[player_idx]["damage"] = damage_zone

		# Break Zone
		var break_zone = _create_zone(
			Enums.ZoneType.BREAK, player_idx,
			ZONE_POSITIONS["break"] * Vector3(flip, 1, flip), rot
		)
		player_zones[player_idx]["break"] = break_zone

func _create_deck_indicators() -> void:
	# Create simple card-back boxes for deck representation
	for player_idx in range(2):
		var flip = 1 if player_idx == 0 else -1
		var pos = ZONE_POSITIONS["deck"] * Vector3(flip, 1, flip)

		# Card back mesh (simple colored box)
		var deck_mesh = MeshInstance3D.new()
		add_child(deck_mesh)

		var box = BoxMesh.new()
		box.size = Vector3(0.63, 0.3, 0.88)  # Card size with thickness for deck
		deck_mesh.mesh = box

		var mat = StandardMaterial3D.new()
		mat.albedo_color = Color(0.15, 0.1, 0.3)  # Dark blue for card back
		deck_mesh.material_override = mat

		deck_mesh.position = pos + Vector3(0, 0.15, 0)  # Raise above table

		deck_indicators[player_idx] = deck_mesh

		# Card count label
		var label = Label3D.new()
		add_child(label)
		label.text = "50"
		label.font_size = 64
		label.position = pos + Vector3(0, 0.35, 0)
		label.rotation.x = deg_to_rad(-90)  # Face up
		if player_idx == 1:
			label.rotation.z = deg_to_rad(180)  # Flip for opponent
		deck_count_labels[player_idx] = label

func _create_zone(zone_type: Enums.ZoneType, player_idx: int, pos: Vector3, rot: float) -> ZoneVisual:
	var zone = ZoneVisual.new()
	add_child(zone)

	zone.zone_type = zone_type
	zone.player_index = player_idx
	zone.zone_position = pos
	zone.zone_rotation = rot

	# Configure based on zone type
	match zone_type:
		Enums.ZoneType.FIELD_FORWARDS, Enums.ZoneType.FIELD_BACKUPS:
			zone.card_spacing = 0.8
		Enums.ZoneType.DAMAGE, Enums.ZoneType.BREAK:
			zone.stack_offset = 0.02

	zone.card_clicked.connect(_on_zone_card_clicked.bind(zone_type, player_idx))

	return zone

## Get a zone visual
func get_zone(player_idx: int, zone_name: String) -> ZoneVisual:
	if player_idx >= 0 and player_idx < player_zones.size():
		return player_zones[player_idx].get(zone_name)
	return null

## Sync visual state with game state
func sync_with_game_state(game_state: GameState) -> void:
	for player_idx in range(2):
		var player = game_state.get_player(player_idx)
		if not player:
			continue

		# Sync forwards
		_sync_zone(player_zones[player_idx]["forwards"], player.field_forwards)

		# Sync backups
		_sync_zone(player_zones[player_idx]["backups"], player.field_backups)

		# Update deck count (don't sync individual cards)
		_update_deck_indicator(player_idx, player.deck.get_count())

		# Sync damage
		_sync_zone(player_zones[player_idx]["damage"], player.damage_zone)

		# Sync break zone
		_sync_zone(player_zones[player_idx]["break"], player.break_zone)

## Update deck indicator
func _update_deck_indicator(player_idx: int, count: int) -> void:
	if deck_count_labels[player_idx]:
		deck_count_labels[player_idx].text = str(count)

	# Scale deck thickness based on count
	if deck_indicators[player_idx]:
		var thickness = max(0.05, count * 0.006)  # Min thickness, scale with cards
		var mesh = deck_indicators[player_idx].mesh as BoxMesh
		if mesh:
			mesh.size.y = thickness
		deck_indicators[player_idx].position.y = 0.1 + thickness / 2

func _sync_zone(visual_zone: ZoneVisual, game_zone: Zone) -> void:
	if not visual_zone or not game_zone:
		return

	# Get current visual cards
	var visual_instances = {}
	for cv in visual_zone.card_visuals:
		if cv.card_instance:
			visual_instances[cv.card_instance.instance_id] = cv

	# Get game zone cards
	var game_cards = game_zone.get_cards()

	# Add missing cards
	for card in game_cards:
		if not visual_instances.has(card.instance_id):
			visual_zone.add_card(card)

	# Remove cards no longer in zone
	var game_ids = {}
	for card in game_cards:
		game_ids[card.instance_id] = true

	for instance_id in visual_instances:
		if not game_ids.has(instance_id):
			visual_zone.remove_card(visual_instances[instance_id])

## Card click handler
func _on_zone_card_clicked(card_visual: CardVisual, zone_type: Enums.ZoneType, player_idx: int) -> void:
	if card_visual.card_instance:
		card_clicked.emit(card_visual.card_instance, zone_type, player_idx)

## Highlight cards in a zone based on a condition
func highlight_zone_cards(player_idx: int, zone_name: String, predicate: Callable) -> void:
	var zone = get_zone(player_idx, zone_name)
	if zone:
		zone.highlight_interactive(predicate)

## Clear all highlights
func clear_all_highlights() -> void:
	for player_idx in range(2):
		for zone_name in player_zones[player_idx]:
			var zone = player_zones[player_idx][zone_name]
			if zone:
				zone.clear_highlights()
