class_name HintOverlay extends CanvasLayer
## Phase 19 — Top-center hint banner for the onboarding tour.
##
## Layer 22: above StorytellerModal (20) and DaySummaryCard (19) so hints are
## always visible.  Non-blocking — only the banner itself catches input; the
## world below remains fully interactive while the hint is up.
##
## API:
##   show_hint(hint_id, message) — populate text and slide in.
##   hide_hint()                 — slide out and emit hint_dismissed.
##
## Registers itself with HintSystem in _ready so the autoload never calls
## find_child() on the tree.

const BANNER_W:  int = 640
const BANNER_H:  int = 80
const SLIDE_DUR: float = 0.30   # seconds for the slide-in/out tween

# Accent gold — matches MedievalTheme.C_ACCENT_GOLD.
const C_ACCENT_GOLD: Color = Color(0.92, 0.75, 0.22, 1.0)

# ── node refs ─────────────────────────────────────────────────────────────────

var _root_ctrl:  Control       = null   # MOUSE_FILTER_IGNORE, full-rect anchor
var _panel:      PanelContainer = null  # the visible banner
var _icon_lbl:   Label         = null
var _msg_lbl:    Label         = null
var _got_it_btn: Button        = null

# ── state ─────────────────────────────────────────────────────────────────────

var _current_hint_id: StringName = &""
var _tween: Tween = null


func _ready() -> void:
	layer = 22
	process_mode = Node.PROCESS_MODE_ALWAYS
	_build_ui()
	_set_panel_visible(false)

	# Register with the HintSystem autoload so it can call show_hint/hide_hint.
	if Engine.has_singleton("HintSystem") or has_node("/root/HintSystem"):
		var hs: Node = get_node_or_null("/root/HintSystem")
		if hs != null and hs.has_method("register_overlay"):
			hs.register_overlay(self)
	Audit.log("hint_overlay", "HintOverlay ready (layer %d)" % layer)


func _exit_tree() -> void:
	pass  # signal connections owned by HintSystem are cleaned up when it exits


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

func _build_ui() -> void:
	# Transparent full-rect root — MOUSE_FILTER_IGNORE so world stays interactive.
	_root_ctrl = Control.new()
	_root_ctrl.name = "Root"
	_root_ctrl.set_anchors_preset(Control.PRESET_FULL_RECT)
	_root_ctrl.mouse_filter = Control.MOUSE_FILTER_IGNORE
	add_child(_root_ctrl)

	# Banner PanelContainer — top-center, fixed size.
	_panel = PanelContainer.new()
	_panel.name = "Banner"
	_panel.custom_minimum_size = Vector2(BANNER_W, BANNER_H)
	# Anchor to top-center.
	_panel.set_anchors_preset(Control.PRESET_TOP_WIDE)
	# Center horizontally: offset left/right to BANNER_W wide, centred.
	_panel.anchor_left   = 0.5
	_panel.anchor_right  = 0.5
	_panel.anchor_top    = 0.0
	_panel.anchor_bottom = 0.0
	_panel.offset_left   = -BANNER_W / 2.0
	_panel.offset_right  =  BANNER_W / 2.0
	_panel.offset_top    = 0.0
	_panel.offset_bottom = BANNER_H
	_panel.mouse_filter  = Control.MOUSE_FILTER_STOP   # banner catches its own taps
	_panel.gui_input.connect(_on_banner_input)
	_root_ctrl.add_child(_panel)

	# Inner HBox: icon | message (expanding) | button
	var hbox := HBoxContainer.new()
	hbox.alignment = BoxContainer.ALIGNMENT_CENTER
	hbox.add_theme_constant_override("separation", 12)
	_panel.add_child(hbox)

	# Icon label — bulb emoji as procedural indicator, gold-tinted.
	_icon_lbl = Label.new()
	_icon_lbl.name = "Icon"
	_icon_lbl.text = "💡"
	_icon_lbl.add_theme_font_size_override("font_size", 20)
	_icon_lbl.add_theme_color_override("font_color", C_ACCENT_GOLD)
	_icon_lbl.vertical_alignment = VERTICAL_ALIGNMENT_CENTER
	hbox.add_child(_icon_lbl)

	# Message label — auto-wraps, expands to fill.
	_msg_lbl = Label.new()
	_msg_lbl.name = "Message"
	_msg_lbl.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
	_msg_lbl.size_flags_horizontal = Control.SIZE_EXPAND_FILL
	_msg_lbl.vertical_alignment = VERTICAL_ALIGNMENT_CENTER
	hbox.add_child(_msg_lbl)

	# "Got it" button — right side.
	_got_it_btn = Button.new()
	_got_it_btn.name = "GotItBtn"
	_got_it_btn.text = Strings.t(&"hint.got_it")
	_got_it_btn.custom_minimum_size = Vector2(80, 40)
	_got_it_btn.focus_mode = Control.FOCUS_NONE
	_got_it_btn.pressed.connect(hide_hint)
	hbox.add_child(_got_it_btn)


# ── public API ────────────────────────────────────────────────────────────────

## Populate the banner with hint_id + message text then slide it in from above.
func show_hint(hint_id: StringName, message: String) -> void:
	_current_hint_id = hint_id
	_msg_lbl.text = message

	_set_panel_visible(true)

	var reduce_motion: bool = bool(GameState.settings.get("accessibility_reduce_motion", false))
	if reduce_motion:
		# Snap to final position immediately.
		_panel.offset_top    = 0.0
		_panel.offset_bottom = BANNER_H
		return

	# Slide in from above: start fully off-screen, tween to resting position.
	_panel.offset_top    = -BANNER_H
	_panel.offset_bottom = 0.0

	if _tween != null and _tween.is_running():
		_tween.kill()
	_tween = create_tween()
	_tween.set_trans(Tween.TRANS_CUBIC).set_ease(Tween.EASE_OUT)
	_tween.tween_property(_panel, "offset_top",    0.0,      SLIDE_DUR)
	_tween.parallel().tween_property(_panel, "offset_bottom", float(BANNER_H), SLIDE_DUR)


## Slide the banner out upward and emit hint_dismissed with the current hint_id.
func hide_hint() -> void:
	var id: StringName = _current_hint_id
	var reduce_motion: bool = bool(GameState.settings.get("accessibility_reduce_motion", false))
	if reduce_motion:
		_set_panel_visible(false)
		EventBus.hint_dismissed.emit(id)
		return

	if _tween != null and _tween.is_running():
		_tween.kill()
	_tween = create_tween()
	_tween.set_trans(Tween.TRANS_CUBIC).set_ease(Tween.EASE_IN)
	_tween.tween_property(_panel, "offset_top",    -float(BANNER_H), SLIDE_DUR)
	_tween.parallel().tween_property(_panel, "offset_bottom", 0.0,             SLIDE_DUR)
	_tween.tween_callback(_on_slide_out_finished.bind(id))


# ── internal callbacks ────────────────────────────────────────────────────────

func _on_slide_out_finished(id: StringName) -> void:
	_set_panel_visible(false)
	EventBus.hint_dismissed.emit(id)


func _on_banner_input(event: InputEvent) -> void:
	# Tap anywhere on the banner also dismisses it (touch-friendly).
	if event is InputEventMouseButton and event.pressed and event.button_index == MOUSE_BUTTON_LEFT:
		hide_hint()


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

func _set_panel_visible(v: bool) -> void:
	if _panel != null:
		_panel.visible = v
	# Keep root_ctrl always present but invisible panel blocks nothing.
	if _root_ctrl != null:
		_root_ctrl.visible = true   # always: root is MOUSE_FILTER_IGNORE anyway
