-- Get needed values
local exact_selectionbox = ladders_3d.option('exact_selection_box', false,true)
local walkable_by_default = ladders_3d.option('walkable_by_default',false,true)
local game = ladders_3d.game.id
local log = ladders_3d.log


-- Default nodebox resembles the default “Minetest Game” ladder shape
-- but in 3D.
local default_nodebox = {
    type = 'fixed',
    fixed = {
        { -6/16, -8/16, 6/16, -4/16,  8/16, 8/16 }, -- left
        {  4/16, -8/16, 6/16,  6/16,  8/16, 8/16 }, -- right
        { -7/16,  5/16, 6/16,  7/16,  7/16, 8/16 }, -- top
        { -7/16,  1/16, 6/16,  7/16,  3/16, 8/16 }, -- middle top
        { -7/16, -3/16, 6/16,  7/16, -1/16, 8/16 }, -- middle bottom
        { -7/16, -7/16, 6/16,  7/16, -5/16, 8/16 }, -- bottom
    }
}


-- Get the requested selectionbox, if there is none, get the default
-- selectionbox, except the exact selection box should be used.
local selectionbox = function (requested_selectionbox)
    local selectionbox = requested_selectionbox or {
        type = 'fixed',
        fixed = { { -7/16, -8/16, 6/16, 7/16, 8/16, 8/16 } }
    }
    if exact_selectionbox then
        return nil
    else
        return selectionbox
    end
end


-- Register a ladder
--
-- {
--   description = 'My Cool Ladder'
--   recipe = {},
--   yield = 7,
--   uncraft = '',
--   tiles = {},
--   sounds = {},
--   light = 0,
--   groups = {},
--   nodebox = {},
--   selectionbox = {},
--   walkable = false,
--   parameters = {}
-- }
--
-- @return string The full ID of the registered ladder
ladders_3d.register = function (short_id, definition)
    local ladder_id = 'ladders_3d:'..short_id

    -- Node parameters
    local parameters = {
        description = definition.description or ladder_id,
        tiles = definition.tiles,
        drawtype = 'nodebox',
        paramtype = 'light',
        node_box = definition.nodebox or default_nodebox,
        selection_box = selectionbox(definition.selectionbox),
        climbable = true,
        walkable = definition.walkable or not walkable_by_default,
        sounds = definition.sounds,
        groups = definition.groups,
        wield_image = definition.image,
        inventory_image = definition.image,
        paramtype2 = 'facedir',
        light_source = definition.light or 0,
    }

    -- Adding extra parameters
    for parameter,value in pairs(definition.parameters or {}) do
        parameters[parameter] = value
    end

    -- Register the node
    core.register_node(':'..ladder_id, parameters)

    -- Register recipe if available
    if definition.recipe then
        core.register_craft({
            output = ladder_id..' '..(definition.yield or 7),
            recipe = definition.recipe
        })
    end

    -- Register “uncrafting recipe” if available
    if definition.uncraft then
        core.register_craft({
            type = 'shapeless',
            output = definition.uncraft,
            recipe = { ladder_id }
        })
    end

    -- Return the ID of the registered ladder
    return ladder_id
end


-- Mass register ladders from a table
--
-- The following table needs to be provided in order to register multiple
-- ladders in one go. All entries except `ladders` are optional and will
-- fall back to default values.
--
-- {
--   groups = {},  -- Groups for the registered ladders
--   nodebox = {}, -- Nodebox for the registered ladders
--   sounds = {},  -- Fallback SimpleSoundSpec
--   shading = 32, -- Strength of the shading mask
--   ladders = {}  -- Table of ladder definitions
-- }
--
-- The `ladders` entry in that table is a table of ladders to register. All
-- entries in the individual ladder tables are mandatory.
--
-- ladders = {
--   my_cool_id = { 'Name',       'mymod:mynode',      'mymod_texture.png' },
--   the_second = { 'Cool Name',  'crafting:material', 'base_texture.png' },
--   other_id =   { 'Other Name', 'other:material',    'other_texture.png' },
--   -- ... and so on
-- }
--
-- The table entry ID will be expanded to `ladders_3d_THE_ID` where `THE_ID`
-- is the table entry ID (e.g. `ladders_3d:my_cool_id`).
--
-- The function assumes the following files to be existing and looking like
-- it’s needed for the game `GAME` (which will always be the currently
-- active game).
--
-- * `ladders_3d_GAME_inventory_mask.png`
-- * `ladders_3d_GAME_shading_mask.png`
--
-- If the crafting material in the ladders table (second entry) does not
-- have a sounds definition attached, the function tries to use the provided
-- SimpleSoundSpec `sounds`.
--
-- @param ladders The table as described
-- @return table  A table of all registered ladders full IDs
ladders_3d.mass_register = function (ladders)
    local texture_template = '(+base^(+mask^[opacity:+opacity))'
    local image_template = '((+texture)^[mask:+mask)'
    local registered_ladders = {}

    for short_id,def in pairs(ladders.ladders or {}) do

        -- Build texture
        local texture = (texture_template:gsub('%+%w+', {
            ['+base'] = '('..def[3]..')',
            ['+mask'] = 'ladders_3d_'..game..'_shading_mask.png',
            ['+opacity'] = ladders.shading or 32
        }))

        -- Build sounds
        local sounds = (core.registered_items[def[2]] or {}).sounds
        if not sounds then sounds = ladders.sounds end

        local registered_ladder = ladders_3d.register(short_id, {
            description = def[1],
            tiles = { texture },
            groups = ladders.groups,
            sounds = sounds,
            uncraft = def[2]..' 1',
            nodebox = ladders.nodebox and {
                type = 'fixed',
                fixed = ladders.nodebox
            } or nil,
            selectionbox = ladders.selectionbox and {
                type = 'fixed',
                fixed = ladders.selectionbox
            } or nil,
            image = (image_template:gsub('%+%w+', {
                ['+texture'] = texture,
                ['+mask'] = 'ladders_3d_'..game..'_inventory_mask.png'
            })),
            recipe = {
                { def[2], '',     def[2] },
                { def[2], def[2], def[2] },
                { def[2], '',     def[2] }
            }
        })

        table.insert(registered_ladders, registered_ladder)
    end

    return registered_ladders
end
