local mod_name = core.get_current_modname()
local S = core.get_translator(mod_name)

local node_box
if true then
    local pw = 6/16
    local pl = 8/16
    local pa = 4/16
    node_box = {
        type = "fixed",
        fixed = {
            {-pl, -pl,  pa,
              pl,  pl,  pl},
            {-pw, -pw, -pa,
              pw,  pw,  pa},
            {-pa, -pa, -pl,
              pa,  pa, -pa},
        },
    }
end

local function do_push_sound(pos, ndef)
    core.sound_play("aom_machines_piston", {
        pos = pos,
        max_hear_distance = 5,
        gain = 0.1
    })
end

local function do_fail_sound(pos, ndef)
    local sound = ndef.sounds and ndef.sounds.dig
    if not sound then
        sound = aom_sounds.default_stone().dig
    end
    sound = table.copy(sound)
    sound.pos = pos
    core.sound_play(sound.name, sound)
end

local function try_push(pos)
    if aom_wire.get_setting(nil, "wire_max_movable_nodes", 1000) < 1 then
        return false
    end
    local dir = core.facedir_to_dir(core.get_node(pos).param2)
    local to_pos = vector.add(pos, dir)
    local node = core.get_node_or_nil(to_pos)
    if not node then return false end
    local ndef = core.registered_nodes[node.name]

    -- local cl = os.clock()
    local flags = {show_particles=true}
    -- when nothing in front, try to pull instead
    if node.name == "air" then
        to_pos = to_pos + dir
        dir = dir * (-1)
    end
    local movable_info = aom_wire.node_movement.gather_movable_chain(to_pos, dir, flags)
    if aom_wire.node_movement.move_movable_chain(movable_info, flags) then
        do_push_sound(pos)
        -- core.log(os.clock() - cl)
        return true
    end
    -- core.log(os.clock() - cl)
    do_fail_sound(to_pos, ndef)
    core.sound_play("aom_fire_extinguish", {
        pos = pos,
        max_hear_distance = 10,
        gain = 0.1
    })
    return false
end

core.register_node("aom_machines:piston", {
    description = S("Piston"),
    _tt_color = 3,
    _tt_long_desc = S("On wire signal, pushes nodes in front of it. If there is air in front, tries to pull instead.") .. "\n" ..
        S("Adjacent nodes may be pushed if they are welded to the node in front."),
    groups = { cracky = 1, oddly_breakable_by_hand = 2, solid = 1, mechanisms = 1, piston = 1, },
    tiles = {
        "aom_machines_piston_side.png^[transformR90",
        "aom_machines_piston_side.png^[transformR270",
        "aom_machines_piston_side.png",
        "aom_machines_piston_side.png^[transformFX",
        "aom_machines_piston_front.png",
        "aom_machines_piston_back.png",
    },
    sounds = aom_sounds.default_wood(),
    paramtype = "light",
    sunlight_propagates = true,
    paramtype2 = "facedir",
    drawtype = "normal",
    on_place = aom_util.rotate_and_place_against,
    on_timer = function(pos, elapsed)
    end,
    _on_wire_input = function(pos, user, source)
        local uid = aom_wire.update_meta_uid(pos)
        core.after(0.0000001, function()
            if uid ~= aom_wire.get_meta_uid(pos) then return false end
            try_push(pos)
        end)
    end,
    _has_formspec = true,
})

aom_tcraft.register_craft({
    output = "aom_machines:piston",
    items = {
        ["aom_stone:cobble"] = 10,
        ["aom_items:iron_bar"] = 5,
    },
})
