local mod_name = minetest.get_current_modname()
local mod_path = minetest.get_modpath(mod_name)
local S = minetest.get_translator(mod_name)


pmb_inventory.player = {}

local me = pmb_inventory.player

function pmb_inventory.get_itemslot_array(x, y, width, height, hotbar)
    local ret = ""
    local o = 0.250
    local p = 0.185
    for k = 0, height - 1, 1 do
        if hotbar and k == height - 1 then y = y + hotbar end
        for i = 0, width - 1, 1 do
            ret = ret .."image["..(x+i+0.025 - o/2)..","..(y+k-0.0 - p/2)..";"..(1+o)..","..(1+p)..";pmb_inv_itemslot_bg.png^[opacity:150]"
        end
    end
    return ret
end

me.p = {}

-- inventory sizes
me.width = 10
me.height = 4

function pmb_inventory.player.set_size(width, height)
    me.width = width
    me.height = height
end

function pmb_inventory.player.init_hotbar(player)
    player:hud_set_hotbar_itemcount(me.width)
    player:hud_set_hotbar_selected_image("pmb_inv_hotbar_select.png^[colorize:#603866:256")
    player:hud_set_hotbar_image("white.png^[colorize:#81507b:256")
    -- player:hud_set_flags({hotbar=false})
    me.p[player] = {}
end


pmb_inventory.register_formspec_process("inventory", "pmb_inventory:main", function(flags)
    local offset, size = flags.offset, flags.size
    if offset==nil then offset = {x=5, y=12} end
    if size==nil then size = {x=me.width, y=me.height} end
    return (
        "bgcolor[#00000000]"..
        pmb_inventory.get_itemslot_array(offset.x, offset.y - me.height, me.width, me.height, 0.3)..
        "list[current_player;main;"..tostring(offset.x)..","..tostring(offset.y - me.height)..     ";"..(me.width)..","..(me.height-1)..";10]"..
        "list[current_player;main;"..tostring(offset.x)..","..tostring(0.3+offset.y-1)..";"..(me.width)..","..(1)..";]"..
        "listcolors[#66504f00;#554a6440]"..
        pmb_inventory.player.get_armor({x=offset.x+10.3,y=offset.y-me.height})..
        pmb_inventory.player.get_accessories({x=offset.x+11.3,y=offset.y-me.height})..
        "background["..(offset.x-0.5)..","..(offset.y-0.5 - me.height)..";"..(size.x+3.5)..","..(size.y+1)..";pmb_inv_bg.png^[opacity:200]"
    )
end)

pmb_inventory.register_formspec_process("crafting", "pmb_inventory:main", function(flags)
    local crafting_disabled = (minetest.get_modpath("pmb_gamemodes")) and not pmb_gamemodes.player_has_tag(flags.player, "crafting")
    return ((crafting_disabled and "") or pmb_inventory.tcraft_get_formspec(flags.player, flags.method))
end)

local function get_formspec(offset, size)
    return pmb_inventory.get_formspec_of_type("inventory", {offset=offset, size=size}),
        (size or {x=me.width, y=me.height})
end
pmb_inventory.player.get_formspec = get_formspec

function pmb_inventory.player.get_armor(o)
    return (
        pmb_inventory.get_itemslot_array(o.x, o.y, 1, 4)..
        "list[current_player;armor;"..(o.x)..","..(o.y)..";1,4;]"..
        "image["..(o.x)..","..(o.y+0)..";1,1;pmb_inv_head.png^[colorize:#33333344:255]"..
        "image["..(o.x)..","..(o.y+1)..";1,1;pmb_inv_torso.png^[colorize:#33333344:255]"..
        "image["..(o.x)..","..(o.y+2)..";1,1;pmb_inv_legs.png^[colorize:#33333344:255]"..
        "image["..(o.x)..","..(o.y+3)..";1,1;pmb_inv_boots.png^[colorize:#33333344:255]"
    )
end

function pmb_inventory.player.get_accessories(o)
    return (
        pmb_inventory.get_itemslot_array(o.x, o.y, 1, 1)..
        "list[current_player;accessories;"..(o.x)..","..(o.y)..";1,1;]"..
        "image["..(o.x)..","..(o.y+0)..";1,1;pmb_inv_backpack.png^[colorize:#33333344:255]"
        -- left out for now since there probably won't even be items for this
        -- "image["..(o.x)..","..(o.y+3)..";1,1;pmb_inv_necklace.png^[colorize:#33333344:255]"..
        -- "image["..(o.x)..","..(o.y+1)..";1,1;pmb_inv_ring.png^[colorize:#33333344:255]"..
        -- "image["..(o.x)..","..(o.y+2)..";1,1;pmb_inv_ring.png^[colorize:#33333344:255]"
    )
