extends RefCounted
## Hearthvale address chooser (docs/HOUSING_V2.md), UI v3 skin. Opened by the Hearthvale Gate in Aldoria (no house
## yet), the Lane Keeper in every lane, or "Move" in the Life window's Home tab. Left: the open lanes (neighbours, party
## friends living there); right: the lane plan - 4 rows x 5 plots on two streets, every plot a card (house number,
## owner + house level, NPC tenant, or "For rent"); pick one and press "Live here" / "Move here". All server commands
## (house_list -> "lanes" event, house_claim / house_move).

const Life = preload("res://scripts/server/life.gd")
const Housing = preload("res://scripts/server/housing.gd")
const UiSkin = preload("res://scripts/ui/ui_skin.gd")

const INK := Color("#5b4128")
const INK_SOFT := Color("#8a7052")

var lu = null
var hud = null
var lanes: Array = []
var sel_lane := ""
var sel_plot := -1


func setup(life_ui) -> void:
	lu = life_ui
	hud = life_ui.hud
	hud._window("housing", "Hearthvale  ·  หมู่บ้านฮาร์ธเวล", Vector2(250, 70), Vector2(820, 0))


func is_open() -> bool:
	return hud.is_open("housing")


func open() -> void:
	UiSkin.set_open(hud.windows["housing"], true)
	hud.windows["housing"].move_to_front()
	var r: Dictionary = lu._send({"t": "house_list"})
	if r.get("lanes", null) is Array:
		lanes = r["lanes"]
	fill()


## "lanes" event (remote clients) / a plot changed while the window is open.
func on_lanes(ls: Array) -> void:
	lanes = ls
	if is_open():
		fill()


func on_plot(_comm: String) -> void:
	if is_open():
		var r: Dictionary = lu._send({"t": "house_list"})
		if r.get("lanes", null) is Array:
			lanes = r["lanes"]
		fill()


func _own() -> Dictionary:
	var c = PlayerState.ch
	return c.life.get("house", {}) if c != null and c.life is Dictionary else {}


func fill() -> void:
	var body: VBoxContainer = hud.bodies["housing"]
	hud._clear(body)
	var own := _own()
	var has_house := not Housing.own_rec_client(PlayerState.ch).is_empty()
	if sel_lane == "" or lanes.filter(func(l): return str(l["comm"]) == sel_lane).is_empty():
		sel_lane = str(own.get("comm", "")) if str(own.get("comm", "")) != "" else (str(lanes[lanes.size() - 1]["comm"]) if not lanes.is_empty() else "")
	var ban := PanelContainer.new()
	ban.add_theme_stylebox_override("panel", UiSkin.banner(Color("#6aa888")))
	body.add_child(ban)
	var bl := UiSkin.label("Pick a lane and an address. Twenty houses per lane - live next to your friends! You can move later (once a day).\nเลือกซอยและบ้านเลขที่ ซอยละ 20 หลัง อยู่ใกล้เพื่อนได้ ย้ายได้วันละครั้ง", 13, Color.WHITE, "Medium", 4)
	bl.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART
	ban.add_child(bl)
	var cols := HBoxContainer.new()
	cols.add_theme_constant_override("separation", 10)
	body.add_child(cols)
	# lanes
	var lv := VBoxContainer.new()
	lv.add_theme_constant_override("separation", 4)
	lv.custom_minimum_size = Vector2(200, 0)
	cols.add_child(UiSkin.boxed(lv, 6.0))
	lv.add_child(UiSkin.label("Lanes  ·  ซอย", 15, Color("#8a5418"), "SemiBold"))
	for l in lanes:
		var b := Button.new()
		b.name = "Lane_" + str(l["comm"])
		b.focus_mode = Control.FOCUS_NONE
		var fr: Array = l.get("friends", [])
		b.text = "%s\n%d / %d neighbours%s" % [str(l["name"]), int(l["owners"]), (l["plots"] as Array).size(),
			("  ·  friends: " + ", ".join(fr)) if not fr.is_empty() else ""]
		b.alignment = HORIZONTAL_ALIGNMENT_LEFT
		b.custom_minimum_size = Vector2(190, 52)
		var on := str(l["comm"]) == sel_lane
		b.add_theme_stylebox_override("normal", UiSkin.card(on, 6.0))
		b.add_theme_stylebox_override("hover", UiSkin.card(true, 6.0))
		b.add_theme_stylebox_override("pressed", UiSkin.card(true, 6.0))
		b.add_theme_font_override("font", UiSkin.font("Medium"))
		b.add_theme_font_size_override("font_size", 13)
		for cn in ["font_color", "font_hover_color", "font_pressed_color"]:
			b.add_theme_color_override(cn, INK)
		var cm := str(l["comm"])
		b.pressed.connect(func():
			sel_lane = cm
			sel_plot = -1
			fill())
		lv.add_child(b)
	# plan
	var rv := VBoxContainer.new()
	rv.add_theme_constant_override("separation", 4)
	cols.add_child(rv)
	var lane: Dictionary = {}
	for l in lanes:
		if str(l["comm"]) == sel_lane:
			lane = l
	if lane.is_empty():
		rv.add_child(UiSkin.label("No lane open.", 14, INK_SOFT))
		return
	rv.add_child(UiSkin.label("%s  ·  plan" % str(lane["name"]), 15, Color("#8a5418"), "SemiBold"))
	var plan := VBoxContainer.new()
	plan.name = "Plan"
	plan.add_theme_constant_override("separation", 3)
	rv.add_child(UiSkin.boxed(plan, 6.0))
	var states: Array = lane["plots"]
	for row in 4:
		var g := HBoxContainer.new()
		g.add_theme_constant_override("separation", 4)
		plan.add_child(g)
		for col in 5:
			var i := row * 5 + col
			if i < states.size():
				g.add_child(_plot_card(i, states[i], own))
		if row == 0 or row == 2:
			var st := UiSkin.label("~ street · ถนน ~", 11, INK_SOFT, "Medium")
			st.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
			plan.add_child(st)
		elif row == 1:
			var pz := UiSkin.label("✿  plaza: Tilly · stove · board · mail  ·  ลานกลางหมู่บ้าน  ✿", 12, Color("#5a8a5a"), "Medium")
			pz.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
			plan.add_child(pz)
	var act := HBoxContainer.new()
	act.add_theme_constant_override("separation", 8)
	rv.add_child(act)
	var info := "Pick a plot  ·  เลือกบ้าน"
	var can := false
	if sel_plot >= 0 and sel_plot < states.size():
		var s: Dictionary = states[sel_plot]
		var st2 := str(s.get("s", "free"))
		if st2 == "owner":
			info = "No. %d is %s's house." % [sel_plot + 1, str(s.get("name", ""))]
		else:
			info = "No. %d%s" % [sel_plot + 1, ("  ·  %s will move out for you" % str(s.get("name", ""))) if st2 == "tenant" else "  ·  for rent"]
			can = true
	var il := UiSkin.label(info, 13, INK, "Medium")
	il.size_flags_horizontal = Control.SIZE_EXPAND_FILL
	act.add_child(il)
	var go: Button = hud._button(("Move here  ·  ย้ายมาที่นี่" if has_house else "Live here  ·  อยู่ที่นี่"),
		func(): _choose(), not can, "" if can else "Pick a free plot")
	go.name = "HouseConfirm"
	act.add_child(go)
	if has_house:
		var gh: Button = hud._button("Go home  ·  กลับบ้าน", _go_home, false, "", "alt")
		gh.name = "HouseGoHome"
		act.add_child(gh)


