"use strict"

/* global view, action_button, send_action */

// TODO: pool for hero points to animate ?
// TODO: pool for faction markers to animate ?

const ui = {
	header: document.querySelector("header"),
	status: document.getElementById("status"),
	hand_panel: document.getElementById("hand_panel"),

	map_container: document.getElementById("pieces"),

	tooltip: document.getElementById("tooltip"),

	fascist_cards: document.getElementById("fascist_cards"),
	trash: document.getElementById("trash"),
	hand: document.getElementById("hand"),

	player_areas: document.getElementById("player_areas"),
	panels: [
		document.getElementById("player_area_a"),
		document.getElementById("player_area_c"),
		document.getElementById("player_area_m"),
	],
	tableaus: [
		document.getElementById("tableau_a"),
		document.getElementById("tableau_c"),
		document.getElementById("tableau_m"),
	],
	tokens: [
		document.getElementById("tokens_a"),
		document.getElementById("tokens_c"),
		document.getElementById("tokens_m"),
	],
	bag_of_glory: document.getElementById("bag_of_glory"),

	// spaces
	tracks_x: [],
	tracks: [],
	fronts: [],
	status_fronts: [],
	con_fronts: [],
	str_fronts: [],

	// tokens
	standees: [],
	bonuses: [],
	medallions: [],
	blank_markers: [],

	// cards
	cards: [],
}

/* :r! node tools/parse-layout.js */
const boxes = {
	"Northern": [149,146,149,149],
	"Aragon": [563,275,149,149],
	"Southern": [341,641,149,149],
	"Madrid": [195,398,161,161],
	"Liberty": [955,65,662,59],
	"Collectivization": [954,231,663,60],
	"SovietSupport": [954,564,663,59],
	"ForeignAid": [954,730,663,59],
	"Government": [1015,398,602,58],
	"Medallion1": [608,834,69,70],
	"Medallion2": [690,834,70,70],
	"Medallion3": [772,834,70,70],
	"Medallion4": [855,834,70,70],
	"Medallion5": [937,834,70,70],
	"CurrentYearDeck": [38,976,187,261],
	"CurrentEvent1": [301,976,187,261],
	"CurrentEvent2": [526,976,187,261],
	"CurrentEvent3": [751,976,187,261],
	"CurrentEvent4": [976,976,187,261],
	"Glory1": [1320,966,59,59],
	"Glory2": [1418,966,119,59],
	"Glory3": [1399,1075,58,58],
	"Glory4": [1278,1153,300,59],
	"Bonus1": [728,726,74,73],
	"Bonus2": [818,726,74,73],
}

function toggle_pieces() { // eslint-disable-line no-unused-vars
	ui.map_container.classList.toggle("hide")
}

let animation_register = []

function register_animation(e) {
	animation_register.push(e)
}

function remember_position(e) {
	if (e.parentElement) {
		let prect = e.parentElement.getBoundingClientRect()
		let rect = e.getBoundingClientRect()
		e.my_visible = 1
		e.my_parent = e.parentElement
		e.my_px = prect.x
		e.my_py = prect.y
		e.my_x = rect.x
		e.my_y = rect.y
	} else {
		e.my_visible = 0
		e.my_parent = null
		e.my_x = 0
		e.my_y = 0
		e.my_z = 0
	}
}

function animate_position(e) {
	if (e.parentElement && e.my_visible) {
		let prect = e.parentElement.getBoundingClientRect()
		let rect = e.getBoundingClientRect()
		let dx, dy
		if (e.parentElement === e.my_parent) {
			// animate element within animated element...
			dx = (e.my_x - e.my_px) - (rect.x - prect.x)
			dy = (e.my_y - e.my_py) - (rect.y - prect.y)
		} else {
			dx = e.my_x - rect.x
			dy = e.my_y - rect.y
		}

		// fade in
		if (!e.my_parent) {
			e.animate(
				[
					{ opacity: 0 },
					{ opacity: 1 }
				],
				{ duration: 500, easing: "ease" }
			)
		}

		if (dx !== 0 || dy !== 0) {
			let dist = Math.sqrt((dx * dx) + (dy * dy))
			let time = Math.max(500, Math.min(1000, dist / 2))
			e.animate(
				[
					{ transform: `translate(${dx}px, ${dy}px)`, },
					{ transform: "translate(0, 0)", },
				],
				{ duration: time, easing: "ease" }
			)
		}
	}
}


