local mod_name = minetest.get_current_modname()
local mod_path = minetest.get_modpath(mod_name)
local S = minetest.get_translator(mod_name)


local function put_entity(pos)
    local obj = minetest.add_entity(pos, "pmb_seelie:seelie_shrine_ENTITY")
    return obj
end

local function get_entity_from_pos(pos)
    local objs = minetest.get_objects_in_area(
        vector.offset(pos, -0.5, -0.5, -0.5),
        vector.offset(pos,  0.5,  0.5,  0.5)
    )
    for i, obj in ipairs(objs) do
        local ent = obj and obj:get_luaentity()
        if ent and ent.name == "pmb_seelie:seelie_shrine_ENTITY" then
            return ent
        end
    end
end


local function randrange(s, e)
    return math.random() * (e-s) + s
end

local jitter = {
    min = vector.new(-0.5,-0.3,-0.5),
    max = vector.new( 0.5, 0.3, 0.5)
}
local function add_particles(self)
    local d = 2
    local v = 0.2
    -- self._particleid = 
    local p = self.object:get_pos()
    if not p then return end
    minetest.add_particle({
        pos = p + vector.new(
            randrange(-d, d),
            randrange(-d/2, d),
            randrange(-d, d)
        ),
        jitter = jitter,
        size = randrange(0.2, 0.8),
        glow = randrange(4, 8),
        expirationtime = randrange(20, 40),
        texture = "pmb_seelie_shrine_particle.png",
    })
end

local function add_particlespawners(self)
    local drag = vector.new(0.28, 0.28, 0.28)
    local pos = self.object:get_pos()
    minetest.add_particlespawner({
        amount = 30,
        time = 12,
        collisiondetection = false,
        collision_removal = false,
        object_collision = false,
        attached = self.object, -- to object ref
        vertical = false, -- If true face player using y axis only:-- If true face player using y axis only:
        texture = "pmb_seelie_shrine_particle.png",
        glow = 8,
        drag = {
            min = drag,
            max = drag
        },
        attract = {
            kind = "point",
            strength = {
                min = 0.39,
                max = 0.39,
            },
            origin = vector.offset(pos, 0, 0.4, 0),
            -- origin_attached = self.object,
            die_on_contact = false,
        },
        radius = {
            min = 2,
            max = 3,
        },
        minexptime = 4.4,
        maxexptime = 4.4,
        minsize = 0.1,
        maxsize = 0.5,
    })

    minetest.after(1, function ()
        minetest.sound_play("pmb_seelie_inhabit", {
            gain = 0.6,
            pos = pos,
        }, true)
    end)
end



----------------------------
--------NODE DEF
----------------------------

minetest.register_node("pmb_seelie:seelie_shrine", {
    description = S("Seelie Shrine"),
    _tt_color = 4,
    _tt_long_desc = S("Prevents mobs from spawning nearby."),
    groups = { item_cooking_pot = 1, solid = 0, furniture = 1, oddly_breakable_by_hand = 2, cracky = 1, },
    drawtype = "mesh",
    use_texture_alpha = "opaque",
    paramtype = "light",
    tiles = {
        "[combine:32x32:0,0=pmb_seelie_shrine.png:9,9=pmb_stone_cobble.png",
    },
    collision_box = {
        type = "fixed",
        fixed = {
            -0.3, -0.5, -0.3,
            0.3,  0.5,  0.3
        }
    },
    selection_box = {
        type = "fixed",
        fixed = {
            -0.3, -0.5, -0.3,
            0.3,  0.5,  0.3
        }
    },
    mesh = "pmb_seelie_shrine.b3d",
    inventory_image = "pmb_seelie_shrine_inv_image.png",
    sounds = (pmb_sounds and pmb_sounds.default_stone()) or {},
    -- light_source = 2,
    on_timer = function(pos, elapsed)
        -- check the entity part is still there
        local ent = get_entity_from_pos(pos)

        -- keep timer going
        if ent then return true end

        put_entity(pos)
        return true
    end,
    on_construct = function(pos)
        local obj = put_entity(pos)
        local ent = obj and obj:get_luaentity()
        if ent then
            add_particlespawners(ent)
        end
        minetest.get_node_timer(pos):start(5)
    end,
    on_destruct = function(pos)
        local ent = get_entity_from_pos(pos)
        if ent then
            ent.object:remove()
        end
    end,
    on_punch = function(pos, node, clicker, itemstack, pointed_thing)
    end,
    on_rightclick = function(pos, node, clicker, itemstack, pointed_thing)
        return itemstack
    end,
})

