local S = minetest.get_translator("dwarf_chreator")

local insert = table.insert
local concat = table.concat

local appearance_names =
{
	sex = S("Sex"),
	skin_color = S("Skin Color"),
	hair = S("Hair"),
	beard = S("Beard"),
	hair_brightness = S("Hair Brightness"),
	hair_redness = S("Hair Redness"),
	armor = S("Armor"),
	helmet = S("Helmet")
}

minetest.register_entity("dwarf_chreator:skin_preview", {
	physical = false,
	pointable = false,
	visual = "mesh",
	mesh = "",
	textures = {},
	automatic_rotate = 0.3,
	glow = minetest.LIGHT_MAX,
	static_save = false,
})

local primping_players = {}

local appearance_fields =
{
	"sex",
	"skin_color",
	"hair",
	"beard",
	"hair_brightness",
	"hair_redness",
	"armor",
	"helmet"
}

local formspec_template = {
	"size[3.9,8]" ..
	"position[0.33,0.5]" ..
	"no_prepends[]" ..
	"real_coordinates[true]" ..
	"button[3,0.3;2,0.7;randomize;" .. S("Randomize") .. "]"
}

do
	local offset = 0.3
	for i, v in ipairs(appearance_fields)
	do
		local name = appearance_names[v]
		offset = offset + 0.7

		local bg = "background[0.4," .. offset + 0.05 .. ";2.6,0.6;dwarf_chreator_text_background.png]"
		local label = "label[0.5," .. offset + 0.35 .. ";" .. name .."]"
		local button1 = "button[3," .. offset .. ";1,0.7;" .. v .. "<;<]"
		local button2 = "button[4," .. offset .. ";1,0.7;" .. v .. ">;>]"

		insert(formspec_template, bg)
		insert(formspec_template, label)
		insert(formspec_template, button1)
		insert(formspec_template, button2)
	end

	formspec_template = concat(formspec_template)
end

--[[
	appearance:

	skin color
	hair brightness
	hair redness
	model
	sex
	beard
	hair
	armor
	helmet

]]


local image_spec_prefix = "image[8,1;3,6;"

local function get_skin_preview(appearance)
	return image_spec_prefix .. "dwarf_chreator_skin_preview.png" ..
		dwarf_characters.get_skin_color_mod(appearance.skin_color) .. "]"
end

local function get_simple_preview(appearance, field)
	local img = dwarf_characters["get_" .. field .. "_preview"](appearance[field])
	return img and image_spec_prefix .. img .. "]" or ""
end

local function get_haircolored_preview(appearance, field)
	local img = dwarf_characters["get_" .. field .. "_preview"](appearance[field])
	if not img
	then
		return ""
	end

	local tab =
	{
		image_spec_prefix,
		img,
		dwarf_characters.get_hair_color_mod(
			appearance.hair_brightness,
			appearance.hair_redness),
		"]"
	}
	return concat(tab)
end

local function close_preview(name)
	local player = minetest.get_player_by_name(name)

	if the_end_game_master.get_stage() == "pregame" then
		the_end_game_master.set_pregame_hud(player)
	end

	player:set_properties({visual_size = vector.new(1, 1, 1)})
	player:set_pos(primping_players[name].oldpos)
	player:set_look_horizontal(primping_players[name].old_horiz)
	player:set_look_vertical(primping_players[name].old_vert)

	primping_players[name].luaent.object:remove()

	primping_players[name] = nil
end

local function refresh_preview(playername, appearance)
	local time = minetest.get_timeofday()

	primping_players[playername].luaent.object:set_properties({
		textures = dwarf_characters.get_textures(appearance),
		mesh = appearance.model,
	})
end

local checkstep = 0
minetest.register_globalstep(function(dtime)
	checkstep = checkstep + dtime

	if checkstep >= 3 then
		checkstep = 0

		for _, player in pairs(minetest.get_connected_players()) do
			local playername = player:get_player_name()
			local time = minetest.get_timeofday()

			if primping_players[playername] and (time < 0.2 or time > 0.8) then
				close_preview(playername)
				minetest.close_formspec(playername, "chreator")
				minetest.chat_send_player(playername, "There is no time for changing your appearance. Prepare for battle!")
			end
		end
	end
end)

local function get_primpers()
	local count = 0

	for _, _ in pairs(primping_players) do
		count = count + 1
	end

	return count
end

function dwarf_chreator.show_formspec(player)
	local name = player:get_player_name()
	local offset = vector.new(get_primpers() * 10, 0, get_primpers() * 100)
	local entpos = vector.add(vector.new(-1000, 1000, -1000), offset)
	local playerpos = vector.add(vector.new(-1002, 1000, -1002), offset)

	if the_end_game_master.get_stage() == "pregame" then
		the_end_game_master.remove_pregame_hud(player)
	end

	player:add_player_velocity(vector.multiply(player:get_player_velocity(), -1)) -- set velocity to 0, 0, 0
	player:set_properties({visual_size = vector.new(0, 0, 0)})

	primping_players[name] = {
		oldpos = player:get_pos(),
		old_horiz = player:get_look_horizontal(),
		old_vert = player:get_look_vertical(),
	}

	minetest.set_node(vector.new(playerpos.x, playerpos.y - 1, playerpos.z), {name = "map_master:invisible_wall"})
	player:set_pos(playerpos)

	local obj = minetest.add_entity(entpos, "dwarf_chreator:skin_preview")
	obj:set_animation({x = 31, y = 31}) -- Set to stand animation
	primping_players[name].luaent = obj:get_luaentity()

	player:set_look_horizontal(minetest.dir_to_yaw(vector.direction(playerpos, entpos)) + 0.1)
	player:set_look_vertical(0.1)

	refresh_preview(name, dwarf_characters.get_appearance(name))
	minetest.show_formspec(name, "chreator", formspec_template)
end

minetest.register_chatcommand("chreator",
{
	privs = {interact = true},
	func = function(name)
		local player = minetest.get_player_by_name(name)
		local time = minetest.get_timeofday()

		if player
		then
			if time >= 0.2 and time <= 0.8 then
				dwarf_chreator.show_formspec(player)
				return true, S("Showing formspec")
			else
				return false, S("You can't change your appearance at night!")
			end
		else
			return true, S("Can't show formspec: no player online with name @1", name)
		end
	end
})


minetest.register_on_player_receive_fields(
	function(player, formname, fields)
		local playername = player:get_player_name()

		-- formname isn't 'chreator' when player presses [ESC]
		if fields.quit and primping_players[playername] then
			close_preview(playername)
		end

		if not minetest.check_player_privs(player, "interact") or
			formname ~= "chreator"
		then
			return
		end

		--check for < > type button presses
		local field
		local dir
		for i, v in ipairs(appearance_fields)
		do
			if fields[v .. ">"]
			then
				field = v
				dir = 1
			elseif fields[v .. "<"]
			then
				field = v
				dir = -1
			end
		end

		local appearance
		if not field --not a cycling button
		then
			if fields["randomize"] --handle randomize button
			then
				appearance = dwarf_characters.get_random_appearance()
				dwarf_characters.set_appearance(playername, appearance)

			else --no button: apply appearance to actual player model
				dwarf_characters.apply_appearance(player)
				return true
			end
		else
			--update appearance
			appearance = dwarf_characters.get_appearance(playername)
			--appearance[field] = --cycle through possibilities
			dwarf_characters.cycle_appearance(appearance, field, dir)
		end

		refresh_preview(playername, appearance)
		minetest.show_formspec(playername, "chreator", formspec_template)

		return true
	end)