let action_register = []

function register_action(e, action, id) {
	e.my_action = action
	e.my_id = id
	e.onmousedown = on_click_action
	action_register.push(e)
}

function on_click_action(evt) {
	if (evt.button === 0)
		if (send_action(evt.target.my_action, evt.target.my_id))
			evt.stopPropagation()
}

function is_action(action, arg) {
	if (arg === undefined)
		return !!(view.actions && view.actions[action] === 1)
	return !!(view.actions && view.actions[action] && view.actions[action].includes(arg))
}

let on_init_once = false

function build_track(t, action_name, track_name, a, b) {
	let [x, y, w, h] = boxes[track_name]
	let e

	ui.tracks[t] = []
	ui.tracks_x[t] = []
	for (let s = a; s <= b; ++s) {
		const bm = t * 11 + s

		ui.tracks_x[t][s] = Math.round(x) + 4 + "px"
		e = ui.tracks[t][s] = document.createElement("div")
		e.className = "track"
		e.style.top = y + "px"
		e.style.left = Math.round(x) + "px"
		register_action(e, action_name, s)
		ui.map_container.appendChild(e)

		e = (ui.blank_markers[bm] = document.createElement("div"))
		e.className = "red token blank hide"
		e.style.top = Math.round(y+4) + "px"
		e.style.left = Math.round(x+3) + "px"
		register_action(e, "blank_marker", bm)
		ui.map_container.appendChild(e)

		x += 60.5
	}

	e = (ui.standees[t] = document.createElement("div"))
	e.className = "white token standee standee_" + t
	e.style.top = y - 10 + "px"
	e.style.left = boxes[track_name][0] + 4 + "px"
	register_action(e, "standee", t)
	register_animation(e)
	ui.map_container.appendChild(ui.standees[t])
}

function build_bonus(b, box_name, cname) {
	var [x, y, w, h] = boxes[box_name]
	var e = ui.bonuses[b] = document.createElement("div")
	e.className = "red token round " + cname
	e.style.top = Math.round(y + w/2 - 32) + "px"
	e.style.left = Math.round(x + w/2 - 32) + "px"
	register_action(e, "bonus", b)
	ui.map_container.appendChild(e)
}

function build_front(i, box_name) {
	var [x, y, w, h] = boxes[box_name]
	var e

	e = ui.status_fronts[i] = document.createElement("div")
	e.className = "hide"
	e.style.position = "absolute"
	e.style.top = Math.round(y + h / 2 - 140) + "px"
	e.style.left = Math.round(x + w / 2 - 103) + "px"
	ui.map_container.appendChild(e)

	e = ui.con_fronts[i] = document.createElement("div")
	e.className = "front_container"
	e.style.top = y + 5 + "px"
	e.style.left = x + "px"
	e.style.width = w - 25 + "px"
	e.style.height = 55 + "px"
	ui.map_container.appendChild(e)

	e = ui.str_fronts[i] = document.createElement("div")
	e.className = "front_container"
	e.style.top = y + h - 55 - 5+ "px"
	e.style.left = x + "px"
	e.style.width = w - 25 + "px"
	e.style.height = 55 + "px"
	ui.map_container.appendChild(e)

	e = ui.fronts[i] = document.createElement("div")
	e.className = "front"
	e.style.top = Math.round(y-3) + "px"
	e.style.left = Math.round(x-3) + "px"
	e.style.width = Math.round(w - 6) + "px"
	e.style.height = Math.round(h - 6) + "px"
	register_action(e, "front", i)
	ui.map_container.appendChild(e)
}

