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,
	backface_culling = false,
	on_activate = function(self)
		self.object:set_yaw(math.pi/ 4 * 3) --rotate so it's facing the player in the beginning
		self.object:set_animation(dwarf_characters.get_animation("stand"))
	end,
	
})

local primping_players = {}

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

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

do
	local offset = 0.3
	for i, v in ipairs(lr_button_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() == "game"
	then
		hud_set_api.set_set(player, "game")
	else
		hud_set_api.set_set(player, "pregame")
	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)
	primping_players[playername].luaent.object:set_properties({
		textures = dwarf_characters.get_textures(appearance),
		mesh = appearance.model,
		automatic_rotate = primping_players[playername].autorotate.val
	})
end


local function get_primpers()
	local count = 0

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

	return count
end

hud_set_api.register_set("chreator",
	{
		flags = 
		{
			hotbar = false,
			healthbar = false,
			crosshair = false,
			wielditem = false,
			breathbar = false,
		}
	})

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)

	hud_set_api.set_set(player, "chreator")

	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(),
		autorotate = {val = 0.3, prev = -1},
	}

	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")
	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, server = true},
	func = function(name)
		local player = minetest.get_player_by_name(name)
		
		if player
		then
			dwarf_chreator.show_formspec(player)
			return true, S("Showing formspec")
		else
			return false, 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(lr_button_fields)
		do
			if fields[v .. ">"]
			then
				field = v
				dir = 1
			elseif fields[v .. "<"]
			then
				field = v
				dir = -1
			end
		end

		local appearance = dwarf_characters.get_appearance(playername)
		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)
			elseif fields["autorotate"]
			then
				--stop rotating and rotate in opposite direction when done
				local rot = primping_players[playername].autorotate
				if rot.val ~= 0
				then
					rot.prev = math.sign(rot.val)
					rot.val = 0
				else
					rot.val = 0.3 * rot.prev * -1
				end
			else --no button: apply appearance to actual player model
				dwarf_characters.apply_appearance(player)
				return true
			end
		else
			--update appearance
			--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)
