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

dofile(mod_path .. DIR_DELIM .. "spawning.lua")

pmb_kelar = {}
function pmb_kelar.do_sound(self, name, gain)
    minetest.sound_play(("pmb_kelar_"..name), {
        gain = gain or 1,
        pos = self.object:get_pos(),
        object = self.object,
        pitch = (math.random()*0.2) + 0.9
    })
end

local kelar = {
    initial_properties = {
        visual = "mesh",
        mesh = "kelar.b3d",
        textures = {"kelar.png"},
        use_texture_alpha = false,
        stepheight = 0.5,
        hp_max = 20,
        physical = true,
        collisionbox = {-0.3, -0.5, -0.3, 0.3, 1, 0.3},
        selectionbox = {-0.3, -0.5, -0.3, 0.3, 1, 0.3},
        pointable = true,
        damage_texture_modifier = "^[colorize:#ff9999:50",
    },
    _name = "pmb_kelar:kelar",


    on_step = pmb_entity_api.do_states(),
    _drop = {
        max_items = 2,
        items = {
            {
                rarity = 4,
                items = {"pmb_items:copper_nugget"},
            },
            {
                rarity = 4,
                items = {"pmb_items:iron_nugget"},
            },
            {
                rarity = 4,
                items = {"pmb_items:tin_nugget"},
            },
            {
                rarity = 4,
                items = {"pmb_stone:cobble"},
            },
        }
    },
    on_death = function(self, killer)
        if killer then
            pmb_entity_api.do_drops(self)
            for i=1, 10 do
                minetest.add_particle({
                    pos = self.object:get_pos(),
                    velocity = vector.new((math.random()-0.5)*3, (math.random())*2, (math.random()-0.5)*3),
                    expirationtime = math.random(),
                    size = math.random() * 2 + 2,
                    collisiondetection = false,
                    vertical = false,
                    texture = "kelar_particle.png",
                })
            end
        end
    end,

    _states = {
        on_step = function(self, dtime, moveresult)
            pmb_entity_api.test_fall_damage(self, dtime, false)
            if not self.object:get_pos() then
                return "die"
            end
            if self._state ~= "death" then
                local in_or_above_water = pmb_entity_api.float_in_liquids(self, dtime * 20, {offset=vector.new(0, 1.2, 0)})
                if not in_or_above_water then
                    pmb_entity_api.apply_gravity(self, dtime)
                end
            end
        end,
        idle = {
            animation = "idle",
            step = function(self, dtime, moveresult)

                pmb_entity_api.get_target(self)
                pmb_entity_api.get_wander(self, 300)
                pmb_entity_api.decelerate(self, 0.8)

                if self._pmb_to_pos and self._pmb_state_time > 1 then
                    return "charge"
                end
            end,
        },
        charge = {
            -- animation = "charge",
            step = function(self, dtime, moveresult)
                if not self._pmb_attack_cooldown then self._pmb_attack_cooldown = 2 end
                if self._pmb_attack_cooldown > 0 then self._pmb_attack_cooldown = self._pmb_attack_cooldown - dtime end

                pmb_entity_api.decelerate(self, 0.9)

                local tmp_vel = self.object:get_velocity()
                tmp_vel.y = 0
                if vector.length(tmp_vel) > 0.2 then
                    pmb_entity_api.set_my_animation(self, "charge")
                else
                    pmb_entity_api.set_my_animation(self, "idle")
                end

                -- no target or target pos
                if (not self._pmb_path) and (not self._pmb_target) then
                    return "idle"
                elseif not pmb_entity_api.path_reachable(self) then
                    self._pmb_path = {}
                    return "idle"
                end

                local dist = pmb_entity_api.get_target_dist(self)
                if (self._pmb_target and dist and dist > 5) then
                    pmb_entity_api.get_and_follow_target(self, 1)
                elseif not self._pmb_target then
                    pmb_entity_api.get_and_follow_target(self)
                end

                pmb_entity_api.check_jump(self, 5)

                if (not self._pmb_to_pos) and (not self._pmb_target) then return "idle" end

                if dist and dist < 5 then
                    pmb_entity_api.rotate_to_target(self, dtime*8)
                else
                    pmb_entity_api.rotate_to_path(self, dtime*8)
                end

                if pmb_entity_api.has_los_to_object(self, self._pmb_target) then
                    pmb_entity_api.punch_in_radius(self, 1, 2)
                elseif self._pmb_state_time > 1 then
                    return "idle"
                end

                if (dist and dist > 50) or self._pmb_state_time > 1 then
                    pmb_entity_api.get_target(self)
                end

                if self._pmb_attack_cooldown <= 0 and dist and dist < 7 then
                    -- pmb_entity_api.do_path(self, 0)
                    self._pmb_attack_cooldown = nil
                    local vel = self.object:get_velocity()
                    vel.x = 0
                    vel.z = 0
                    self.object:set_velocity(vel)
                    return "pre_lunge"
                end
            end,
        },
        pre_lunge = {
            animation = "idle",
            on_state_start = function(self)
            end,
            step = function(self, dtime, moveresult)
                if not self._pmb_target then
                    pmb_entity_api.get_target(self)
                end
                if not self._pmb_path then
                    pmb_entity_api.get_path(self, pmb_entity_api.min_cost)
                end
                pmb_entity_api.rotate_to_target(self, dtime*3)
                if not self._pmb_lunge_time then self._pmb_lunge_time = 0.5 end
                if self._pmb_lunge_time > 0 then self._pmb_lunge_time = self._pmb_lunge_time - dtime end

                if self._pmb_lunge_time <= 0 then
                    self._pmb_lunge_time = nil
                    return "lunge"
                end
            end,
        },
        lunge = {
            animation = "lunge",
            on_state_start = function(self)
                pmb_kelar.do_sound(self, "lunge_"..(math.random(0,3)), 1)
                self._pmb_path = nil
                self._pmb_to_pos = nil
            end,
            step = function(self, dtime, moveresult)
                if not self._pmb_attack_time then self._pmb_attack_time = 1
                else self._pmb_attack_time = self._pmb_attack_time - dtime end

                if self._pmb_attack_time == 1 then
                    if not self._pmb_target then
                        return "idle"
                    end
                    local target_pos = self._pmb_target:get_pos()
                    local pos = self.object:get_pos()
                    local dir = vector.direction(pos, target_pos)
                    local yaw = minetest.dir_to_yaw(dir)
                    self.object:set_yaw(yaw)
                    dir = vector.multiply(dir, self._pmb_speed * 1.3)
                    dir.y = 4
                    self.object:set_velocity(dir)
                end

                if self._pmb_attack_time <= 0 then
                    self._pmb_attack_time = nil
                    return "charge"
                end

                local dist = pmb_entity_api.get_target_dist(self)
                if self._pmb_since_attack >= 1 and dist and dist < 2
                and pmb_entity_api.has_los_to_object(self, self._pmb_target) then
                    self._pmb_target:punch(self.object, 1.0, {
                        full_punch_interval = 1.0,
                        damage_groups = {
                            blunt=4,
                        }
                    }, nil)
                    self._pmb_since_attack = 0
                end
            end,
        },
    },
    _default_state = "idle",
    on_activate = function(self, staticdata, dtime_s)
        self.object:set_armor_groups({
            pierce=200,
            slash=100,
            blunt=100,
            magic=200,
            poison=100,
        })
        self.object:set_hp(self._pmb_max_health)
        pmb_entity_api.on_activate(self, staticdata, dtime_s)
    end,
    get_staticdata = function(self)
        return pmb_entity_api.get_staticdata(self)
    end,
    on_deactivate = function(self, removal)
        pmb_entity_api.on_deactivate(self, removal)
    end,
    on_punch = function(self, puncher, time_from_last_punch, tool_capabilities, dir, damage)
        if damage and damage > 0 then
            pmb_kelar.do_sound(self, "hurt_0", 1)
            if puncher and puncher ~= self.object and not self._pmb_target then
                self._pmb_target = puncher
                pmb_entity_api.set_state(self, "charge")
            end
        end
        return pmb_entity_api.damage.on_punch(self, puncher, time_from_last_punch, tool_capabilities, dir, damage)
    end,
    _pmb_staticdata_load_list = {
        "_pmb_speed",
        "_pmb_damage_groups",
        "_pmb_hostile",
    },
    _pmb_speed = 5,
    _pmb_acceleration = 20,
    _pmb_gravity = 9,
    _pmb_max_health = 20,
    _pmb_hostile = {player=1},
    _pmb_damage_groups = {
        pierce=2,
        slash=2,
        blunt=1,
    },
    _animations = {
        idle = {frames={x=0, y=39}},
        charge = {frames={x=50, y=69}},
        lunge = {frames={x=50, y=69}, speed = 48}
    },
    _pmb_wander = 3,
    _pmb_range = 20,
    _pmb_statusfx_enable = true,
}


minetest.register_entity("pmb_kelar:kelar", kelar)

local underkelar = table.copy(kelar)
underkelar.initial_properties.textures = {"kelar.png^[multiply:#ffb9b780"}
underkelar.initial_properties.glow = 2
underkelar._pmb_speed = 8
underkelar._pmb_did_variant_check = true
underkelar._drop = {
    max_items = 3,
    items = {
        {
            rarity = 2,
            items = {"pmb_underworld:lava_brick"},
        },
        {
            rarity = 4,
            items = {"pmb_underworld:ash"},
        },
        {
            rarity = 8,
            items = {"pmb_underworld:mythril_strand"},
        },
        {
            rarity = 8,
            items = {"pmb_underworld:mythril_strand 2"},
        },
    }
}
minetest.register_entity("pmb_kelar:kelar_underworld", underkelar)

minetest.register_craftitem("pmb_kelar:kelar_spawn",
{
    description = "Golem spawn egg",
    on_place = function(itemstack, placer, pointed_thing)
        local ent = minetest.add_entity(vector.offset(minetest.get_pointed_thing_position(pointed_thing), 0, 1, 0), "pmb_kelar:kelar")
    end,
})

-- get rid of unused vars
underkelar = nil
kelar = nil
