local S = core.get_translator("shapetester")

--Shapeshift sound setting
local default_shapeshift_sound = core.settings:get("shapetester_default_sound") or "shapetester_shift"

--Tool wear settings
local tool_wear = core.settings:get("shapetester_tool_wear") or "none"
local wear_amount = core.settings:get("shapetester_tool_max_uses") or 256

--Technical shapeshift tool
local function sethand(player,handname)
    player:get_inventory():set_size("hand", 1)
    player:get_inventory():set_stack("hand", 1, handname)
    return true
end

core.register_tool("shapetester:shape_computer", {
    description = S("Shape-shift Computer"),
    inventory_image = "shapetester_shape_computer.png",
    on_use = function(itemstack,user)
        if core.check_player_privs(user, {shapeshift=true}) then
            local name = user:get_player_name()
            shapetester.show_shapeshift_tech_menu(name)
            if not core.is_creative_enabled("") then
                if tool_wear == "both" or tool_wear == "shape_computer" then 
                    itemstack:add_wear_by_uses(wear_amount)
                    return itemstack
                end
            end
        else
            core.chat_send_player(user:get_player_name(), S("Shapetester -!- Insufficient privileges! (shapeshift)"))
        end
    end
})

--formspec
function shapetester.shapeshift_tech_menu_form(player)
    local formspec = {
        "size[11,4.5]",
        "background[0,0;0,0;shapetester_menu.png;true]",
        "field[0.25,0.35;8,0.8;model;"..S("Model file name")..":;shapetester_cube.obj]",
        "field[8.25,0.35;1.5,0.8;gravity;"..S("Gravity")..":;1]",
        "field[8.25,1.35.35;1.5,0.8;speed;"..S("Speed")..":;1]",
        "field[8.25,2.35;1.5,0.8;jump;"..S("Jump")..":;1]",
        "field[8.25,3.35;1.5,0.8;eye_height;"..S("Eye height")..":;0.5]",
        "field[8.25,4.35;1.5,0.8;step_height;"..S("Step height")..":;0.6]",
        "field[0.25,1.35;8,0.8;image;"..S("Model image")..":;shapetester_cube.png]",
        "field[0.25,2.35;8,0.8;collision;"..S("Collision box")..":;-0.5 -0.5 -0.5 0.5 0.5 0.5]",
        "field[0.25,3.35;8,0.8;visual_size;"..S("Visual size")..":;1 1 1]",
        "field[0.25,4.35;8,0.8;hand;"..S("Hand")..":;shapetester:cube_hand]",
        "button[9.5,0.155;1.5,0.4;transform;"..S("Transform!").."]",
        "button[9.5,1.155;1.5,0.4;load;"..S("Load").."]",
        "button[9.5,2.155;1.5,0.4;save;"..S("Save").."]",
    }

    return table.concat(formspec, "")
end

function shapetester.shapeshift_save_menu_form(player)
    local formspec = {
        "size[4,1.5]",
        "background[0,0;0,0;shapetester_menu.png;true]",
        "field[0.25,0.25;4,1;filename;"..S("Name")..":;myshapeshift]",
        "button[0.25,1;1.6,0.8;save;"..S("Save").."]",
    }

    return table.concat(formspec, "")
end

function shapetester.shapeshift_load_menu_form(player)
    local formspec = {
        "size[4,1.5]",
        "background[0,0;0,0;shapetester_menu.png;true]",
        "field[0.25,0.25;4,1;filename;"..S("Name")..":;myshapeshift]",
        "button[0.25,1;1.6,0.8;load;"..S("Load").."]",
    }

    return table.concat(formspec, "")
end

function shapetester.show_shapeshift_load_menu(player)
    core.show_formspec(
        player,
        "shapetester:shapeshift_load_menu",
        shapetester.shapeshift_load_menu_form(player)
    )
end

function shapetester.show_shapeshift_tech_menu(player)
    core.show_formspec(
        player,
        "shapetester:shapeshift_tech_menu",
        shapetester.shapeshift_tech_menu_form(player)
    )
end

function shapetester.show_shapeshift_save_menu(player)
    core.show_formspec(
        player,
        "shapetester:shapeshift_save_menu",
        shapetester.shapeshift_save_menu_form(player)
    )
end

