-- streetpipe/init.lua
--
-- Copyright (C) 2025 VerdiSchubert
--
-- This mod is licensed under the GNU General Public License v3.0 (GPLv3)
-- You should have received a copy of the GNU GPL along with this mod.
-- If not, see <https://www.gnu.org/licenses/gpl-3.0.html>.
--
-- This mod may be used, modified and distributed under the terms of the GPLv3.
-- Commercial use is allowed only if the source code remains open under GPLv3.




local get_modpath = minetest.get_modpath
local sound_play = minetest.sound_play
local sound_stop = minetest.sound_stop
local add_particlespawner = minetest.add_particlespawner
local facedir_to_dir = minetest.facedir_to_dir

local has_default_mod = get_modpath("default") ~= nil

-- Константи для node_box
local PIPE_RADIUS = 0.125
local SPOUT_SIZE = 0.0625
local BASE_SIZE = 0.1875

-- Звукові ідентифікатори для активних звуків
local active_sounds = {}

-- Функція для отримання звуків (фолбек)
local function get_sounds()
    if has_default_mod then
        return {
            footstep = {name = "default_hard_footstep", gain = 0.3},
            dig = {name = "default_dig_metal", gain = 0.5},
            dug = {name = "default_dug_metal", gain = 1.0},
            place = {name = "default_place_node_metal", gain = 1.0},
        }
    else
        return {
            footstep = {name = "", gain = 0.0},
            dig = {name = "", gain = 0.0},
            dug = {name = "", gain = 0.0},
            place = {name = "", gain = 0.0},
        }
    end
end

-- Функція створення водяного ефекту (частинки)
local function create_water_effect(pos, node)
    local dir = facedir_to_dir(node.param2)
    local spout_pos = vector.add(pos, vector.multiply(dir, 0.19))
    spout_pos.y = spout_pos.y + 0.44

    -- Основний потік води (без glow)
    add_particlespawner({
        amount = 30,
        time = 1,
        minpos = vector.subtract(spout_pos, vector.new(0.05, 0, 0.05)),
        maxpos = vector.add(spout_pos, vector.new(0.05, 0, 0.05)),
        minvel = vector.new(-0.1, -3, -0.1),
        maxvel = vector.new(0.1, -4, 0.1),
        minacc = vector.new(0, -9.81, 0),
        maxacc = vector.new(0, -9.81, 0),
        minexptime = 1,
        maxexptime = 1.5,
        minsize = 0.8,
        maxsize = 1.2,
        collisiondetection = true,
        collision_removal = true,
        texture = has_default_mod and "default_water.png" or "bubble.png",
        -- glow = 2, -- вимкнено для менш яскравого ефекту
    })

    -- Бризки
    add_particlespawner({
        amount = 10,
        time = 1,
        minpos = vector.subtract(spout_pos, vector.new(0.1, 0, 0.1)),
        maxpos = vector.add(spout_pos, vector.new(0.1, 0, 0.1)),
        minvel = vector.new(-0.7, 0.5, -0.7),
        maxvel = vector.new(0.7, 1, 0.7),
        minacc = vector.new(0, -9.81, 0),
        maxacc = vector.new(0, -9.81, 0),
        minexptime = 0.4,
        maxexptime = 0.8,
        minsize = 0.3,
        maxsize = 0.6,
        texture = has_default_mod and "default_water.png" or "bubble.png",
        vertical = false,
        bounce = 0.3,
    })

    -- Туман/пара
    add_particlespawner({
        amount = 5,
        time = 1,
        minpos = vector.subtract(spout_pos, vector.new(0.2, -0.2, 0.2)),
        maxpos = vector.add(spout_pos, vector.new(0.2, 0, 0.2)),
        minvel = vector.new(-0.1, 0.1, -0.1),
        maxvel = vector.new(0.1, 0.2, 0.1),
        minacc = vector.new(0, 0.1, 0),
        maxacc = vector.new(0, 0.2, 0),
        minexptime = 1,
        maxexptime = 2,
        minsize = 2,
        maxsize = 3,
        texture = has_default_mod and "default_water.png" or "bubble.png",
        alpha = 0.3,
    })
end

-- Запуск потоку води
local function start_water_flow(pos)
    local meta = minetest.get_meta(pos)
    meta:set_string("flowing", "true")
    minetest.get_node_timer(pos):start(0.5)
    meta:set_string("infotext", "Street Water Stand Pipe (flowing)\nRight-click to stop water")

    local pos_str = minetest.pos_to_string(pos)
    if not active_sounds[pos_str] and has_default_mod then
        active_sounds[pos_str] = sound_play("default_water_flowing", {
            pos = pos,
            gain = 0.4,
            max_hear_distance = 10,
            loop = true,
        })
    end
end

