extends RefCounted
## Housing v2 P3 flower market window (docs/HOUSING_V2.md), UI v3 skin. Florist Posy on every lane plaza buys crops +
## flowers and sells crops, base / hybrid flowers and base-colour seeds, for gold. Prices drift every day (server/garden2.gd
## mult(): the same for everyone): each row shows today's price, the change since yesterday and a 7-day sparkline, so
## you can stock up on poor days and sell on great ones. Every button is a server command (market_sell / market_buy).

const Life = preload("res://scripts/server/life.gd")
const Garden2 = preload("res://scripts/server/garden2.gd")
const Icons = preload("res://scripts/icons.gd")
const UiSkin = preload("res://scripts/ui/ui_skin.gd")

const INK := Color("#5b4128")
const INK_SOFT := Color("#8a7052")
const UP := Color("#2f8a3a")
const DOWN := Color("#c0392b")

var lu = null
var hud = null
var tab := "sell"


func setup(life_ui) -> void:
	lu = life_ui
	hud = life_ui.hud
	hud._window("market", "Flower Market  ·  ตลาดดอกไม้", Vector2(300, 80), Vector2(720, 0))


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


func open(t: String = "") -> void:
	if t != "":
		tab = t
	UiSkin.set_open(hud.windows["market"], true)
	hud.windows["market"].move_to_front()
	fill()


func _send(cmd: Dictionary) -> Dictionary:
	var r: Dictionary = lu._send(cmd)
	lu.dirty = true
	return r


## Market goods in a stable order: crops, then flowers by species + colour tier.
static func goods() -> Array:
	var m: Dictionary = Garden2.market()
	var ids: Array = m.keys()
	ids.sort_custom(func(a, b): return [int(m[a].get("tier", 0)), str(a)] < [int(m[b].get("tier", 0)), str(b)])
	return ids


func fill() -> void:
	var body: VBoxContainer = hud.bodies["market"]
	hud._clear(body)
	var c = PlayerState.ch
	if c == null:
		return
	var top := HBoxContainer.new()
	top.add_theme_constant_override("separation", 8)
	body.add_child(top)
	for t in [["sell", "Sell  ·  ขาย"], ["buy", "Buy  ·  ซื้อ"], ["seeds", "Seeds  ·  เมล็ด"]]:
		var b: Button = hud._tab_button(str(t[1]), tab == str(t[0]), open.bind(str(t[0])))
		b.name = "MkTab_" + str(t[0])
		top.add_child(b)
	top.add_child(hud._grow(Control.new()))
	var gp := PanelContainer.new()
	gp.add_theme_stylebox_override("panel", UiSkin.badge(Color("#c4923a")))
	gp.add_child(UiSkin.label("Gold %s" % _fmt(int(c.zeny)), 13, Color.WHITE, "SemiBold", 3))
	top.add_child(gp)
	var hint := UiSkin.label("Prices change every day at midnight - buy on poor days, sell on great ones.  ·  ราคาเปลี่ยนทุกวัน", 12, INK_SOFT, "Medium")
	body.add_child(hint)
	var list := _scroll(body, 400, "MarketList")
	match tab:
		"sell":
			var any := false
			for id in goods():
				if int(c.count(str(id))) > 0:
					any = true
					_row(list, c, str(id), "sell")
			if not any:
				list.add_child(UiSkin.label("Nothing to sell yet - harvest crops and flowers in your garden.  ·  ยังไม่มีของขาย", 13, INK_SOFT, "Medium"))
		"buy":
			for id in goods():
				if Garden2.buy_price(str(id)) > 0:
					_row(list, c, str(id), "buy")
		"seeds":
			for n in GameData.npcs:
				if str(n.get("life", "")) == "market":
					for id in n.get("sells", []):
						_row(list, c, str(id), "seed")
					break
	hud.windows["market"].reset_size.call_deferred()


func _scroll(parent: Control, h: float, name: String) -> VBoxContainer:
	var sc := ScrollContainer.new()
	sc.name = name
	sc.custom_minimum_size = Vector2(660, h)
	sc.horizontal_scroll_mode = ScrollContainer.SCROLL_MODE_DISABLED
	parent.add_child(UiSkin.boxed(sc, 6.0))
	var v := VBoxContainer.new()
	v.add_theme_constant_override("separation", 4)
	v.size_flags_horizontal = Control.SIZE_EXPAND_FILL
	sc.add_child(v)
	return v