--Saving shapeshifts
local function save_form(filename,shapeshift)
    local world_path = core.get_worldpath()

    local dir_path  = world_path .. "/shapeshifts"
    local file_path = dir_path .. "/"..filename..".lua"

    core.mkdir(dir_path)

    local file_content = core.serialize(shapeshift)

    local ok, err = core.safe_file_write(file_path, file_content)
    if not ok then
        core.log("error", "[shapetester] failed to write file: " .. err)
    else
        core.log("action", "[shapetester] player definition saved to " .. file_path)
    end
end

core.register_on_player_receive_fields(function(player, formname, fields)
    if formname == "shapetester:shapeshift_tech_menu" then
        if fields.transform then
            local coll = fields.collision:split(" ")
            local vis = fields.visual_size:split(" ")
            player:set_properties({
                textures      = { fields.image },
                visual        = "mesh",
                mesh          = fields.model,
                collisionbox  = {tonumber(coll[1]),tonumber(coll[2]),tonumber(coll[3]),tonumber(coll[4]),tonumber(coll[5]),tonumber(coll[6])},
                eye_height    = tonumber(fields.eye_height) or 0.5,
                visual_size   = {x=tonumber(vis[1]),y=tonumber(vis[2]),z=tonumber(vis[3])},
                step_height = fields.step_height
            })
            local pos = player:get_pos()
            player:set_pos({x = pos.x,y = pos.y+1,z = pos.z})
            shapetester.sparks(player)
            player:set_physics_override({gravity = fields.gravity or 1,speed = fields.speed or 1,jump = fields.jump or 1})
            core.sound_play(default_shapeshift_sound, {gain = 0.4,max_hear_distance = 16})
            core.close_formspec(player:get_player_name(), "shapetester:shapeshift_tech_menu")
            if fields.hand then
                sethand(player,fields.hand)
            end
        end
        if fields.save then
            local coll = fields.collision:split(" ")
            local vis = fields.visual_size:split(" ")
            shapetester.last_content = {
                textures      = { fields.image },
                visual        = "mesh",
                mesh          = fields.model,
                collisionbox  = {tonumber(coll[1]),tonumber(coll[2]),tonumber(coll[3]),tonumber(coll[4]),tonumber(coll[5]),tonumber(coll[6])},
                eye_height    = tonumber(fields.eye_height) or 0.5,
                visual_size   = {x=tonumber(vis[1]),y=tonumber(vis[2]),z=tonumber(vis[3])},
                gravity = tonumber(fields.gravity),
                speed = tonumber(fields.speed),
                jump = tonumber(fields.jump),
                hand = fields.hand,
                stepheight = fields.step_height
            }
            core.close_formspec(player:get_player_name(), "shapetester:shapeshift_tech_menu")
            shapetester.show_shapeshift_save_menu(player:get_player_name())
        end
        if fields.load then
            core.close_formspec(player:get_player_name(), "shapetester:shapeshift_tech_menu")
            shapetester.show_shapeshift_load_menu(player:get_player_name())
        end
    end
    if formname == "shapetester:shapeshift_save_menu" then
        if fields.save then
            save_form(fields.filename,shapetester.last_content)
            core.close_formspec(player:get_player_name(), "shapetester:shapeshift_save_menu")
        end
    end
    if formname == "shapetester:shapeshift_load_menu" then
        if fields.load then
            if io.open(core.get_worldpath().."/shapeshifts/"..fields.filename..".lua","r") then
                local data = dofile(core.get_worldpath().."/shapeshifts/"..fields.filename..".lua")
                player:set_properties({
                    textures      = data.textures,
                    visual        = "mesh",
                    mesh          = data.mesh,
                    collisionbox  = data.collisionbox,
                    eye_height    = data.eye_height,
                    visual_size   = data.visual_size,
                    stepheight = data.stepheight
                })
                sethand(player,data.hand)
                local pos = player:get_pos()
                player:set_pos({x = pos.x,y = pos.y+1,z = pos.z})
                if core.settings:get_bool("shapeshift_sparks") == false then
                    --Nothing
                else 
                    shapetester.sparks(player)
                end
                core.sound_play(default_shapeshift_sound, {gain = 0.4,max_hear_distance = 16})
                player:set_physics_override({gravity = data.gravity or 1,speed = data.speed or 1,jump = data.jump or 1})
                core.close_formspec(player:get_player_name(), "shapetester:shapeshift_load_menu")
            else
                core.chat_send_player(player:get_player_name(), "Shapetester -!- File doesn't exist!")
            end
        end
    end
end)