-- my hand the stand
minetest.override_item("", {
	wield_image = "orionplayer_hand.png",
	groups = {not_in_creative_inventory=1},
	range = 10.0,
	tool_capabilities = {
		groupcaps = {
			flora = {
				times = {
					[1] = 0.4,
					[2] = 0.9
				},
				maxlevel = 2
			},
			semisolids = {
				times = {
					[1] = 2
				},
				maxlevel = 1
			}
		}
	}
})


local creative_count = 0
minetest.register_on_player_hpchange(function(player, hp_change, reason)
	if reason.type == "fall" then return 0, true end
end, true)


local function update_scale(player, scale)
	player:set_properties({
		eye_height = 1.45 * scale,
		visual_size ={
			x=0.825 * scale,
			y=1.7 * scale,
			z=0.825 * scale
		},
		collisionbox = { -0.4125 * scale, 0.0, -0.415 * scale, 0.4125 * scale , 1.7 * scale, 0.4125 * scale },
		stepheight = 1.5
	})

	player:set_physics_override({
		jump= 0.7 * scale,
		gravity= 0.9,
		speed= 1.1 * scale
	})
end


local function make_scale(player)
	local playername = (type(player) == "string" and player or player:get_player_name())
	local shaplayer = minetest.sha1(playername, true)
	local rand = shaplayer:byte(1)
	local scale = shaplayer:byte(1) / 256 /2
	scale = scale + 1.75
	return scale
end


minetest.register_chatcommand("scale", {
	params = "[player] <scale>",
	description = "Scale a player",
	privs = {debug=true},
	func = function(name, param)
		local params = string.split(param, ' ')
		if #params > 2 or #params == 0 then return false end
		local playerObj = nil
		if #params == 1 then
			playerObj = minetest.get_player_by_name(name)
			scale = tonumber(params[1])
		else
			playerObj = minetest.get_player_by_name(params[1])
			scale = tonumber(params[2])
		end
		if not scale then return false, "provided scale needs to be a float" end
		if scale == 0 then return false, "provided scale cannot be 0!" end
		if not playerObj then return false, "player not found" end
		update_scale(playerObj, scale)
		local playermeta = playerObj:get_meta()
		playermeta:set_float("scale", scale)
	end
})


minetest.register_chatcommand("getnativescale", {
	params = "[player]",
	description = "gets a players FOV",
	privs = {debug=true},
	func = function(name, param)
		local params = string.split(param, ' ')
		if #params == 0 then
			return true, "Scale of " .. name .. " is " .. make_scale(name)
		else
			for i=1, #params do
				minetest.chat_send_player(name, params[i] .. " Scale: " .. make_scale(params[i]))
			end
			return true
		end
	end
})


minetest.register_chatcommand("getscale", {
	params = "[player]",
	description = "gets a players FOV",
	privs = {debug=true},
	func = function(name, param)
		local params = string.split(param, ' ')
		if #params > 1 then return false end
		local playerObj = nil
		if #params == 1 then
			playerObj = minetest.get_player_by_name(param)
			if not playerObj then return false, "player not found" end
			local meta = playerObj:get_meta()
			local scale = meta:get_float("scale")
			return true, "Scale of " .. name .. " is " .. scale
		else
			playerObj = minetest.get_player_by_name(name)
			if not playerObj then return false, "Fatal error, you do not exist :(" end
			local meta = playerObj:get_meta()
			local scale = meta:get_float("scale")
			return true, "Scale of " .. name .. " is " .. scale
		end
	end
})


minetest.register_chatcommand("setfov", {
	params = "[player] <fov>",
	description = "sets a players FOV",
	privs = {debug=true},
	func = function(name, param)
		local params = string.split(param, ' ')
		if #params > 2 then return false end
		local playerObj = nil
		if #params == 1 then
			playerObj = minetest.get_player_by_name(name)
			if not playerObj then return false, "player not found" end
			playerObj:set_fov(params[1], false, 0)
		elseif #params == 2 then
			playerObj = minetest.get_player_by_name(params[1])
			if not playerObj then return false, "player not found" end
			playerObj:set_fov(params[2], false, 0)
		else
			return false, "Needs atleast FOV specified"
		end
	end
})