function on_init() {
	var i, e

	if (on_init_once)
		return
	on_init_once = true

	ui.roles_list = document.getElementById("roles"),
	ui.roles = [
		document.getElementById("role_Anarchist"),
		document.getElementById("role_Communist"),
		document.getElementById("role_Moderate"),
	]

	build_track(0, "tr0", "Liberty", 0, 10)
	build_track(1, "tr1", "Collectivization", 0, 10)
	build_track(2, "tr2", "Government", 1, 10)
	build_track(3, "tr3", "SovietSupport", 0, 10)
	build_track(4, "tr4", "ForeignAid", 0, 10)

	build_bonus(0, "Bonus1", "bonus_morale")
	build_bonus(1, "Bonus2", "bonus_teamwork")

	build_front(0, "Aragon")
	build_front(1, "Madrid")
	build_front(2, "Northern")
	build_front(3, "Southern")

	ui.medallion_container = []
	for (i = 0; i < 5; ++i) {
		e = ui.medallion_container[i] = document.createElement("div")
		e.className = "medallion_container"
		e.style.top = boxes["Medallion"+(i+1)][1] + "px"
		e.style.left = boxes["Medallion"+(i+1)][0] + "px"
		ui.map_container.appendChild(e)
	}

	ui.raw_glory_container = []
	for (i = 0; i < 4; ++i) {
		e = ui.raw_glory_container[i] = document.createElement("div")
		e.className = "glory_container"
		e.style.left = boxes["Glory" + (i+1)][0] + "px"
		e.style.top = boxes["Glory" + (i+1)][1] + "px"
		ui.map_container.appendChild(e)
	}
	ui.glory_container = [
		ui.raw_glory_container[0],
		ui.raw_glory_container[1],
		ui.raw_glory_container[1],
		ui.raw_glory_container[2],
		ui.raw_glory_container[3],
		ui.raw_glory_container[3],
		ui.raw_glory_container[3],
		ui.raw_glory_container[3],
		ui.raw_glory_container[3],
	]

	e = ui.fascist_deck = document.createElement("div")
	e.className = "fascist_deck"
	e.style.top = boxes["CurrentYearDeck"][1] - 10 + "px"
	e.style.left = boxes["CurrentYearDeck"][0] - 10 + "px"
	ui.map_container.appendChild(e)

	ui.current_events = []
	for (i = 0; i < 4; ++i) {
		e = (ui.current_events[i] = document.createElement("div"))
		e.className = "current_events"
		e.style.left = boxes["CurrentEvent" + (i+1)][0] - 10 + "px"
		e.style.top = boxes["CurrentEvent" + (i+1)][1] - 10 + "px"
		ui.map_container.appendChild(e)
	}

	for (i = 0; i < 9; ++i) {
		e = (ui.medallions[i] = document.createElement("div"))
		e.className = "pink token medallion medallion_" + i
		e.onmouseenter = on_focus_medallion
		e.onmouseleave = on_blur_medallion
		register_action(e, "medallion", i)
		register_animation(e)
	}

	for (i = 1; i <= 120; ++i) {
		e = (ui.cards[i] = document.createElement("div"))
		e.className = "card card_" + i
		register_action(e, "card", i)
		register_animation(e)
	}

	e = ui.initiative = document.createElement("div")
	e.className = "red token round initiative"
	register_animation(e)
}

function place_cards(e, cards) {
	if (cards) {
		for (var c of cards) {
			e.appendChild(ui.cards[c])
			ui.cards[c].classList.toggle("selected", view.selected_cards.includes(c))
		}
	}
}

const faction_class = {
	"Anarchist": "anarchist",
	"Communist": "communist",
	"Moderate": "moderate",
	"0": "anarchist",
	"1": "communist",
	"2": "moderate",
	"f": "fascist",
}

function update_front(status_card, str_container, con_container, front, front_id) {
	var i, n, e, cn

	str_container.replaceChildren()
	con_container.replaceChildren()

	if (front.status === "Victory") {
		status_card.className = "card card_111"
		return
	}
	if (front.status === "Defeat") {
		status_card.className = "card card_112"
		return
	}
	status_card.className = "hide"

	if (front.value < 0) {
		n = -front.value
		cn = "brown token front_minus"
	} else {
		n = front.value
		cn = "pink token front_plus"
	}
	for (i = 0; i < n; ++i) {
		e = document.createElement("div")
		e.className = cn
		str_container.appendChild(e)
	}

	var current_card = view.current_events[view.current_events.length-1]
	if (current_card && data.cards[current_card].test.front === front_id) {
		e = document.createElement("div")
		e.className = "red token player fascist"
		con_container.appendChild(e)
	}

	for (i = 0; i < 3; ++i) {
		if (front.contributions.includes(i)) {
			e = document.createElement("div")
			e.className = "red token player " + faction_class[i]
			con_container.appendChild(e)
		}
	}
}

function update_medallions(container, list) {
	for (var i of list)
		container.appendChild(ui.medallions[i])
}

function update_hero_points(container, n) {
	for (var i = 0; i < n; ++i) {
		var e = document.createElement("div")
		e.className = "token pink hero_point"
		container.appendChild(e)
	}
}

