--[[
    Fillable canteens
    
    This work is licensed under Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0).
    Author: HarukaSai (visit us at: https://discord.gg/efp)
    2023-06-28
]]

local string_find = string.find
local geometry_ray = demonized_geometry_ray.geometry_ray

waters = {
    ["flask"] = true,
    ["dirty_water"] = true,
    ["boiled_water"] = true
}

local sound_objs = {
    boiling_water = sound_object("fillable_canteens\\boiling_water"),
    filling_water = sound_object("fillable_canteens\\filling_water")
}

function is_liquid(ray, result)
    if (not result.material_name) then
        return false
    end

    return (string.find(result.material_name, "water") or ray:isMaterialFlag("flLiquid"))
end

function check_water(material)
    local ray = geometry_ray({
        ray_range = 4,
        flags = 1 + 2 + 4 + 8,
        ignore_object = db.actor
    })
    
    local res = ray:get(device().cam_pos, device().cam_dir)
    return is_liquid(ray, res.result)
end

function actor_on_item_use(obj)
    local sec = obj:section()

    if (waters[sec]) and obj:get_remaining_uses() == 0 then
        alife_create_item("empty_canteen", db.actor)
    end
end

function find_object(t, sec)
    for i = 1, #t do
        local result = t[i]:section() == sec and t[i]

        if result then 
            return result
        end
    end
end

function find_object_t(t, secs)
    for i = 1, #secs do
        local result = find_object(t, secs[i])

        if result then 
            return result
        end
    end
end

function on_item_drag_dropped(obj_1, obj_2, slot_from, slot_to)
    local p_1, p_2 = obj_1:parent(), obj_2:parent()

    if not ((p_1 and p_1:id() == AC_ID) and (p_2 and p_2:id() == AC_ID)) then
        return
    end

    local akvatab = find_object({obj_1, obj_2}, "purification_tablet")
    local dirty_water = find_object_t({obj_1, obj_2}, {"dirty_water","boiled_water"})
    
    if not (akvatab and dirty_water) then
        return
    end

    alife_create_item("flask", db.actor, {["uses"] = dirty_water:get_remaining_uses()})
    alife_release(dirty_water)

    utils_item.discharge(akvatab, 1)
end

function fill(obj, sec)
    alife_create_item("dirty_water", obj:parent())
    sound_objs.filling_water:play(db.actor, 0, sound_object.s2d)
    alife_release(obj)
end

local function fill_condition_function(obj, bag, mode)
    local p = obj:parent()
    if not (p and p:id() == AC_ID) then
        return
    end
    local sec = obj:section()
    if (sec == "empty_canteen" or waters[sec]) and check_water() then
        return true
    end
end

local add_functor = custom_functor_autoinject.add_functor
add_functor("haruka_fill", fill_condition_function, function() 
    return game.translate_string("st_haruka_fill")
end, nil, fill)

function on_game_start()
    RegisterScriptCallback("ActorMenu_on_item_drag_drop", on_item_drag_dropped)
    RegisterScriptCallback("actor_on_item_use", actor_on_item_use)
end