--[[
    X Farming. Extends Minetest farming mod with new plants, crops and ice fishing.
    Copyright (C) 2024 SaKeL

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to juraj.vajda@gmail.com
--]]

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.use_texture_alpha = 'clip'
    def.sounds = x_farming.node_sound_wood_defaults()
    def.paramtype = 'light'
    def.paramtype2 = 'facedir'
    def.place_param2 = 0
    def.is_ground_content = false
    def.groups = {
        -- MTG
        choppy = 2,
        oddly_breakable_by_hand = 2,
        flammable = 2,
        not_in_creative_inventory = 1,
        -- MCL
        handy = 1,
        material_wood = 1,
        deco_block = 1,
        dirtifier = 1,
        fire_encouragement = 3,
        fire_flammability = 4,
    }
    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

        -- fill the composter
        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('x_farming_dirt_hit', { gain = 0.3, pos = pos, max_hear_distance = 10 }, true)

        if not minetest.is_creative_enabled(clicker:get_player_name()) then
            itemstack:take_item()
        end

        return itemstack
    end

    if i == 1 then
        -- empty composter is craftable, so can be in creative inventory
        def.groups = {
            -- MTG
            choppy = 2,
            oddly_breakable_by_hand = 2,
            -- MCL
            handy = 1,
            material_wood = 1,
            deco_block = 1,
            dirtifier = 1,
            fire_encouragement = 3,
            fire_flammability = 4,
            -- ALL
            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('x_farming_dirt_hit', { gain = 0.3, pos = pos, max_hear_distance = 10 }, true)
            -- drop bonemeal
            minetest.add_item(
                vector.new(drop_pos.x, drop_pos.y + 1, drop_pos.z),
                ItemStack({ name = 'x_farming:bonemeal', count = math.random(1, 2) })
            )
            -- swap to beginning
            minetest.swap_node(pos, { name = 'x_farming:composter_1' })
            -- reset status
            meta:set_int('composter_status', 0)
        end
    end

    -- MCL
    def._mcl_hardness = 0.6
    def._mcl_blast_resistance = 0.6

    minetest.register_node(def.name, def)
end