function update_stat_line(x) {
	var i, line
	line = ""
	for (i = 0; i < view.hero_points[x]; ++i)
		line += "\u272b"
	if (view.initiative === x)
		line += (view.year & 1) ? " \u2bc6" : " \u2bc5"
	return line
}

function on_update() { // eslint-disable-line no-unused-vars
	var i, x, e

	on_init()

	animation_register.forEach(remember_position)

	ui.player_areas.replaceChildren()
	ui.roles_list.replaceChildren()
	for (i = 0; i < 3; ++i) {
		ui.player_areas.appendChild(ui.panels[view.player_order[i]])
		ui.roles_list.appendChild(ui.roles[view.player_order[i]])
	}

	ui.header.classList.toggle("fascist", !!view.fascist)

	ui.initiative.classList.toggle("ccw", (view.year & 1) === 0)
	roles.Anarchist.stat.textContent = update_stat_line(0)
	roles.Communist.stat.textContent = update_stat_line(1)
	roles.Moderate.stat.textContent = update_stat_line(2)

	// TODO: played card (side panel?)

	// TODO: player draw/discard/trash
	// TODO: bag of glory

	ui.fascist_deck.replaceChildren()
	if (view.year === 1) 
		place_cards(ui.fascist_deck, [ 120, 119, 118 ])
	else if (view.year === 2)
		place_cards(ui.fascist_deck, [ 120, 119 ])
	else
		place_cards(ui.fascist_deck, [ 120])

	ui.fascist_cards.replaceChildren()
	place_cards(ui.fascist_cards, view.fascist_cards)

	ui.trash.replaceChildren()
	place_cards(ui.trash, view.trash)

	ui.hand_panel.classList = "panel " + faction_class[player]
	ui.hand.replaceChildren()
	place_cards(ui.hand, view.hand)

	ui.tableaus[0].replaceChildren()
	ui.tableaus[1].replaceChildren()
	ui.tableaus[2].replaceChildren()
	ui.tableaus[0].appendChild(ui.cards[117])
	ui.tableaus[1].appendChild(ui.cards[116])
	ui.tableaus[2].appendChild(ui.cards[115])
	place_cards(ui.tableaus[0], view.tableaus[0])
	place_cards(ui.tableaus[1], view.tableaus[1])
	place_cards(ui.tableaus[2], view.tableaus[2])

	for (i = 0; i <= 1; ++i) {
		ui.bonuses[i].classList.toggle("red", !!view.bonuses[i])
		ui.bonuses[i].classList.toggle("gray", !view.bonuses[i])
		ui.bonuses[i].classList.toggle("off", !view.bonuses[i])
	}

	for (i = 0; i < 4; ++i) {
		ui.current_events[i].replaceChildren()
		if (i < view.current_events.length)
			ui.current_events[i].appendChild(ui.cards[view.current_events[i]])
	}

	for (i = 0; i < 5; ++i)
		ui.standees[i].style.left = ui.tracks_x[i][view.tracks[i]]

	for (i = 0; i < 55; ++i) {
		if (ui.blank_markers[i])
			ui.blank_markers[i].classList.toggle("hide",
				!view.triggered_track_effects.includes(i))
	}

	for (i = 0; i < 5; ++i) {
		ui.medallion_container[i].replaceChildren()
		if (i < view.medallions[3].length) {
			x = view.medallions[3][i]
			if (x !== null)
				ui.medallion_container[i].appendChild(ui.medallions[x])
		}
	}

	ui.tokens[0].replaceChildren()
	ui.tokens[1].replaceChildren()
	ui.tokens[2].replaceChildren()
	ui.tokens[view.initiative].appendChild(ui.initiative)
	update_medallions(ui.tokens[0], view.medallions[0])
	update_medallions(ui.tokens[1], view.medallions[1])
	update_medallions(ui.tokens[2], view.medallions[2])
	update_hero_points(ui.tokens[0], view.hero_points[0])
	update_hero_points(ui.tokens[1], view.hero_points[1])
	update_hero_points(ui.tokens[2], view.hero_points[2])

	update_front(ui.status_fronts[0], ui.str_fronts[0], ui.con_fronts[0], view.fronts[0], "a")
	update_front(ui.status_fronts[1], ui.str_fronts[1], ui.con_fronts[1], view.fronts[1], "m")
	update_front(ui.status_fronts[2], ui.str_fronts[2], ui.con_fronts[2], view.fronts[2], "n")
	update_front(ui.status_fronts[3], ui.str_fronts[3], ui.con_fronts[3], view.fronts[3], "s")

	for (e of ui.raw_glory_container)
		e.replaceChildren()
	for (i = 0; i < view.glory.length; ++i) {
		x = view.glory[i]
		e = document.createElement("div")
		e.className = "red token player " + faction_class[x]
		ui.glory_container[i].appendChild(e)
	}

	ui.bag_of_glory.replaceChildren()
	if (Array.isArray(view.bag_of_glory)) {
		for (x of view.bag_of_glory) {
			e = document.createElement("div")
			e.className = "red token player " + faction_class[x]
			ui.bag_of_glory.appendChild(e)
		}
	}

	action_button("Anarchist", "Anarchist")
	action_button("Communist", "Communist")
	action_button("Moderate", "Moderate")

	action_button("add_glory", "Add to Bag of Glory")
	action_button("add_to_front", "+1 to a Front")
	action_button("draw_card", "Draw a Card")
	action_button("draw_cards", "Draw Cards")
	action_button("draw_glory", "Draw from Bag of Glory")
	action_button("gain_hp", "Gain Hero Points")
	action_button("lose_hp", "Lose Hero Points")
	action_button("play_to_tableau", "Action Points")
	action_button("play_for_event", "Event")
	action_button("remove_blank_marker", "Remove Blank marker")

	action_button("use_momentum", "Momentum")
	action_button("use_ap", "Action Points")
	action_button("use_morale_bonus", "Morale Bonus")

	action_button("skip", "Skip")
	action_button("yes", "Yes")
	action_button("no", "No")
	action_button("confirm", "Confirm")
	action_button("done", "Done")

	action_button("spend_hp", "Use Hero Points")

	action_button("end_turn", "End Turn")
	action_button("undo", "Undo")

	for (e of action_register)
		e.classList.toggle("action", is_action(e.my_action, e.my_id))

	animation_register.forEach(animate_position)
}