-- Зупинка потоку води
local function stop_water_flow(pos)
    local meta = minetest.get_meta(pos)
    meta:set_string("flowing", "false")
    minetest.get_node_timer(pos):stop()
    meta:set_string("infotext", "Street Water Stand Pipe\nRight-click with empty bucket to get water")

    local pos_str = minetest.pos_to_string(pos)
    if active_sounds[pos_str] then
        sound_stop(active_sounds[pos_str])
        active_sounds[pos_str] = nil
    end
end

-- Таймер для створення частинок
local function on_timer(pos, elapsed)
    local node = minetest.get_node(pos)
    local meta = minetest.get_meta(pos)
    if meta:get_string("flowing") == "true" then
        create_water_effect(pos, node)
        return true -- продовжувати таймер
    end
    return false -- зупинити таймер
end

-- Обробка правого кліку
local function on_rightclick(pos, node, clicker, itemstack, pointed_thing)
    local name = itemstack and itemstack:get_name() or ""
    local meta = minetest.get_meta(pos)
    local flowing = meta:get_string("flowing") == "true"

    if name == "bucket:bucket_empty" then
        -- Якщо відро пусте — замінюємо його на повне у тому ж слоті
        create_water_effect(pos, node)
        if has_default_mod then
            sound_play("default_place_node_metal", {
                pos = pos,
                gain = 0.5,
                max_hear_distance = 5
            })
        end
        -- Просто повертаємо новий itemstack
        return ItemStack("bucket:bucket_water")
    else
        -- Якщо без відра — вмикаємо/вимикаємо потік, без зміни ноди
        if flowing then
            stop_water_flow(pos)
        else
            start_water_flow(pos)
        end
        return itemstack
    end
end


-- Реєстрація ноди
minetest.register_node("streetpipe:standpipe", {
    description = "Street Water Stand Pipe",
    drawtype = "nodebox",
    tiles = {has_default_mod and "default_steel_block.png" or "steel_block.png"},
    paramtype = "light",
    paramtype2 = "facedir",
    groups = {cracky = 2, oddly_breakable_by_hand = 1, water_source = 1},
    sounds = get_sounds(),
    light_source = 0,

    node_box = {
        type = "fixed",
        fixed = {
            {-PIPE_RADIUS, -0.5, -PIPE_RADIUS, PIPE_RADIUS, 0.75, PIPE_RADIUS},
            {-PIPE_RADIUS, 0.625, -PIPE_RADIUS, PIPE_RADIUS, 0.75, PIPE_RADIUS},
            {-SPOUT_SIZE, 0.375, PIPE_RADIUS, SPOUT_SIZE, 0.5, PIPE_RADIUS + 0.125},
            {-BASE_SIZE, -0.5, -BASE_SIZE, BASE_SIZE, -0.4375, BASE_SIZE},
            {-PIPE_RADIUS, -0.5, PIPE_RADIUS, PIPE_RADIUS, -0.25, 0.375},
            {-0.03, 0.2, -0.3, 0.03, 0.7, -0.25},
            {-0.03, 0.7, -0.3, 0.03, 0.8, -0.15},
            {-0.15, 0.75, -0.15, 0.15, 0.85, -0.05},
            {-0.05, 0.85, -0.1, 0.05, 0.9, 0.0},
        }
    },

    selection_box = {
        type = "fixed",
        fixed = {-0.25, -0.5, -0.35, 0.25, 1.0, 0.25}
    },

    collision_box = {
        type = "fixed",
        fixed = {-BASE_SIZE, -0.5, -BASE_SIZE, 0.25, 0.75, BASE_SIZE}
    },

    on_rightclick = on_rightclick,
    on_timer = on_timer,

    on_construct = function(pos)
        local meta = minetest.get_meta(pos)
        meta:set_string("infotext", "Street Water Stand Pipe\nRight-click with empty bucket to get water")
        meta:set_string("flowing", "false")
    end,
})

-- Крафт
if has_default_mod then
    minetest.register_craft({
        output = "streetpipe:standpipe",
        recipe = {
            {"", "default:steel_ingot", ""},
            {"default:steel_ingot", "bucket:bucket_water", "default:steel_ingot"},
            {"", "default:steel_ingot", ""}
        }
    })

    if get_modpath("pipes") then
        minetest.register_craft({
            output = "streetpipe:standpipe",
            recipe = {
                {"", "default:steel_ingot", ""},
                {"pipes:pipe", "bucket:bucket_water", "pipes:pipe"},
                {"", "default:steel_ingot", ""}
            }
        })
    end
else
    minetest.register_craft({
        output = "streetpipe:standpipe",
        recipe = {
            {"", "steel_ingot", ""},
            {"steel_ingot", "bucket_water", "steel_ingot"},
            {"", "steel_ingot", ""}
        }
    })
end
