local S = minetest.get_translator(minetest.get_current_modname())

local function particle_effect(pos)
    minetest.add_particlespawner({
        amount = 8,
        time = 2,
        minpos = { x = pos.x - 0.4, y = pos.y + 0.4, z = pos.z - 0.4 },
        maxpos = { x = pos.x + 0.4, y = pos.y + 0.6, z = pos.z + 0.4 },
        minvel = { x = -0.1, y = 0, z = -0.1 },
        maxvel = { x = 0.1, y = 0.1, z = 0.1 },
        minacc = vector.new({ x = -0.1, y = 0, z = -0.1 }),
        maxacc = vector.new({ x = 0.1, y = 0.1, z = 0.1 }),
        minexptime = 1,
        maxexptime = 2,
        minsize = 1,
        maxsize = 2,
        texture = 'x_farming_x_bonemeal_particles.png',
        animation = {
            type = 'vertical_frames',
            aspect_w = 8,
            aspect_h = 8,
            length = 3,
        },
    })
end

for i = 1, 5, 1 do
    local def = {}

    def.name = 'x_farming:composter_' .. i
    def.description = S('Composter') .. ' ' .. i
    def.short_description = S('Composter') .. ' ' .. i
    def.drawtype = 'mesh'
    def.mesh = 'x_farming_crate.obj'
    def.tiles = { 'x_farming_composter_' .. i .. '.png' }
    def.sounds = default.node_sound_wood_defaults()
    def.paramtype = 'light'
    def.paramtype2 = 'facedir'
    def.place_param2 = 0
    def.is_ground_content = false
    def.groups = { choppy = 2, oddly_breakable_by_hand = 2, flammable = 2, not_in_creative_inventory = 1 }
    def.stack_max = 1
    def.mod_origin = 'x_farming'
    def.drop = 'x_farming:composter_1'
    def.on_rightclick = function(pos, node, clicker, itemstack, pointed_thing)
        local p_name = clicker:get_player_name()

        if minetest.is_protected(pos, p_name) then
            return itemstack
        end

        local wield_stack = clicker:get_wielded_item()
        local wield_stack_name = wield_stack:get_name()

        -- percentage, higher = better, max 100%
        local chance = 0

        if minetest.get_item_group(wield_stack_name, 'compost') > 0 then
            -- defined in groups, e.g. `{ compost = 10 }`
            chance = minetest.get_item_group(wield_stack_name, 'compost')
        elseif minetest.get_item_group(wield_stack_name, 'food_bread') == 1
            or minetest.get_item_group(wield_stack_name, 'wool') == 1
            or node.name == 'farming:straw'
        then
            chance = 85
        elseif minetest.get_item_group(wield_stack_name, 'flora') == 1
            or minetest.get_item_group(wield_stack_name, 'food_apple') == 1
            or minetest.get_item_group(wield_stack_name, 'fern') == 1
            or minetest.get_item_group(wield_stack_name, 'food_wheat') == 1
            or minetest.get_item_group(wield_stack_name, 'food_flour') == 1
            or minetest.get_item_group(wield_stack_name, 'mushroom') == 1
            or minetest.get_item_group(wield_stack_name, 'flower') == 1
        then
            chance = 65
        elseif minetest.get_item_group(wield_stack_name, 'marram_grass') == 1
            or minetest.get_item_group(wield_stack_name, 'junglegrass') == 1
            or node.name == 'default:cactus'
            or node.name == 'default:coral_green'
            or node.name == 'default:coral_pink'
            or node.name == 'default:coral_cyan'
        then
            chance = 50
        elseif minetest.get_item_group(wield_stack_name, 'leaves') == 1
            or minetest.get_item_group(wield_stack_name, 'seed') == 1
            or minetest.get_item_group(wield_stack_name, 'grass') == 1
            or minetest.get_item_group(wield_stack_name, 'snappy') == 3
            or minetest.get_item_group(wield_stack_name, 'sapling') == 1
            or minetest.get_item_group(wield_stack_name, 'food_blueberries') == 1
            or minetest.get_item_group(wield_stack_name, 'food_berry') == 1
            or node.name == 'default:sand_with_kelp'
            or node.name == 'default:large_cactus_seedling'
        then
            chance = 30
        end

        if chance == 0 then
            return itemstack
        end

        if math.random() < chance / 100 then
            local meta = minetest.get_meta(pos)
            local prev_status = meta:get_int('composter_status')
            local status = prev_status + 10

            if status > 100 then
                status = 100
            end

            meta:set_int('composter_status', status)

            local node_def = minetest.registered_nodes[node.name]

            if math.fmod(status, 50) == 0 and node_def._next_state then
                local placenode = { name = node_def._next_state }

                minetest.swap_node(pos, placenode)
                particle_effect(pos)

                if i == 3 then
                    -- placed nr 4
                    minetest.get_node_timer(pos):start(math.random(1, 2))
                end
            elseif i == 1 then
                -- convert to visual 1st level
                minetest.swap_node(pos, { name = 'x_farming:composter_2' })
                particle_effect(pos)
            end
        end

        minetest.sound_play('default_dig_crumbly', { gain = 0.3, pos = pos, max_hear_distance = 10 }, true)

        return itemstack
    end

    if i == 1 then
        -- empty composter is craftable, so can be in creative inventory
        def.groups = { choppy = 2, oddly_breakable_by_hand = 2, flammable = 2 }
        def.description = S('Composter') .. ' (' .. S('right-click/place with item to create compost') .. ')'
        def.short_description = S('Composter')
    end

    if i < 4 then
        -- all except the last
        def._next_state = 'x_farming:composter_' .. i + 1
    end

    if i == 4 then
        def.on_rightclick = function(pos, node, clicker, itemstack, pointed_thing)
            -- do nothing
        end

        -- last step
        def.on_timer = function(pos, elapsed)
            minetest.swap_node(pos, { name = 'x_farming:composter_5' })
        end
    end

    if i == 5 then
        def.on_rightclick = function(pos, node, clicker, itemstack, pointed_thing)
            local p_name = clicker:get_player_name()

            if minetest.is_protected(pos, p_name) then
                return itemstack
            end

            local meta = minetest.get_meta(pos)
            local above = vector.new(pos.x, pos.y + 0.5, pos.z)
            local drop_pos = minetest.find_node_near(above, 0.5, { 'air' }) or above

            minetest.sound_play('default_dig_crumbly', { gain = 0.3, pos = pos, max_hear_distance = 10 }, true)
            -- drop bonemeal
            minetest.item_drop(ItemStack({ name = 'x_farming:bonemeal' }), nil, drop_pos)
            -- swap to beginning
            minetest.swap_node(pos, { name = 'x_farming:composter_1' })
            -- reset status
            meta:set_int('composter_status', 0)
        end
    end

    minetest.register_node(def.name, def)
end