function on_focus_card_tip(x) {
	ui.tooltip.className = "card card_" + x
}

function on_focus_medallion_tip(x) {
	ui.tooltip.className = "pink token medallion medallion_" + x
}

function on_blur_tip(x) {
	ui.tooltip.className = "hide"
}

function on_focus_medallion(evt) {
	let info = data.medallions[evt.target.my_id]
	ui.status.textContent = info.name + ": " + info.tooltip
}

function on_blur_medallion() {
	ui.status.textContent = ""
}

function sub_card(_match, p1) {
	return `<span class="tip" onmouseenter="on_focus_card_tip(${p1})" onmouseleave="on_blur_tip()">${data.cards[p1].title}</span>`
}

function sub_medallion(_match, p1) {
	return `<i class="tip" onmouseenter="on_focus_medallion_tip(${p1})" onmouseleave="on_blur_tip()">${data.medallions[p1].name}</i>`
}

function sub_token(match) {
	switch (match) {
	case "T0": return `<img src="images/icons/player_anarchist.png">`
	case "T1": return `<img src="images/icons/player_communist.png">`
	case "T2": return `<img src="images/icons/player_moderate.png">`
	case "T3": return `<img src="images/icons/player_fascist.png">`
	case "HP": return `<img src="images/icons/hero_point.png">`
	}
	return match
}

function on_log(text) { // eslint-disable-line no-unused-vars
	let p = document.createElement("div")

	if (text.match(/^>>/)) {
		text = text.substring(2)
		p.className = "ii"
	}
	if (text.match(/^>/)) {
		text = text.substring(1)
		p.className = "i"
	}

	text = text.replace(/<-/g, "\u2190")
	text = text.replace(/->/g, "\u2192")

	text = text.replace(/&/g, "&amp;")
	text = text.replace(/</g, "&lt;")
	text = text.replace(/>/g, "&gt;")
	text = text.replace(/-( ?[\d(])/g, "\u2212$1")

	text = text.replace(/\bC(\d+)\b/g, sub_card)
	text = text.replace(/\bM(\d+)\b/g, sub_medallion)
	text = text.replace(/\bT\d\b/g, sub_token)
	text = text.replace(/\bHP\b/g, "Hero points")
	// text = text.replace(/\bHP\b/g, "\u272b")
	// text = text.replace(/\bHP\b/g, sub_token)

	if (text.startsWith("#")) {
		p.className = "h " + faction_class[text[1]]
		text = text.substring(3)
	}

	p.innerHTML = text
	return p
}