--[[
    X Farming. Extends Luanti farming mod with new plants, crops and ice fishing.
    Copyright (C) 2025 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 = core.get_translator(core.get_current_modname())

x_farming.register_plant('x_farming:rice', {
    description = S('Rice Seed') .. '\n' .. S('Compost chance') .. ': 30%',
    short_description = S('Rice Seed'),
    tiles = { 'x_farming_silt_loam_soil.png' },
    inventory_image = 'x_farming_rice_seed_inv.png',
    steps = 8,
    minlight = 13,
    maxlight = 14,
    fertility = { 'grassland' },
    drawtype = 'plantlike_rooted',
    paramtype2 = 'none',
    visual_scale = 3.0,
    special_tiles = 'x_farming_rice_seed.png',
    node_dig_prediction = 'x_farming:silt_loam_soil',
    groups = {
        -- MTG
        attached_node = 0,
        -- VL
        plant = 1,
        dig_by_water = 0,
        destroy_by_lava_flow = 1,
        dig_by_piston = 1,
        compostability = 30,
        -- X Farming
        compost = 30,
    },
    node_placement_prediction = '',
    buildable_to = false,
    floodable = false,
    selection_box = {
        type = 'fixed',
        fixed = {
            { -0.5, -0.5, -0.5, 0.5, 0.5, 0.5 },
            { -4 / 16, 0.5, -4 / 16, 4 / 16, 1.5, 4 / 16 },
        },
    },
    selection_box_1 = {
        type = 'fixed',
        fixed = {
            { -0.5, -0.5, -0.5, 0.5, 0.5, 0.5 },
            { -4 / 16, 0.5, -4 / 16, 4 / 16, 1.5, 4 / 16 },
        },
    },
    selection_box_2 = {
        type = 'fixed',
        fixed = {
            { -0.5, -0.5, -0.5, 0.5, 0.5, 0.5 },
            { -4 / 16, 0.5, -4 / 16, 4 / 16, 1.5, 4 / 16 },
        },
    },
    selection_box_3 = {
        type = 'fixed',
        fixed = {
            { -0.5, -0.5, -0.5, 0.5, 0.5, 0.5 },
            { -4 / 16, 0.5, -4 / 16, 4 / 16, 2, 4 / 16 },
        },
    },
    selection_box_4 = {
        type = 'fixed',
        fixed = {
            { -0.5, -0.5, -0.5, 0.5, 0.5, 0.5 },
            { -4 / 16, 0.5, -4 / 16, 4 / 16, 2.5, 4 / 16 },
        },
    },
    selection_box_5 = {
        type = 'fixed',
        fixed = {
            { -0.5, -0.5, -0.5, 0.5, 0.5, 0.5 },
            { -4 / 16, 0.5, -4 / 16, 4 / 16, 2.5, 4 / 16 },
        },
    },
    selection_box_6 = {
        type = 'fixed',
        fixed = {
            { -0.5, -0.5, -0.5, 0.5, 0.5, 0.5 },
            { -4 / 16, 0.5, -4 / 16, 4 / 16, 3, 4 / 16 },
        },
    },
    selection_box_7 = {
        type = 'fixed',
        fixed = {
            { -0.5, -0.5, -0.5, 0.5, 0.5, 0.5 },
            { -4 / 16, 0.5, -4 / 16, 4 / 16, 3, 4 / 16 },
        },
    },
    selection_box_8 = {
        type = 'fixed',
        fixed = {
            { -0.5, -0.5, -0.5, 0.5, 0.5, 0.5 },
            { -4 / 16, 0.5, -4 / 16, 4 / 16, 3, 4 / 16 },
        },
    },
    on_place = function(itemstack, placer, pointed_thing)
        if pointed_thing.type ~= 'node' or not placer then
            return itemstack
        end

        local player_name = placer:get_player_name()
        local pos_under = pointed_thing.under
        local pos_above = pointed_thing.above
        local node_under = core.get_node(pos_under)
        local def_under = core.registered_nodes[node_under.name]

        if def_under and def_under.on_rightclick and not placer:get_player_control().sneak then
            return def_under.on_rightclick(pos_under, node_under, placer, itemstack, pointed_thing) or itemstack
        end

        local water_above = core.find_nodes_in_area(
            vector.new(pos_above),
            vector.new(pos_above.x, pos_above.y + 2, pos_above.z),
            { 'group:water' }
        )

        if node_under.name ~= 'x_farming:silt_loam_soil'
            or core.get_item_group(core.get_node(pos_above).name, 'water') == 0
            or #water_above ~= 1
        then
            return itemstack
        end

        if core.is_protected(pos_under, player_name)
            or core.is_protected(pos_above, player_name)
        then
            core.record_protection_violation(pos_under, player_name)
            return itemstack
        end

        node_under.name = itemstack:get_name()
        core.set_node(pos_under, node_under)
        x_farming.tick(pos_under)

        if not core.is_creative_enabled(player_name) then
            itemstack:take_item()
        end

        return itemstack
    end,
    after_destruct = function(pos, oldnode)
        core.set_node(pos, { name = 'x_farming:silt_loam_soil' })
    end,
    on_timer = function(pos, elapsed)
        local node = core.get_node(pos)
        local name = node.name
        local def = core.registered_nodes[name]

        if not def.next_plant then
            -- disable timer for fully grown plant
            return
        end

        -- grow seed
        if core.get_item_group(node.name, 'seed') and def.fertility then
            local water_above = core.find_nodes_in_area(
                vector.new(pos),
                vector.new(pos.x, pos.y + 2, pos.z),
                { 'default:water_source' }
            )

            if #water_above ~= 1 then
                x_farming.tick_again(pos)
                return
            end
            -- omitted is a check for light, we assume seeds can germinate in the dark.
            local placenode = { name = def.next_plant }

            if def.place_param2 then
                placenode.param2 = def.place_param2
            end

            core.swap_node(pos, placenode)

            if core.registered_nodes[def.next_plant].next_plant then
                x_farming.tick(pos)
                return
            end

            return
        end

        -- check if emerged in water
        local water_above = core.find_nodes_in_area(
            vector.new(pos),
            vector.new(pos.x, pos.y + 2, pos.z),
            { 'default:water_source' }
        )

        local air_above = core.find_nodes_in_area(
            vector.new(pos),
            vector.new(pos.x, pos.y + 3, pos.z),
            { 'air' }
        )

        if #water_above ~= 1 or #air_above ~= 2 then
            x_farming.tick_again(pos)
            return
        end

        -- check light
        local light = core.get_node_light(pos)

        if not light or light < def.minlight or light > def.maxlight then
            x_farming.tick_again(pos)
            return
        end

        -- grow
        local placenode = { name = def.next_plant }

        if def.place_param2 then
            placenode.param2 = def.place_param2
        end

        core.swap_node(pos, placenode)

        -- new timer needed?
        if core.registered_nodes[def.next_plant].next_plant then
            x_farming.tick(pos)
        end
    end
})

-- Registered before the stairs so the stairs get fuel recipes.
core.register_craft({
    type = 'fuel',
    recipe = 'x_farming:rice_stack',
    burntime = 3,
})

if core.get_modpath('stairs') then
    do
        local recipe = 'x_farming:rice'
        local groups = { snappy = 3, flammable = 4 }
        local images = { 'x_farming_rice_stack_side.png' }
        local sounds = x_farming.node_sound_leaves_defaults()

        stairs.register_stair('rice_stack', recipe, groups, images, S('Rice Stack Stair'),
            sounds, true)
        stairs.register_stair_inner('rice_stack', recipe, groups, images, '',
            sounds, true, S('Inner Rice Stack Stair'))
        stairs.register_stair_outer('rice_stack', recipe, groups, images, '',
            sounds, true, S('Outer Rice Stack Stair'))
        stairs.register_slab('rice_stack', recipe, groups, images, S('Rice Stack Slab'),
            sounds, true)
    end
end

-- crate
x_farming.register_crate('crate_rice_3', {
    description = S('Rice Crate'),
    short_description = S('Rice Crate'),
    tiles = { 'x_farming_crate_rice_3.png' },
    _custom = {
        crate_item = 'x_farming:rice'
    }
})

-- bag
x_farming.register_bag('bag_rice_grains', {
    description = S('Rice Grain') .. ' Bag',
    short_description = S('Rice Grain') .. ' Bag',
    tiles = { 'x_farming_bag_rice_grains.png' },
    _custom = {
        bag_item = 'x_farming:rice_grains'
    }
})

core.register_on_mods_loaded(function()
    local deco_place_on = {}
    local deco_biomes = {}

    -- MTG
    if core.get_modpath('default') then
        table.insert(deco_place_on, 'default:dirt')
        table.insert(deco_place_on, 'default:dry_dirt')
        table.insert(deco_biomes, 'rainforest_swamp')
        table.insert(deco_biomes, 'savanna_shore')
    end

    -- MCL
    if core.get_modpath('mcl_core') then
        table.insert(deco_place_on, 'mcl_core:sand')
        table.insert(deco_biomes, 'Savanna_beach')
    end

    if next(deco_place_on) and next(deco_biomes) then
        core.register_decoration({
            name = 'x_farming:rice',
            deco_type = 'simple',
            place_on = deco_place_on,
            sidelen = 16,
            noise_params = {
                offset = -0.3,
                scale = 0.7,
                spread = { x = 200, y = 200, z = 200 },
                seed = 354,
                octaves = 3,
                persist = 0.7
            },
            biomes = deco_biomes,
            y_max = -1,
            y_min = -1,
            decoration = {
                'x_farming:rice_5',
                'x_farming:rice_6',
                'x_farming:rice_7',
                'x_farming:rice_8'
            },
            flags = 'force_placement'
        })
    end
end)