func _row(list: Control, c, id: String, mode: String) -> void:
	var p := PanelContainer.new()
	p.name = "Mk_" + id
	var d := Garden2.day()
	var today := Garden2.sell_price(id)
	var yday := Garden2.sell_price(id, Garden2.day_back(d, 1))
	var great := mode != "seed" and Garden2.mult(id) >= 1.4
	p.add_theme_stylebox_override("panel", UiSkin.card(great and mode == "sell", 5.0))
	list.add_child(p)
	var r := HBoxContainer.new()
	r.add_theme_constant_override("separation", 8)
	p.add_child(r)
	r.add_child(Icons.item_tile(id, 40))
	var tv := VBoxContainer.new()
	tv.add_theme_constant_override("separation", 0)
	tv.custom_minimum_size = Vector2(190, 0)
	r.add_child(tv)
	tv.add_child(UiSkin.label(GameData.item_name(id), 13, INK, "SemiBold"))
	var tier := int(Garden2.market().get(id, {}).get("tier", 0))
	tv.add_child(UiSkin.label("in bag %d%s" % [int(c.count(id)), ["", "  ·  hybrid", "  ·  rare", "  ·  legendary"][clampi(tier, 0, 3)]], 11, INK_SOFT, "Medium"))
	if mode != "seed":
		# 7-day sparkline of the sell price
		var hist: Array = []
		for k in range(6, -1, -1):
			hist.append(float(Garden2.sell_price(id, Garden2.day_back(d, k))))
		var sp := Control.new()
		sp.custom_minimum_size = Vector2(110, 34)
		sp.draw.connect(_spark.bind(sp, hist))
		r.add_child(sp)
		var ch := (float(today) - float(yday)) / maxf(1.0, float(yday)) * 100.0
		var cb := PanelContainer.new()
		cb.add_theme_stylebox_override("panel", UiSkin.badge(UP if ch >= 0 else DOWN))
		cb.add_child(UiSkin.label("%s%d%%" % ["+" if ch >= 0 else "", int(round(ch))], 11, Color.WHITE, "SemiBold", 2))
		cb.custom_minimum_size = Vector2(52, 0)
		r.add_child(cb)
		if great:
			var gb := PanelContainer.new()
			gb.add_theme_stylebox_override("panel", UiSkin.badge(Color("#d08a1a")))
			gb.add_child(UiSkin.label("Great day!", 11, Color.WHITE, "SemiBold", 2))
			r.add_child(gb)
	r.add_child(hud._grow(Control.new()))
	match mode:
		"sell":
			r.add_child(UiSkin.label("%s g" % _fmt(today), 15, INK, "Bold"))
			var b1: Button = hud._button("Sell 1", func(): _send({"t": "market_sell", "id": id, "n": 1}), false, "", "alt")
			b1.name = "Sell1_" + id
			r.add_child(b1)
			var ba: Button = hud._button("Sell all", func(): _send({"t": "market_sell", "id": id, "n": int(c.count(id))}), false)
			ba.name = "SellAll_" + id
			r.add_child(ba)
		_:
			var bp := Garden2.buy_price(id)
			r.add_child(UiSkin.label("%s g" % _fmt(bp), 15, INK, "Bold"))
			for n in [1, 5]:
				var bb: Button = hud._button("Buy %d" % n, func(): _send({"t": "market_buy", "id": id, "n": n}), int(c.zeny) < bp * n, "", "alt" if n == 1 else "")
				bb.name = "Buy%d_%s" % [n, id]
				r.add_child(bb)


func _spark(ctl: Control, hist: Array) -> void:
	var mn := 1e9
	var mx := -1e9
	for v in hist:
		mn = minf(mn, float(v))
		mx = maxf(mx, float(v))
	var w := ctl.size.x
	var h := ctl.size.y
	var pts := PackedVector2Array()
	for i in hist.size():
		var y := h - 4.0 - (float(hist[i]) - mn) / maxf(1.0, mx - mn) * (h - 8.0)
		pts.append(Vector2(4.0 + i * (w - 8.0) / maxf(1.0, hist.size() - 1), y))
	ctl.draw_rect(Rect2(Vector2.ZERO, ctl.size), Color(1, 1, 1, 0.35))
	ctl.draw_polyline(pts, Color("#8a5418"), 2.0, true)
	var last: Vector2 = pts[pts.size() - 1]
	ctl.draw_circle(last, 3.5, UP if hist[hist.size() - 1] >= hist[hist.size() - 2] else DOWN)


static func _fmt(n: int) -> String:
	var s := str(absi(n))
	var out := ""
	while s.length() > 3:
		out = "," + s.right(3) + out
		s = s.left(s.length() - 3)
	return ("-" if n < 0 else "") + s + out