func _plot_card(i: int, s: Dictionary, own: Dictionary) -> Control:
	var b := Button.new()
	b.name = "PlotCard_%d" % i
	b.focus_mode = Control.FOCUS_NONE
	b.custom_minimum_size = Vector2(108, 62)
	var st := str(s.get("s", "free"))
	var mine := str(own.get("comm", "")) == sel_lane and int(own.get("plot", -1)) == i
	var t := "No. %d\n" % (i + 1)
	var col := INK
	match st:
		"owner":
			t += "%s  Lv %d" % [str(s.get("name", "")).left(10), int(s.get("lv", 1))]
		"tenant":
			t += "%s" % str(s.get("name", "")).left(12)
			col = Color("#6a4a8a")
		_:
			t += "For rent · ว่าง"
			col = Color("#2f7d2a")
	if mine:
		t = "No. %d\n★ Your home" % (i + 1)
	b.text = t
	var on := i == sel_plot or mine
	var sb = UiSkin.card(on, 5.0)
	if st == "owner" and not mine:
		sb = UiSkin.inset(5.0, 0)
	b.add_theme_stylebox_override("normal", sb)
	b.add_theme_stylebox_override("hover", UiSkin.card(true, 5.0))
	b.add_theme_stylebox_override("pressed", UiSkin.card(true, 5.0))
	b.add_theme_font_override("font", UiSkin.font("Medium"))
	b.add_theme_font_size_override("font_size", 12)
	for cn in ["font_color", "font_hover_color", "font_pressed_color"]:
		b.add_theme_color_override(cn, col)
	b.pressed.connect(func():
		sel_plot = i
		fill())
	return b


func _choose() -> void:
	if sel_lane == "" or sel_plot < 0:
		return
	var has_house := not Housing.own_rec_client(PlayerState.ch).is_empty()
	var r: Dictionary = lu._send({"t": "house_move" if has_house else "house_claim", "comm": sel_lane, "plot": sel_plot})
	if bool(r.get("ok", false)):
		hud.windows["housing"].visible = false


func _go_home() -> void:
	lu._send({"t": "house_go"})
	hud.windows["housing"].visible = false