end

local function get_craft_menu(player, method)
    return (
        "size[24.00,12.0]"..
        pmb_inventory.get_formspec_of_type("crafting", {player=player, method=method}) ..
        pmb_inventory.get_formspec_of_type("inventory", {offset={x=5, y=12}, size={x=me.width, y=me.height}})
    )
end
pmb_inventory.player.get_craft_menu = get_craft_menu


local pl = {}
local _t = 0.1
minetest.register_globalstep(function(dtime)
    _t = _t - dtime
    if _t > 0 then return end
    _t = 0.2

    for i, player in ipairs(minetest.get_connected_players()) do
        local new_spec = ""
        repeat
            if (minetest.get_modpath("pmb_gamemodes")) and not pmb_gamemodes.player_has_tag(player, "inventory") then
                pl[player] = new_spec
                player:set_inventory_formspec(new_spec)
                break
            end

            new_spec = pmb_inventory.player.get_craft_menu(player)
            if string.len(new_spec) ~= string.len(pl[player] or "") then
                pl[player] = new_spec
                player:set_inventory_formspec(new_spec)
                break
            end
        until true
    end
end)

minetest.register_on_joinplayer(function(player, last_login)
    player:set_inventory_formspec(pmb_inventory.player.get_craft_menu(player, "normal"))
end)


pmb_inventory.player.inventory_slot_groups = {}

function pmb_inventory.player.bind_group_to_inventory_slot(group, listname, listindex)
    local invslots = pmb_inventory.player.inventory_slot_groups
    if not invslots[listname] then invslots[listname] = {} end
    invslots[listname][listindex] = group
end

pmb_inventory.player.bind_group_to_inventory_slot("armor_head", "armor", 1)
pmb_inventory.player.bind_group_to_inventory_slot("armor_torso", "armor", 2)
pmb_inventory.player.bind_group_to_inventory_slot("armor_legs", "armor", 3)
pmb_inventory.player.bind_group_to_inventory_slot("armor_boots", "armor", 4)
pmb_inventory.player.bind_group_to_inventory_slot("accessory", "accessories", 1)
pmb_inventory.player.bind_group_to_inventory_slot("necklace", "accessories", 2)
pmb_inventory.player.bind_group_to_inventory_slot("ring", "accessories", 3)
pmb_inventory.player.bind_group_to_inventory_slot("ring", "accessories", 4)


local function fix_bad_inventory_action_args(player, action, inventory, inventory_info)
    local info = {}
    -- deal with the silly way this callback gives its parameters
    if (action == "move") then
        info.to_list = inventory_info.to_list
        info.to_index = inventory_info.to_index
        info.from_list = inventory_info.from_list
        info.from_index = inventory_info.from_index
        info.from_stack = inventory:get_stack(inventory_info.from_list, inventory_info.from_index)
        info.to_stack = inventory:get_stack(inventory_info.to_list, inventory_info.to_index)
    elseif (action == "put") then
        info.to_list = inventory_info.listname
        info.to_index = inventory_info.index
        info.to_stack = inventory_info.stack
    elseif (action == "take") then
        info.from_list = inventory_info.listname
        info.from_index = inventory_info.index
        info.to_stack = inventory_info.stack
    end
    return info
end

minetest.register_allow_player_inventory_action(function(player, action, inventory, inventory_info)
    local to_list = inventory_info.listname or inventory_info.to_list

    -- nothing is defined for this list name so just forget about it
    if not pmb_inventory.player.inventory_slot_groups[to_list] then return end

    local info = fix_bad_inventory_action_args(player, action, inventory, inventory_info)
    if not info then return end
    local slotgroups = pmb_inventory.player.inventory_slot_groups[to_list]

    -- nothing is defined for this index so just forget about it
    if not slotgroups[info.to_index] then return end

    -- now test if it has the group
    if minetest.get_item_group(info.from_stack:get_name(), slotgroups[info.to_index]) > 0 then return end

    -- return 0 will prevent any item from being moved
    return 0
end)

