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


aom_combat.projectile = {}

function aom_combat.projectile.is_node_or_hostile(self, pointed_thing)
    if pointed_thing.type == "node" then
        local node = core.get_node(pointed_thing.under)
        local def = core.registered_nodes[node.name]
        if def and def.walkable then
            return true
        end
    else
        return true
    end
end

local function retnil(...)
    return nil
end

local tracked_vars = {
    ["_prj_gravity"] = 3,
    ["_prj_speed"] = 10,
    ["_prj_dir"] = vector.new(0, 0, 1),
    ["_prj_can_collide"] = aom_combat.projectile.is_node_or_hostile,
    ["_prj_on_collide"] = retnil,
    ["_prj_do_collision_checks"] = true,
}

function aom_combat.projectile.init(self)
    self._last_pos = self.object:get_pos()
    self._avg_vel = self.object:get_velocity()
    for key, val in pairs(tracked_vars) do
        if not self[key] then self[key] = val end
    end
    self._prj_init = true
end

function aom_combat.projectile.on_step(self, dtime, flags)
    -- check to make sure init'd
    if not self._prj_init then aom_combat.projectile.init(self) end
    if not flags then flags = {} end

    local pos = self.object:get_pos()

    if self.object and not flags.no_vel then
        local vel = self.object:get_velocity()
        vel.y = vel.y - self._prj_gravity * dtime
        self.object:set_velocity(vel)
    end

    if self._last_pos and self._prj_do_collision_checks then
        local lastpos = self._last_pos
        lastpos = lastpos + vector.direction(pos, lastpos)
        local ray = core.raycast(lastpos, pos, true, false)
        for pointed_thing in ray do
            if pointed_thing.ref ~= self.object and pointed_thing.ref ~= self._prj_owner
            and self._prj_can_collide(self, pointed_thing)
            and self._prj_on_collide(self, pointed_thing) then
                self._prj_do_collision_checks = false
                break
            end
        end
    end

    self._last_pos = pos
end

function aom_combat.projectile.rotate_to_trajectory(self, amount)
    if (not self.object:get_pos()) then return end
    if (not self._prj_init) or (not self._avg_vel) then aom_combat.projectile.init(self) return end
    self._avg_vel = vector.divide(vector.add(vector.multiply(self._avg_vel, amount), self.object:get_velocity()), 1 + amount)
    self.object:set_rotation(vector.dir_to_rotation(self._avg_vel))
end

function aom_combat.projectile.add_projectile(from_user, entity_name, pos, dir, speed)
    local object = core.add_entity(pos, entity_name)
    object:set_rotation(vector.dir_to_rotation(dir))
    local ent = object and object:get_luaentity()
    if not ent then return nil end
    ent._prj_dir = dir
    ent._prj_init = true
    ent._prj_owner = from_user
    object:set_velocity(vector.multiply(dir, speed))
    return ent
end