minetest.register_alias("pmb_spawn_inhibitors:seelie_shrine", "pmb_seelie:seelie_shrine")





----------------------------
--------ENTITY DEF
----------------------------

local box_w = 40
local off_y = 20

local csize = 0.2
minetest.register_entity("pmb_seelie:seelie_shrine_ENTITY", {
    initial_properties = {
        visual = "mesh",
        mesh = "pmb_seelie_shrine_orb.b3d",
        textures = {"pmb_seelie_shrine_orb.png"},
        stepheight = 0,
        hp_max = 1,
        physical = false,
        pointable = false,
        backface_culling = false,
        glow = 12,
        collisionbox = {
            -csize, -csize, -csize, csize, csize, csize,
        },
        selectionbox = {
            -csize, -csize, -csize, csize, csize, csize,
        },
    },
    on_step = function(self, dtime)
        self._timer = (self._timer or 1) + dtime
        if self._timer < 1 then return end
        self._timer = self._timer - 1

        local pos = self.object:get_pos()

        if not pos then
            self.object:remove()
            return
        end

        local node = minetest.get_node(pos)
        if node.name ~= "pmb_seelie:seelie_shrine" then
            self.object:remove()
            return
        end

        local p = vector.offset(pos, 0, 1, 0)
        local n = minetest.get_node_or_nil(p)
        if n and n.name == "pmb_util:light_node_3" then
            minetest.get_node_timer(p):set(3,0)
        else
            local ndef = n and minetest.registered_nodes[n.name]
            if ndef and ndef.buildable_to then
                minetest.set_node(p, {name="pmb_util:light_node_3"}, true)
            end
        end


        if self._sleeping then return end
        self._iter = (self._iter or -1) + 1

        if self._iter % self._nearby_check_freq == 0 then
            if #pmb_entity_api.get_objects_of_type(self.object:get_pos(), 0.5, {[self.name]=true}) > 1 then
                self.object:remove() return
            end
            -- don't make any particles or search for nearby if not natural node below
            n = minetest.get_node(vector.offset(p, 0, -2, 0))
            if minetest.get_item_group(n.name or "air", "nature") == 0 then
                self._sleeping = true
                return
            end
            self._nearby_check_freq = math.random(10,20)
            self._nearby_count = #pmb_entity_api.get_objects_of_type(self.object:get_pos(), 20, {[self.name]=true})
        end

        if self._iter % 3 == 0 then
            if math.random() * self._nearby_count * 0.2 < 1 then
                add_particles(self)
            end
        end
    end,
    on_activate = function(self, staticdata, dtime_s)
        pmb_entity_api.on_activate(self, staticdata, dtime_s)
        self.object:set_animation({x=0, y=120}, 24, 0, true)
        add_particles(self)
    end,
    on_deactivate = function(self, removal)
        local p = vector.offset(self.object:get_pos(), 0, 1, 0)
        if minetest.get_node(p).name == "pmb_util:light_node_3" then
            minetest.set_node(p, {name="air"})
        end
    end,
    get_staticdata = function(self)
        return pmb_entity_api.get_staticdata(self)
    end,
    _is_position_uninhibited = function(self, pos)
        -- get position relative to this spawn inhibitor
        local p = pos - self.object:get_pos()
        if p.x < -box_w or p.y < -box_w+off_y or p.z < -box_w
        or p.x >  box_w or p.y >  box_w+off_y or p.z >  box_w then
            return true
        end
        return false
    end,
    _nearby_check_freq = 5,
    _pmb_staticdata_load_list = {
        "_nearby_check_freq",
        "_nearby_count",
    },
})

if minetest.get_modpath("pmb_spawn_inhibitors") ~= nil then
    pmb_spawn_inhibitors.register_inhibitor_entity("pmb_seelie:seelie_shrine_ENTITY", 50)
end


-- TODO: add crafting recipe that is easy to obtain items for, but not silly levels of easy like the following:
pmb_tcraft.register_craft({
    output = "pmb_seelie:seelie_shrine",
    items = {
        ["pmb_stone:cobble"] = 4,
        ["pmb_items:tin_nugget"] = 1,
    }
})






