class_name StorytellerBanner extends CanvasLayer
## Phase 15 — Non-blocking ambient banner for BANNER-display EventDef events.
##
## Anchored top-center just below the top bar (~60 px Y offset).
## Shows: title (bold), body, optional "Go there" button.
## Auto-dismisses after 6 sec via Timer; tap-to-dismiss-early also supported.
##
## Multiple banners queue — only one is visible at a time.  On dismiss the
## next queued event is shown automatically.
##
## On dismiss: calls Storyteller.resolve_current(0).
## Subscribes to EventBus.storyteller_event_fired in _ready; ignores MODAL events.

const AUTO_DISMISS_SEC: float = 6.0
const TILE_SIZE_PX: int = 16

## Internal queue of pending EventDef refs (BANNER display only).
var _queue: Array = []
## The EventDef currently on screen (null when idle).
var _current_event = null

# ── node refs ───────────────────────────────────────────────────────────────
var _root: Control = null
var _title_label: Label = null
var _body_label: Label = null
var _go_there_btn: Button = null
var _dismiss_btn: Button = null
var _timer: Timer = null


func _ready() -> void:
	layer = 15  # above world (0), above top-bar (10), below modal (20)

	_build_ui()
	_root.visible = false

	EventBus.storyteller_event_fired.connect(_on_event_fired)
	Audit.log("storyteller_ui", "StorytellerBanner ready")


func _exit_tree() -> void:
	if EventBus.storyteller_event_fired.is_connected(_on_event_fired):
		EventBus.storyteller_event_fired.disconnect(_on_event_fired)


# ── UI construction ──────────────────────────────────────────────────────────

func _build_ui() -> void:
	# Outer anchor — top-center strip.
	_root = Control.new()
	_root.name = "BannerRoot"
	_root.set_anchors_preset(Control.PRESET_TOP_WIDE)
	_root.custom_minimum_size = Vector2(0, 80)
	_root.offset_top = 60     # sit just below the 48 px top bar
	_root.offset_bottom = 140
	_root.mouse_filter = Control.MOUSE_FILTER_PASS
	add_child(_root)

	# Panel background centred horizontally.
	var panel := PanelContainer.new()
	panel.name = "Panel"
	panel.set_anchors_preset(Control.PRESET_CENTER_TOP)
	panel.custom_minimum_size = Vector2(480, 80)
	# Offset so it stays centred regardless of screen width.
	panel.offset_left = -240
	panel.offset_right = 240
	panel.offset_top = 0
	panel.offset_bottom = 80
	panel.mouse_default_cursor_shape = Control.CURSOR_POINTING_HAND
	_root.add_child(panel)

	# Tap-anywhere-to-dismiss — GuiInput on the panel itself.
	panel.gui_input.connect(_on_panel_gui_input)

	var vbox := VBoxContainer.new()
	vbox.add_theme_constant_override("separation", 4)
	panel.add_child(vbox)

	_title_label = Label.new()
	_title_label.name = "TitleLabel"
	_title_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
	_title_label.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
	vbox.add_child(_title_label)

	_body_label = Label.new()
	_body_label.name = "BodyLabel"
	_body_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
	_body_label.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
	vbox.add_child(_body_label)

	var btn_row := HBoxContainer.new()
	btn_row.alignment = BoxContainer.ALIGNMENT_CENTER
	btn_row.add_theme_constant_override("separation", 8)
	vbox.add_child(btn_row)

	_go_there_btn = Button.new()
	_go_there_btn.name = "GoThereBtn"
	_go_there_btn.text = Strings.t(&"ui.go_there")
	_go_there_btn.custom_minimum_size = Vector2(96, 48)
	_go_there_btn.focus_mode = Control.FOCUS_NONE
	_go_there_btn.visible = false
	_go_there_btn.pressed.connect(_on_go_there_pressed)
	btn_row.add_child(_go_there_btn)

	_dismiss_btn = Button.new()
	_dismiss_btn.name = "DismissBtn"
	_dismiss_btn.text = Strings.t(&"ui.dismiss")
	_dismiss_btn.custom_minimum_size = Vector2(96, 48)
	_dismiss_btn.focus_mode = Control.FOCUS_NONE
	_dismiss_btn.pressed.connect(_on_dismiss_pressed)
	btn_row.add_child(_dismiss_btn)

	# Auto-dismiss timer.
	_timer = Timer.new()
	_timer.name = "AutoDismiss"
	_timer.one_shot = true
	_timer.wait_time = AUTO_DISMISS_SEC
	_timer.timeout.connect(_on_dismiss_pressed)
	add_child(_timer)


# ── event handling ───────────────────────────────────────────────────────────

func _on_event_fired(event) -> void:
	# Only handle banner-display events.
	if event.display != EventDef.Display.BANNER:
		return
	_queue.append(event)
	if _current_event == null:
		_show_next()


func _show_next() -> void:
	if _queue.is_empty():
		_root.visible = false
		_current_event = null
		return

	_current_event = _queue.pop_front()
	var ev = _current_event

	_title_label.text = ev.title
	_body_label.text = _substitute_pawn(ev.body)

	var has_focus: bool = ev.focus_tile != Vector2i(-1, -1)
	_go_there_btn.visible = has_focus

	_root.visible = true
	_timer.start()
	Audit.log("storyteller_ui", "banner shown: %s" % ev.id)


func _on_dismiss_pressed() -> void:
	if not _timer.is_stopped():
		_timer.stop()
	Storyteller.resolve_current(0)
	Audit.log("storyteller_ui", "banner dismissed: %s" % (_current_event.id if _current_event != null else "(none)"))
	_current_event = null
	_show_next()


func _on_go_there_pressed() -> void:
	if _current_event == null:
		return
	_pan_camera(_current_event.focus_tile)
	# Also dismiss so the banner clears after the pan.
	_on_dismiss_pressed()


func _on_panel_gui_input(event: InputEvent) -> void:
	if event is InputEventMouseButton and event.pressed and event.button_index == MOUSE_BUTTON_LEFT:
		_on_dismiss_pressed()
	elif event is InputEventScreenTouch and event.pressed:
		_on_dismiss_pressed()


# ── helpers ──────────────────────────────────────────────────────────────────

func _pan_camera(tile: Vector2i) -> void:
	var cam = get_node_or_null("/root/Main/World/CameraRig")
	if cam == null:
		Audit.log("storyteller_ui", "pan_camera: CameraRig not found")
		return
	if cam.has_method("pan_to_tile"):
		cam.pan_to_tile(tile)
	else:
		# Fallback: instant snap to tile centre.
		cam.position = Vector2(tile.x * TILE_SIZE_PX + TILE_SIZE_PX / 2,
				tile.y * TILE_SIZE_PX + TILE_SIZE_PX / 2)


func _substitute_pawn(body: String) -> String:
	if not "%pawn%" in body:
		return body
	var name: String = "Settler"
	if not World.pawns.is_empty():
		name = World.pawns[0].pawn_name
	return body.replace("%pawn%", name)