minetest.register_chatcommand("resetscale", {
	params = "[player]",
	description = "resets a player scale",
	privs = {debug=true},
	func = function(name, param)
		local params = string.split(param, ' ')
		if #params > 1 then return false end
		local playerObj = nil
		if #params == 0 then
			playerObj = minetest.get_player_by_name(name)
		else
			playerObj = minetest.get_player_by_name(params[1])
		end
		if not playerObj then return false, "player not found" end
		local scale = make_scale(playerObj)
		update_scale(playerObj, scale)
		local playermeta = playerObj:get_meta()
		playermeta:set_float("scale", 0)
	end
})


local maxStackSize = minetest.settings:get("default_stack_max") or 99 -- the engine default is 99
local function populateCreativeInventory(player)
	creative_count = 0
	local inventory = player:get_inventory()
	inventory:set_list("crafting", nil)
	inventory:set_size("crafting", 500)
	for name, node in pairs(minetest.registered_nodes) do
		if node.groups.not_in_creative_inventory ~= 1 then
			inventory:add_item("crafting", ItemStack(node.name .. " " .. node.stack_max or maxStackSize))
			creative_count = creative_count +1
		end
	end
	for name, tools in pairs(minetest.registered_tools) do
		local newTool = ItemStack(tools.name)
		local meta = newTool:get_meta()
		local chargeable = tools.groups.sparktech_chargeable
		if chargeable then
			meta:set_int("energy", chargeable)
			newTool:set_wear(1)
			meta:set_tool_capabilities(tools.spark_caps_charge)
		end
		inventory:add_item("crafting", newTool)
		creative_count = creative_count +1
	end
	inventory:set_size("crafting", creative_count)
end


function populateSideBar(player)
	if not minetest.is_creative_enabled(player) then
		populateSurvivalInventory(picker)
	end
end


function populateSurvivalInventory(player)
	local inventory = player:get_inventory()
	local mainInventory = inventory:get_list("main")
	inventory:set_list("crafting", nil)
	local newList = orion.get_possible_crafts("hand", mainInventory)
	local listCount = 0
	if newList then listCount = #newList end
	inventory:set_size("crafting", listCount)
	inventory:set_list("crafting", newList)
end


if minetest.register_on_item_pickup then
	minetest.register_on_item_pickup(function(itemstack, picker, pointed_thing, time_from_last_punch)
		populateSideBar(picker)
	end)
end


minetest.register_craft_predict(function(itemstack, player, old_craft_grid, craft_inv)
	populateSideBar(player)
end)


minetest.register_on_dignode(function(pos, oldnode, digger)
	populateSideBar(digger)
end)


