local S = airutils.S

local function attach_entity(self, target_obj, ent, dest_pos, relative_pos, attach_up)
    attach_up = attach_up or false
    if not target_obj then return end
    if self.object then
        if self._vehicle_custom_data then
            local y = 0
            if attach_up == false then
                y = self.initial_properties.collisionbox[2] - ent.initial_properties.collisionbox[2]
            else
                y = (relative_pos.y/10) + ent.initial_properties.collisionbox[5]
            end
            dest_pos.y = dest_pos.y + y
            target_obj:set_pos(dest_pos)
            local ent = target_obj:get_luaentity()
            if ent then
                relative_pos.y = y*10
                target_obj:set_attach(self.object,'',relative_pos,{x=0,y=0,z=0})
                self._vehicle_custom_data.simple_external_attach_entity = ent.name
                self._vehicle_custom_data.simple_external_attach_pos = relative_pos
                self._vehicle_custom_data.simple_external_attach_invid = ent._inv_id --why?! Because I can identify the target entity by it's inventory ;)
            end
        end
    end
end

function airutils.get_attached_entity(self)
    if not self._vehicle_custom_data then return nil, nil end
    if not self._vehicle_custom_data.simple_external_attach_entity then return nil, nil end

    local inv_id = self._vehicle_custom_data.simple_external_attach_invid

    local pos = self.object:get_pos()
    local nearby_objects = minetest.get_objects_inside_radius(pos, 32)
	for i,obj in ipairs(nearby_objects) do
        local ent = obj:get_luaentity()
        if ent then
            if ent._inv_id then
                if ent._inv_id == inv_id then
                    return ent, obj
                end
            end
        end
    end
    return nil, nil
end

function airutils.dettach_entity(self)
    local ent, obj = airutils.get_attached_entity(self)
    if ent and obj then
        local relative_pos = self._vehicle_custom_data.simple_external_attach_pos
        local pos = self.object:get_pos()
        local rotation = self.object:get_rotation()
        local direction = rotation.y
        local velocity = self.object:get_velocity()

        local move = -1*relative_pos.z/10
        pos.x = pos.x + move * math.sin(direction)
        pos.z = pos.z - move * math.cos(direction)
        pos.y = pos.y + self.initial_properties.collisionbox[2] - ent.initial_properties.collisionbox[2]
        obj:set_detach()
        obj:set_pos(pos)
        obj:set_rotation(rotation)
        obj:set_velocity(velocity)
        --clear
        self._vehicle_custom_data.simple_external_attach_entity = nil
        self._vehicle_custom_data.simple_external_attach_pos = nil
        self._vehicle_custom_data.simple_external_attach_invid = nil
    end
end

function airutils.attach_external_object(self, object, ent, destination_pos, relative_pos, attach_up)
    local dest_pos = vector.new(destination_pos)
    local rel_pos = vector.new(relative_pos)
    if attach_up == false then
        rel_pos.y = 0
    end
    dest_pos = vector.add(dest_pos, vector.divide(rel_pos,10))
    attach_entity(self, object, ent, dest_pos, rel_pos, attach_up)
end

function airutils.simple_external_attach(self, relative_pos, entity_name, radius, attach_up)
    attach_up = attach_up or false
    radius = radius or 12
    if self.object then
        local curr_ent, _ = airutils.get_attached_entity(self)
        if curr_ent then return end

        local pos = self.object:get_pos()
        local nearby_objects = minetest.get_objects_inside_radius(pos, radius)
		for i,obj in ipairs(nearby_objects) do
			if obj == self.object then
				table.remove(nearby_objects,i)
			end
            local ent = obj:get_luaentity()
            if ent then
                if ent.name == entity_name then
                    airutils.attach_external_object(self, nearby_objects[i], ent, pos, relative_pos, attach_up)
                    return
                end
            end
		end
    end
end

--execute on load
function airutils.restore_external_attach(self)
    if not self._vehicle_custom_data then return end
    if not self._vehicle_custom_data.simple_external_attach_invid then return end

    local pos = self.object:get_pos()
    local dest_pos = vector.new(pos)
    local relative_pos = self._vehicle_custom_data.simple_external_attach_pos
    local inv_id = self._vehicle_custom_data.simple_external_attach_invid
    dest_pos = vector.add(dest_pos, relative_pos)

    minetest.after(0.3, function()
        local nearby_objects = minetest.get_objects_inside_radius(pos, 32)
        local ent
	    for i,obj in ipairs(nearby_objects) do
            ent = obj:get_luaentity()
            if ent then
                --minetest.chat_send_all(dump(ent.name))
                if ent._inv_id then
                    --minetest.chat_send_all(">> "..dump(ent._inv_id).." >> "..dump(inv_id))
                    if ent._inv_id == inv_id and ent._inv_id ~= self._inv_id then
                        --minetest.chat_send_all("++ "..dump(ent._inv_id).." ++ "..dump(inv_id))
                        local target_obj = nearby_objects[i]
                        target_obj:set_pos(dest_pos)
                        target_obj:set_attach(self.object,'',relative_pos,{x=0,y=0,z=0})
                        --attach_entity(self, nearby_objects[i], dest_pos, relative_pos, entity_name, inv_id)
                        return
                    end
                end
            end
	    end
    end)

    --clear
    --self._vehicle_custom_data.simple_external_attach_entity = nil
    --self._vehicle_custom_data.simple_external_attach_pos = nil
    --self._vehicle_custom_data.simple_external_attach_invid = nil
end

minetest.register_chatcommand("remove_hook", {
    params = "",
    description = S("Dettach current vehicle from another"),
    privs = {interact=true},
	func = function(name, param)
        local colorstring = core.colorize('#ff0000', S(" >>> you are not inside a plane"))
        local player = minetest.get_player_by_name(name)
        local attached_to = player:get_attach()

		if attached_to ~= nil then
            local seat = attached_to:get_attach()
            if seat ~= nil then
                local entity = seat:get_luaentity()
                if entity then
                    if entity.on_step == airutils.on_step then
                        local rem_obj = entity.object:get_attach()
                        if not rem_obj then
                            minetest.chat_send_player(name,core.colorize('#ff0000', S(" >>> no hook found")))
                            return
                        end
                        local rem_ent = rem_obj:get_luaentity()

                        local pos = rem_ent.object:get_pos()
                        local rotation = rem_ent.object:get_rotation()
                        local direction = rotation.y
                        local velocity = rem_ent.object:get_velocity()

                        local move = 0
                        if rem_ent._vehicle_custom_data.simple_external_attach_pos then
                            move = -1*rem_ent._vehicle_custom_data.simple_external_attach_pos.z/10
                        end
                        pos.x = pos.x + move * math.sin(direction)
                        pos.z = pos.z + move * math.cos(direction)
                        pos.y = pos.y + rem_ent.initial_properties.collisionbox[2] - entity.initial_properties.collisionbox[2]
                        entity.object:set_detach()
                        entity.object:set_pos(pos)
                        entity.object:set_rotation(rotation)
                        entity.object:set_velocity(velocity)
                        --clear
                        rem_ent._vehicle_custom_data.simple_external_attach_entity = nil
                        rem_ent._vehicle_custom_data.simple_external_attach_pos = nil
                        rem_ent._vehicle_custom_data.simple_external_attach_invid = nil
                    else
			            minetest.chat_send_player(name,colorstring)
                    end
                end
            end
		else
			minetest.chat_send_player(name,colorstring)
		end
	end
})
