require "vl_quest_utils"
-- require "vl_quest_item_utils"

VLIT = VLIT or {}

assert(VLF,  "Stack trace: Missing dependency: VLF - vl_quest_item_utils.lua")

local GetItemContainerFromCoord = VLF.GetItemContainerFromCoord
local SplitTextByLength = VLF.SplitTextByLength

--Thêm item vào container
function VLIT.AddItemToContainer(container, itemINV, itemType, number) --VLIT.AddItemToContainer(getPlayer():getInventory(), itemINV, "Base.Candle", 30)
    if not container then return end
    if not itemINV and not itemType then return end
    
    local itemList = {}
    local num = number or 1
    for i = 1, num do
        local item = itemINV or instanceItem(itemType)
        if item then
            --container:AddItem(item)
            container:addItem(item)
            sendAddItemToContainer(container, item)
            --table.insert(itemList, item)
            itemList[#itemList + 1] = item
        end
    end
    return itemList
end
local AddItemToContainer = VLIT.AddItemToContainer

--Lấy 1 InventoryItem từ itemINV hoặc itemType trong container và container trong nó. --Hàm Đệ Quy
function VLIT.GetItemInContainerRecursive(container, itemINV, itemType)
    local items = container:getItems()
    if not items then return end
	
    for i = 0, items:size() - 1 do
        local item = items:get(i)
        if item then
            if itemINV then
                if item == itemINV then
                    return item
                end
            elseif itemType then
                if item:getFullType() == itemType then
                    return item
                end
            end
        end

        -- Nếu là container thì duyệt bên trong
        if item and item:IsInventoryContainer() then
            local inner = item:getInventory()
            if inner then
                --VLIT.GetItemInContainerRecursive(inner, itemINV, itemType)
                local found = VLIT.GetItemInContainerRecursive(inner, itemINV, itemType)
                if found then
                    return found
                end
            end
        end
    end
    
    return nil
end
local GetItemInContainerRecursive = VLIT.GetItemInContainerRecursive

--Lấy Tất Cả InventoryItem từ itemINV hoặc itemType trong container và container trong nó. --Hàm Đệ Quy
function VLIT.GetAllItemTypeInContainerRecursive(container, itemList, itemINV, itemType)
    local items = container:getItems()
    if not items then return end
    
    for i = 0, items:size() - 1 do
        local item = items:get(i)
        if item then
            if itemINV then
                if item == itemINV then
                    itemList[#itemList + 1] = item
                end
            elseif itemType then
                if item:getFullType() == itemType then
                    itemList[#itemList + 1] = item
                end
            end

            -- Nếu là container thì duyệt bên trong
            if item:IsInventoryContainer() then
                local inner = item:getInventory()
                if inner then
                    VLIT.GetAllItemTypeInContainerRecursive(inner, itemList, itemINV, itemType)
                end
            end
        end
    end
end
local GetAllItemTypeInContainerRecursive = VLIT.GetAllItemTypeInContainerRecursive

--Xóa item trong container
function VLIT.RemoveItemInContainer(container, item)
    container:DoRemoveItem(item)
    sendRemoveItemFromContainer(container, item)    
end
local RemoveItemInContainer = VLIT.RemoveItemInContainer

--Xóa 1 InventoryItem từ itemINV trong container hoặc container trong nó. --Hàm Đệ Quy
function VLIT.RemoveItemInContainerRecursive(container, itemINV)
    local items = container:getItems()
    if not items then return false end
	
    for i = 0, items:size() - 1 do
        local item = items:get(i)
        if item and item == itemINV then
            RemoveItemInContainer(container, item)
            return true
        end
        -- Nếu là container thì duyệt bên trong
        if item and item:IsInventoryContainer() then
            local inner = item:getInventory()
            if inner then
                local innerRemoved = VLIT.RemoveItemInContainerRecursive(inner, itemINV)
                if innerRemoved == true then
                    return true
                end
            end
        end
    end
    return false
end
local RemoveItemInContainerRecursive = VLIT.RemoveItemInContainerRecursive

--Xóa item khỏi container hoặc container con. itemINV chỉ xóa 1, itemType xóa theo number
function VLIT.RemoveItemFromContainer(container, itemINV, itemType, number) --VLIT.RemoveItemFromContainer(getPlayer():getInventory(), itemINV, "Base.Candle", 20)
    if not container then return false end
    if not itemINV and not itemType then return false end
    number = number or 1
    
    if itemINV then --itemINV không xác định được vị trí cụ thể trong container
        local removed = RemoveItemInContainerRecursive(container, itemINV)
        if removed == true then
            return true
        end
        
    elseif itemType then 
        local flagRemoved = false
        for i = 1, number do    
            local itemInINV = GetItemInContainerRecursive(container, nil, itemType)
            if itemInINV then
                local removed = RemoveItemInContainerRecursive(container, itemInINV)
                if removed == true then
                    flagRemoved = true
                end
            end
        end
        
        if flagRemoved == true then
            return true
        end
    end
    return false
end
local RemoveItemFromContainer = VLIT.RemoveItemFromContainer

--Lấy ModData của Item
function VLIT.GetItemModData(item)
    local iData = item:getModData()
    if not iData.VL then iData.VL = {} end
    if not iData.VL.isQuestItem then iData.VL.isQuestItem = {} end
    return iData.VL
end
local GetItemModData = VLIT.GetItemModData

--Kiểm tra square có sàn không, nếu không thì kiểm tra tiếp các square xung quanh --cùng tầng
local function GetSquareHasFloorInArea(square, range) --GetSquareHasFloorInArea(square, 1)
    local x, y, z = square:getX(), square:getY(), square:getZ()
    if not x or not y or not z then return end
    if not range then range = 1 end
    --kiểm tra square này có floor hay không
    if square:isSolidFloor() then return square end
    --nếu không, kiểm tra square xung quanh
    for i = -range, range do
        for j = -range, range do
            local newX, newY = x + i, y + j
            local newSq = getCell():getGridSquare(newX, newY, z)
            if newSq and newSq:isSolidFloor() then return newSq end
        end
    end
    --print("Shared-----------GetSquareHasFloorInArea: no square") 
    return nil
end

--Add item vào square, nếu có bàn, ghế, giường,... thì cho item đặt trên chúng --chạy trên Client thì item add sẽ không đồng bộ?
function VLIT.AddItemToSquares(square, itemFullType, args) --VLIT.AddItemToSquares(square, itemFullType, {qStep = qStep, range = range})
    --if not square and not instanceItem(itemFullType) then return nil end
    local sq = GetSquareHasFloorInArea(square, args.range)
    local qStep = args.qStep
    
    if sq and qStep then
        local objs = sq:getObjects()
        local listFurnitureCanPlace = {"Desk", "Chair", "Couch", "Table", "Armchair", "Bed"} --"Drawers", "Cabinet", "Counter", "Dryer", 
        for i = 0, objs:size() - 1 do
            local obj = objs:get(i)
            if obj then
                local tileName = obj:getTileName() or ""
                --add item lên trên các listFurnitureCanPlace nếu có
                for _, v in ipairs(listFurnitureCanPlace) do
                    if string.find(tileName, v) then
                        local item = obj:addItemToObjectSurface(itemFullType)
                        if item then
                            print("Shared---AddItemToSquares---On ObjectSurface= ", item:getName(), sq:getX(), sq:getY(), sq:getZ())
                            return item
                        end
                    end
                end            
            end
        end
        --add item ở mặt đất nếu không có listFurnitureCanPlace
        local item = instanceItem(itemFullType)
        if item then
            sq:AddWorldInventoryItem(item, 0.5, 0.5, 0.0)
            print("Shared---AddItemToSquares---On Square= ", item:getName(), sq:getX(), sq:getY(), sq:getZ())
            return item
        end
    end
    
    return nil
end
local AddItemToSquares = VLIT.AddItemToSquares

--Set quest ModData cho Item
local function SetQuestModDataOnItem(item, qStep, iModData) --SetQuestModDataOnItem(item, qStep, "isKeyQuest1")
    local iData = GetItemModData(item)
    iData.isQuestItem[qStep] = true
    --print("Shared-----------SetQuestModDataOnItem:")

    if iModData then
        if not iData[iModData] then iData[iModData] = true end
    end
    return item
end

--Kiểm tra trong khu vực có item giống itemFullType không
function VLIT.HasItemOnSquares(square, itemFullType, range) --VLIT.HasItemOnSquares(square, itemFullType, range)
    --if not square and not instanceItem(itemFullType) then return nil end
    local x, y, z = square:getX(), square:getY(), square:getZ()
    if not x or not y or not z then return nil end
    if not range then range = 0 end
    local itemList = {}
    local cell = getCell()
    for i = -range, range do
        for j = -range, range do
            local newX, newY = x + i, y + j
            local newSq = cell:getGridSquare(newX, newY, z)
            if newSq and newSq:isSolidFloor() then
                local wObjs = newSq:getWorldObjects()
                for h = 0, wObjs:size() - 1 do
                    local wObj = wObjs:get(h)
                    if wObj and instanceof(wObj, "IsoWorldInventoryObject") then
                        local item = wObj:getItem()
                        if item and item:getFullType() == itemFullType then
                            --table.insert(itemList, item)
                            itemList[#itemList + 1] = item
                        end
                    end
                end
            end
        end
    end
    if #itemList > 0 then
        return itemList
    end
    return nil
end
local HasItemOnSquares = VLIT.HasItemOnSquares

--Kiểm tra item trên các square có ModData isQuestItem không. Nếu có thì trả về item
local function CheckItemsOnSquareIsQuestItem(square, itemFullType, qStep, range)
    local itemList = HasItemOnSquares(square, itemFullType, range)
    if itemList then
        for _, item in ipairs(itemList) do
            if item then
                local iData = GetItemModData(item)
                if iData.isQuestItem[qStep] == true then
                    print("Shared---CheckItemsOnSquareIsQuestItem= ", item:getName(), square:getX(), square:getY(), square:getZ())
                    return item
                end
            end
        end
    end
    return nil
end

local specLangs = {
    CN = true,
    CH = true,
    JP = true,
    KO = true,
    TH = true,
}

local function IsSpecialLanguage(languageName)
    return specLangs[languageName] == true
end

--Sửa item nếu là dạng Notepad
local function EditNotepadItem(item, qID, qStep, noteStep, totalPage) --EditNotepadItem(item, 1, qStep, 1, 1)
    --local qID, qStep, noteStep, totalPage = args.qID, args.qStep, args.noteStep, args.totalPage or 1
	item:setName(getText("IGUI_VLQ_"..tostring(qID).."_NoteTitle"..tostring(noteStep).."_"..tostring(qStep)))
	item:setCanBeWrite(true)
    item:setPageToWrite(totalPage)
    
    local lang = getCore():getOptionLanguageName()
    for i = 1, totalPage do
        local text = getText("IGUI_VLQ_"..tostring(qID).."_NotePage"..tostring(noteStep).."_"..tostring(i).."_"..tostring(qStep))
        --Thay thế tất cả <LINE> thành dấu xuống dòng
        text = text:gsub("<LINE>", "\n")
        --Kiểm tra có thuộc ngôn ngữ đặc biệt không --Có ngôn ngữ không có space
        if IsSpecialLanguage(lang) then
            --Chia dòng theo độ rộng
            local lines = SplitTextByLength(text, 300, UIFont.NewSmall)
            local newText = ""
            for i, l in ipairs(lines) do
                newText = newText .. " " .. l
            end
            text = newText
        end
            
        item:addPage(i, text)
    end
	item:setLockedBy("npcQuest")
end

--Kiểm tra khu vực spawn item quest đã có item quest chưa, nếu chưa thì spawn
function VLIT.DoSpawnItemQuestOnSquare(args) --VLIT.DoSpawnItemQuestOnSquare({qStep = qStep, x = x, y = y, z = z, itemFullType = itemFullType, range = 0, isNote = true, noteStep = 1, qID = 2, iModData = "isKeyQuest1", totalPage = 2})
    if not args or not args.x or not args.y or not args.z then return nil end
    local square = getCell():getGridSquare(args.x, args.y, args.z)
    local itemFullType, qStep = args.itemFullType, args.qStep
    
    if square then
        local itemQuest = CheckItemsOnSquareIsQuestItem(square, itemFullType, qStep, args.range)
        if itemQuest then
            return itemQuest
        else
            --khi không có item quest trong các square mới spawn để không bị spawn trùng
            --print("Shared-----------VLIT.DoSpawnItemQuestOnSquare: not have itemQuest, Trying add item")
            local item = AddItemToSquares(square, itemFullType, args)
            if item then
                SetQuestModDataOnItem(item, qStep, args.iModData)
				local isNote = args.isNote
				if isNote and isNote == true then
					local noteStep, totalPage = args.noteStep or 1, args.totalPage or 1
                    EditNotepadItem(item, args.qID, qStep, noteStep, totalPage)
				end
			end
            return item
        end
    end
    return nil
end
local DoSpawnItemQuestOnSquare = VLIT.DoSpawnItemQuestOnSquare

--Add item vào ItemContainer ở tọa độ x, y, z.
function VLIT.AddQuestItemToContainer(iContainer, args) --VLIT.AddQuestItemToContainer(iContainer, {qStep = qStep, x = x, y = y, z = z, itemFullType = itemFullType, isNote = true, noteStep = 1, qID = 1})
	local item = instanceItem(args.itemFullType)
    if item then
        local isNote = args.isNote
        if isNote and isNote == true then
            local noteStep = args.noteStep or 1
            EditNotepadItem(item, args.qID, args.qStep, noteStep, 1)
        end
        --local itemAdded = iContainer:addItem(item)
        local itemAdded = AddItemToContainer(iContainer, item, nil, 1)
        return itemAdded[1]
    end
end
local AddQuestItemToContainer = VLIT.AddQuestItemToContainer

--Kiểm tra item trong ItemContainer có ModData isQuestItem không. Nếu có thì trả về item
local function CheckContainerHasQuestItem(iContainer, qStep, itemFullType)
    local itemList = iContainer:getItems()
    for i = 0, itemList:size() - 1 do
        local item = itemList:get(i)
        if item and item:getFullType() == itemFullType then
            local iData = GetItemModData(item)
            if iData.isQuestItem[qStep] == true then
                --print("Shared-----------CheckContainerHasQuestItem: Da co item")
                return item
            end
        end
    end
    return nil
end

--Add item vào ItemContainer nếu trong ItemContainer không có quest Item
function VLIT.DoSpawnItemQuestInContainer(args) --VLIT.DoSpawnItemQuestInContainer({qStep = qStep, x = 5579, y = 12486, z = 0, itemFullType = "Base.Notepad", range = 0, isNote = true, noteStep = 1, qID = 1, addOnSquare = true}) --thêm , iModData = "isKeyQuest1" nếu là quest Item
    local x, y, z = args.x, args.y, args.z
    local square = getCell():getGridSquare(x, y, z)
    local itemFullType, range, qStep = args.itemFullType, args.range, args.qStep
    if square and square:isSolidFloor() then
        local iContainer = GetItemContainerFromCoord(x, y, z)
        if iContainer then
            --Kiểm tra itemContainer có item quest chưa
            local itemQuest = CheckContainerHasQuestItem(iContainer, qStep, itemFullType)
            if not itemQuest then
                --Nếu chưa có thì add item
                local item = AddQuestItemToContainer(iContainer, args)
                if item then
                    print("Shared---DoSpawnItemQuestInContainer= ", item:getName(), x, y, z) 
                    SetQuestModDataOnItem(item, qStep, args.iModData)
                    return item
                end
            else
                --Nếu đang có thì return itemQuest
                return itemQuest
            end
        end
        --Nếu không có ItemContainer thì add item trên square
        if args.addOnSquare and args.addOnSquare == true then
            local item = DoSpawnItemQuestOnSquare(args)
            if item then
                return item 
            end
        end            
    end
    return nil
end

--Kiểm tra có item nào trong các itemFullType có moddata isQuestItem không
function VLIT.GetItemQuestInINVPlayer(player, itemFullType, qStep, iModData) --VLIT.GetItemQuestInINVPlayer(player, itemFullType, qStep, "isKeyQuest1")
    local itemList = {}
    GetAllItemTypeInContainerRecursive(player:getInventory(), itemList, nil, itemFullType)
    
    if #itemList > 0 then
        for i = 1, #itemList do
            local item = itemList[i]
            if item then
                local iData = GetItemModData(item)
                if iData.isQuestItem[qStep] == true and iData[iModData] == true then
                    return item
                end
            end
        end
    end
    
    return nil
end


--=================================== ITEM ===================================--
--Duyệt toàn bộ container để lấy tất cả item có cùng itemType cụ thể
function VLIT.GetItemsInContainer(container, itemList, itemType)
    local items = container:getItems()
    if not items then return end
	
    for i = 0, items:size() - 1 do
        local item = items:get(i)
        if item and item:getFullType() == itemType then
            --table.insert(itemList, item)
            itemList[#itemList + 1] = item
        end
        -- Nếu là container thì duyệt bên trong
        if item and item:IsInventoryContainer() then
            local inner = item:getInventory()
            if inner then
                VLIT.GetItemsInContainer(inner, itemList, itemType)
            end
        end
    end
end
local GetItemsInContainer = VLIT.GetItemsInContainer

--=================================== FOOD ===================================--
--Lấy chỉ số hunger từ thức ăn
function VLIT.GetHungerFromFood(itemINV)
    if itemINV and itemINV:isFood() then
        local hunger = itemINV:getHungChange()
        if hunger and hunger < 0 then
            --hunger là số âm
            --nếu stale thì hunger giảm 24%. rotten giảm 55%. Khi làm tròn + 0.5
            if itemINV:isRotten() then
                hunger = math.floor((hunger * 0.45 * 100) + 0.5)
            else
                if itemINV:isFresh() then 
                    hunger = math.floor((hunger * 100) + 0.5)
                else
                    --stale
                    hunger = math.floor((hunger * 0.76 * 100) + 0.5)
                end
            end
            return hunger
        end
        return 0
    end
end
local GetHungerFromFood = VLIT.GetHungerFromFood

--Duyệt toàn bộ container để lấy food
function VLIT.GetFoodInContainer(container, foodList)
    local items = container:getItems()
    if not items then return end
	
    for i = 0, items:size() - 1 do
        local item = items:get(i)
        -- Nếu là thức ăn thì add vào list
        if item and item:isFood() then
            --table.insert(foodList, item)
            foodList[#foodList + 1] = item
        end
        -- Nếu là container thì duyệt bên trong
        if item and item:IsInventoryContainer() then
            local inner = item:getInventory()
            if inner then
                VLIT.GetFoodInContainer(inner, foodList)
            end
        end
    end
end
local GetFoodInContainer = VLIT.GetFoodInContainer
 
--Lấy tổng số lượng Reduce Hunger từ Food trong container   
function VLIT.GetAmountReduceHungerInContainer(container, isPoison, isbDangerousUncooked, isRotten)
    local foodList = {}
    GetFoodInContainer(container, foodList)
    
    local rHunger = 0
    for i = #foodList, 1, -1 do
        local food = foodList[i]
        if food then
            local skip = false
            --Nếu không lấy food có độc
            if not isPoison then
                if food:isPoison() then skip = true end
            end
            --Nếu không lấy food nguy hiểm khi ăn sống
            if not isbDangerousUncooked then
                if food:isbDangerousUncooked() then skip = true end
            end
            --Nếu không lấy food bị ôi thiu
            if not isRotten then
                if food:isRotten() then skip = true end
            end
            
            if skip == false then
                local rhg = math.abs(GetHungerFromFood(food))
                if rhg then
                    rHunger = rHunger + rhg
                end
            end
        end
    end
    
--[[    local rHunger = 0
    for i = #foodList, 1, -1 do
        local food = foodList[i]
        if food then
            if not food:isRotten() then
                local rhg = math.abs(GetHungerFromFood(food))
                if rhg then
                    rHunger = rHunger + rhg
                end
            end
        end
    end
    ]]
    return rHunger
end
  
--Xóa food theo số lượng rHungerLimit. Nếu rHungerLimit nil hoặc 0 thì xóa hết  --food rotten bỏ qua
function VLIT.RemoveFoodInContainer(container, rHungerLimit)
    local removed = 0
    --local container = player:getInventory()
    local foodList = {}
    GetFoodInContainer(container, foodList)
    
    for i = #foodList, 1, -1 do
        local food = foodList[i]
        if food then
            if not food:isRotten() then
                local reduceHunger = math.abs(GetHungerFromFood(food))
                if reduceHunger > 0 then
                    removed = removed + reduceHunger
                    RemoveItemFromContainer(container, food, nil, 1)
                    if rHungerLimit and rHungerLimit > 0 then
                        if removed > rHungerLimit then    --đã vượt quá giới hạn
                            return rHungerLimit
                        end
                    end
                end 
            end
        end
    end
    
    return removed
end

--Lấy tổng số lượng Reduce Hunger từ 1 loại thức ăn  
function VLIT.GetAmountRHungerInContByType(container, itemFullType, isPoison, isbDangerousUncooked, isRotten)
    local itemList = {}
    GetItemsInContainer(container, itemList, itemFullType)
    
    local rHunger = 0
    for i = #itemList, 1, -1 do
        local item = itemList[i]
        if item and item:isFood() then
            local skip = false
            --Nếu không lấy food có độc
            if not isPoison then
                if item:isPoison() then skip = true end
            end
            --Nếu không lấy food nguy hiểm khi ăn sống
            if not isbDangerousUncooked then
                if item:isbDangerousUncooked() then skip = true end
            end
            --Nếu không lấy food bị ôi thiu
            if not isRotten then
                if item:isRotten() then skip = true end
            end
            
            if skip == false then
                local rhg = math.abs(GetHungerFromFood(item))
                if rhg then
                    rHunger = rHunger + rhg
                end
            end
        end
    end
    
    return rHunger
end

--Xóa food theo số lượng rHungerLimit và theo FullType. Nếu rHungerLimit nil hoặc 0 thì xóa hết  --
function VLIT.RemoveFoodInContByType(container, itemFullType, rHungerLimit, isPoison, isbDangerousUncooked, isRotten)
    local removed = 0
    local itemList = {}
    GetItemsInContainer(container, itemList, itemFullType)
    
    for i = #itemList, 1, -1 do
        local item = itemList[i]
        if item then
            if item and item:isFood() then
                local skip = false
                --Nếu lấy cả food có độc --isPoison == true thì bỏ qua
                if not isPoison then
                    if item:isPoison() then skip = true end
                end
                --Nếu lấy cả food nguy hiểm khi ăn sống  --isbDangerousUncooked == true thì bỏ qua
                if not isbDangerousUncooked then
                    if item:isbDangerousUncooked() then skip = true end
                end
                --Nếu lấy cả food bị ôi thiu     --isRotten == true thì bỏ qua
                if not isRotten then
                    if item:isRotten() then skip = true end
                end
                
                if skip == false then
                    local reduceHunger = math.abs(GetHungerFromFood(item))
                    if reduceHunger > 0 then
                        removed = removed + reduceHunger
                        RemoveItemFromContainer(container, item, nil, 1)
                        if rHungerLimit and rHungerLimit > 0 then
                            if removed >= rHungerLimit then    --đã vượt quá giới hạn
                                return rHungerLimit
                            end
                        end
                    end 
                end
            end
            
        end
    end
    
    return removed
end
--=================================== WATER - FLUID ===================================--
--Duyệt toàn bộ container để lấy water
function VLIT.GetWaterSourcesInCont(container, waterSourceList)
    local items = container:getItems()
    if not items then return end
	
    for i = 0, items:size() - 1 do
        local item = items:get(i)
        -- Nếu là đồ chứa nước thì add vào list
        if item and item:isWaterSource() then
            --table.insert(waterSourceList, item)
            waterSourceList[#waterSourceList + 1] = item
        end
        -- Nếu là container thì duyệt bên trong
        if item and item:IsInventoryContainer() then
            local inner = item:getInventory()
            if inner then
                VLIT.GetWaterSourcesInCont(inner, waterSourceList)
            end
        end
    end
end
local GetWaterSourcesInCont = VLIT.GetWaterSourcesInCont

--Lấy tất cả item là Can đựng xăng trong container --gasoline
function VLIT.GetPetrolCans(container, itemList)
    local items = container:getItems()
    if not items then return end
	
    for i = 0, items:size() - 1 do
        local item = items:get(i)
        if item and item:getDisplayCategory() == "VehicleMaintenance" and item:getFluidContainer() and item:hasTag(ItemTag.PETROL) then
            --table.insert(itemList, item)
            itemList[#itemList + 1] = item
        end
        -- Nếu là container thì duyệt bên trong
        if item and item:IsInventoryContainer() then
            local inner = item:getInventory()
            if inner then
                VLIT.GetPetrolCans(inner, itemList)
            end
        end
    end
end
local GetPetrolCans = VLIT.GetPetrolCans

--Lấy tổng số lượng chất lỏng  trong container  --
function VLIT.GetAmountFluidInContainer(container, fluid)
    local waterSourceList = {}
    GetWaterSourcesInCont(container, waterSourceList)
    
    --lấy thêm Gas Can --vì không phải là waterSource
    if fluid == Fluid.Petrol then
        GetPetrolCans(container, waterSourceList)
    end
      
    local amount = 0
    for i = #waterSourceList, 1, -1 do
        local waterSource = waterSourceList[i]
        if waterSource then
            local fluidCont = waterSource:getFluidContainer()
            if fluidCont then
                if fluid == Fluid.Water then    --Nước
                    --if not fluidCont:isTainted() and fluidCont:getPrimaryFluid() and (fluidCont:getPrimaryFluid():getFluidTypeString() == "Water" or fluidCont:getPrimaryFluid():getFluidTypeString() == "CarbonatedWater") then
                    if (fluidCont:contains(fluid) or fluidCont:contains(Fluid.CarbonatedWater)) and not fluidCont:isTainted() then
                        amount = amount + fluidCont:getAmount()
                    end
                    
                elseif fluid == Fluid.Petrol then   --Gasoline
                    if fluidCont:contains(fluid) then
                        amount = amount + fluidCont:getAmount()
                    end
                end
            end
        end
    end
    return amount
end
 
--Xóa chất lỏng trong vật chứa trong giới hạn limitAmount. Nếu limitAmount nil hoặc 0 thì xóa hết
function VLIT.RemoveFluidKeepSource(container, fluid, limitAmount) --VLIT.RemoveFluidKeepSource(container, fluid, limitAmount)
    local removed = 0
    --local container = player:getInventory()
    local waterSourceList = {}
    GetWaterSourcesInCont(container, waterSourceList)
    
    --lấy thêm Gas Can --vì không phải là waterSource
    if fluid == Fluid.Petrol then
        GetPetrolCans(container, waterSourceList)
    end
    
    local function doRemove(fluidCont)
        local amo = removed + fluidCont:getAmount()
        
        if limitAmount and limitAmount > 0 then
            --Tổng nước hiện tại lớn hơn lượng cần xóa 
            if amo > limitAmount then
                fluidCont:adjustAmount(amo - limitAmount)   --lượng nước còn thừa lại
                return true
            end
        end
        
        fluidCont:adjustAmount(0)
        removed = amo
    end
    
	if #waterSourceList > 0 then
		for i = #waterSourceList, 1, -1 do
			local waterSource = waterSourceList[i]
			if waterSource then
				local fluidCont = waterSource:getFluidContainer()
				if fluidCont and fluidCont:getAmount() > 0 then
                    if fluid == Fluid.Water then    --Nước
                        if (fluidCont:contains(fluid) or fluidCont:contains(Fluid.CarbonatedWater)) and not fluidCont:isTainted() then
                            local isDone = doRemove(fluidCont)
                            if isDone == true then return limitAmount end
                        end
                        
                    elseif fluid == Fluid.Petrol then   --Gas
                        if fluidCont:contains(fluid) then
                            local isDone = doRemove(fluidCont)
                            if isDone == true then return limitAmount end
                            
                        end
                    end
                end
            end
        end
    end
    
    return removed
end
    
--=================================== ALCOHOL ===================================--
--Duyệt toàn bộ container để lấy tất cả item có Alcohol > 0
function VLIT.GetAlcoholsInContainer(container, itemList)
    local items = container:getItems()
    if not items then return end
	
    for i = 0, items:size() - 1 do
        local item = items:get(i)
        if item and item:getFluidContainer() and item:getFluidContainer():getProperties() and item:getFluidContainer():getProperties():getAlcohol() > 0 then
            --table.insert(itemList, item)
            itemList[#itemList + 1] = item
        end
        -- Nếu là container thì duyệt bên trong
        if item and item:IsInventoryContainer() then
            local inner = item:getInventory()
            if inner then
                VLIT.GetAlcoholsInContainer(inner, itemList)
            end
        end
    end
end

--Lấy Item theo phân loại ISO
function VLIT.GetItem(itemFullType, isoItemType) --VLIT.GetItem(itemFullType, "HandWeapon")     --HandWeapon, InventoryItem, Item
    if not itemFullType then return nil end
    local item = nil
    if isoItemType == "HandWeapon" then
        item = instanceItem(itemFullType)
        if item and instanceof(item, "HandWeapon") then
            return item
        end
    elseif isoItemType == "InventoryItem" then
        item = instanceItem(itemFullType)
        if item and instanceof(item, "InventoryItem") then
            return item
        end
    elseif isoItemType == "Item" then
        item = getScriptManager():getItem(itemFullType)
        if item then
            return item
        end
    end
    return nil
end
local GetItem = VLIT.GetItem

--Lấy thông tin về vũ khí
function VLIT.GetWeaponInfo(handWeapon)
    --if not itemFullType then return nil end
    --local weapon = GetItem(itemFullType, "HandWeapon")
    if not handWeapon then return nil end
    
    local wpnInfo = {}
    
    -- ===== BASIC INFO =====
    --wpnInfo.fullType      = itemFullType
    wpnInfo.displayName   = handWeapon:getDisplayName()
    wpnInfo.isRanged      = handWeapon:isRanged()
    wpnInfo.isAimedFire   = handWeapon:isAimedFirearm()
    wpnInfo.attachmentType= handWeapon:getAttachmentType()
    wpnInfo.jamGunChance  = handWeapon:getJamGunChance()
    
    -- ===== DAMAGE =====
    wpnInfo.minDamage       = handWeapon:getMinDamage()
    wpnInfo.maxDamage       = handWeapon:getMaxDamage()
    wpnInfo.critChance      = handWeapon:getCriticalChance()
    wpnInfo.critMultiplier  = handWeapon:getCriticalDamageMultiplier()
    wpnInfo.perkCritMod     = handWeapon:getAimingPerkCritModifier()
    --wpnInfo.doorDamage         = handWeapon:getDoorDamage()

    -- ===== RANGE =====
    wpnInfo.minRange      = handWeapon:getMinRange()
    wpnInfo.maxRange      = handWeapon:getMaxRange()
    wpnInfo.perkRangeMod  = handWeapon:getAimingPerkRangeModifier()
    
    -- ===== TIMING / FIRE RATE =====
    wpnInfo.aimingTime    = handWeapon:getAimingTime()
    wpnInfo.swingTime     = handWeapon:getSwingTime()
    wpnInfo.recoilDelay   = handWeapon:getRecoilDelay()
    wpnInfo.reloadTime    = handWeapon:getReloadTime()

    -- ===== ACCURACY =====
    wpnInfo.hitChance     = handWeapon:getHitChance()
    wpnInfo.perkHitChanceMod     = handWeapon:getAimingPerkHitChanceModifier()

    -- ===== AMMO / FIREARM =====
    wpnInfo.ammoType      = handWeapon:getAmmoType()
    wpnInfo.clipSize      = handWeapon:getMaxAmmo()
    wpnInfo.currentAmmo   = handWeapon:getCurrentAmmoCount()
    wpnInfo.fireMode      = handWeapon:getFireMode()

    -- ===== SOUND =====
    wpnInfo.swingSound    = handWeapon:getSwingSound()
    wpnInfo.soundRadius   = handWeapon:getSoundRadius()
    wpnInfo.soundVolume   = handWeapon:getSoundVolume()
    wpnInfo.shellFallSound= handWeapon:getShellFallSound()
    wpnInfo.rackSound     = handWeapon:getRackSound()
    wpnInfo.clickSound    = handWeapon:getClickSound()
    wpnInfo.ejectAmmoStartSound    = handWeapon:getEjectAmmoStartSound()
    wpnInfo.ejectAmmoSound         = handWeapon:getEjectAmmoSound()
    wpnInfo.ejectAmmoStopSound     = handWeapon:getEjectAmmoStopSound()
    wpnInfo.insertAmmoStartSound   = handWeapon:getInsertAmmoStartSound()
    wpnInfo.insertAmmoSound        = handWeapon:getInsertAmmoSound()
    wpnInfo.insertAmmoStopSound    = handWeapon:getInsertAmmoStopSound()

    -- ===== VISUAL / EFFECT =====
    wpnInfo.muzzleFlash   = handWeapon:getMuzzleFlashModelKey()
    
    -- ===== CONDITION =====
    wpnInfo.condition     = handWeapon:getCondition()
    wpnInfo.maxCondition  = handWeapon:getConditionMax()
    wpnInfo.conditionLowerChance   = handWeapon:getConditionLowerChance()

    return wpnInfo
end


            
            