minetest.register_allow_player_inventory_action(function(player, action, inventory, inventory_info)
	-- action can be "move" "put" "take", the later two ONLY when NOT dealing with player-owned inventories
	--
	-- inventory info contains
	-- put: listname, index, stack
	-- take: listname, index, stack
	-- move: count, from_list, to_list, from_index, to_index
	-- player:get_meta():set_int("creative", 1)
	-- if player:get_meta():get_int("creative") == 1 then

	if action == "move" -- There should be no movement inside the inventory by the player
	and inventory_info.from_list == "crafting"
	and inventory_info.to_list == "crafting" then
		return 0
	end

	if minetest.is_creative_enabled(player) then
		-- allow players to move items here, to trash them.
		-- actual trashing is done in on_player_inventory_action
		-- Make sure destination is empty

		-- TODO
		-- if the item that i am moving into the craft list at the position
		-- is the same as the one i am moving
		-- it should then in the on_inventory callback delete the ammount of items
		-- i am moving from the previous list
		-- (moving fails because the stack on the other side is already full)
		if action == "move"
		and inventory_info.to_list == "crafting" then
			local destItem = inventory:get_stack(inventory_info.to_list, inventory_info.to_index)
			if destItem:get_name() == "" then
				return inventory_info.count
			else
				return 0
			end
		end

		if action == "put" then
			local destItem = inventory:get_stack(inventory_info.listname, inventory_info.index)
			if destItem:get_name() == "" then
				return inventory_info.stack:get_count()
			else
				return 0
			end
		end
	else
		if action == "move" -- Also nothing put into this inventory by the player
		and inventory_info.to_list == "crafting"
		or action == "put"
		and inventory_info.listname == "crafting" then
			return 0
		end

		if action == "take" then
			return inventory_info.stack:get_count()
		end
	end

	if action == "move"
	and inventory_info.from_list == "crafting" then
		return inventory_info.count
	end
end)


local maxStackSize = minetest.settings:get("default_stack_max") or 256
minetest.register_on_player_inventory_action(function(player, action, inventory, inventory_info)
	-- Doc sais "is_creative_enabled" should get a player name,
	-- but builtin doesn't care so implement this later with
	-- taking a player object directly.. or else a name
	if minetest.is_creative_enabled(player) then -- think CREATIVELY!
		if action == "put"
		and inventory_info.listname == "crafting" then
			inventory:set_stack(inventory_info.listname, inventory_into.index, ItemStack(""))
		end

		if action == "move"
		and inventory_info.to_list == "crafting" then
			inventory:set_stack(inventory_info.to_list, inventory_info.to_index, ItemStack(""))
		end

		if action == "take" then
			inventory:set_stack(inventory_info.listname, inventory_info.index, inventory_info.itemstack)
		end

		if action == "move"
		and inventory_info.from_list == "crafting" then
			local stack = inventory:get_stack(inventory_info.to_list, inventory_info.to_index)
			stack:set_count(maxStackSize)
			inventory:set_stack(inventory_info.from_list, inventory_info.from_index, stack)
		end
	else -- survival crafting
		if action == "take" and inventory_info.from_list == "crafting" then

		end
	end
end)


local function calculateScrollbarHeight(count)
	local height = (count - (count % 4)) * 2.15
	if count % 4 > 1 then height = height + 12 end
	return height
end


local scrollerProgress = nil
minetest.register_on_player_receive_fields(function(player, formname, fields)
	if fields["craftingScroller"] then
		scrollerProgress = fields["craftingScroller"]:gsub("CHG:", "")
	end
	if fields["quit"] == "true" then
		player:set_inventory_formspec(sparktech.add_inventory(0, 0, "", scrollerProgress, calculateScrollbarHeight(creative_count)))
	end
end)


minetest.register_on_joinplayer(function(player)
	player:set_properties({zoom_fov = 45})
	local meta = player:get_meta()
	local scale = meta:get_float("scale")
	if scale == 0 or not scale then
		scale = make_scale(player)
	end
	update_scale(player, scale)

	player:set_fov(100, false, 0)

	local inventory = player:get_inventory()
	--FIXMT: engine hardcodes this
	inventory:set_list("craft", nil)
	inventory:set_list("craftpreview", nil)
	inventory:set_list("craftresult", nil)
	inventory:set_size("main", 60)

	player:hud_set_hotbar_itemcount(10)
	--player:set_lighting({shadows = { intensity = 0.33} })
	if minetest.is_creative_enabled(player) then
		populateCreativeInventory(player)
	else
		populateSurvivalInventory(player)
	end
	-- TODO: survival crafting
	local lists = inventory:get_lists()
	player:set_formspec_prepend("")
	player:set_inventory_formspec(sparktech.add_inventory(0, 0, "", 0, calculateScrollbarHeight(creative_count)))
end)
