
local RemoveAllObjectsExceptFloor = VLF.RemoveAllObjectsExceptFloor
local RemoveObjectOnSquare = VLF.RemoveObjectOnSquare
local AddObjectToSquare = VLF.AddObjectToSquare

local GetModDataReliefSupplyEvent = VLERS.GetModDataReliefSupplyEvent
local HasTimePassedInHours = VLF.HasTimePassedInHours
local PlaySound_Helicopter = VLERS.PlaySound_Helicopter
local RemoveSupplysQuestList = VLERS.RemoveSupplysQuestList
local BroadCastAboutSupplyDropped = VLERS.BroadCastAboutSupplyDropped
local EventRS_RemoveQuestList = VLERS.EventRS_RemoveQuestList
local AddToQuestList = VLERS.AddToQuestList
local RegisterReliefCrateSpawn = VLERS.RegisterReliefCrateSpawn
local UpdateSupplyLootedData = VLERS.UpdateSupplyLootedData
local GetPlayerGMDReliefSupply = VLERS.GetPlayerGMDReliefSupply
local RemoveGMDSupplyID = VLERS.RemoveGMDSupplyID
local UpdateSpawnedData = VLERS.UpdateSpawnedData
local requiredHoursToStartEvent = VLERS.requiredHoursToStartEvent

local cSprite = VLERS.cSprite

--Lấy tất cả Crate Event Relief Supply trong phạm vi 60 ô của player
local function HasReliefSupplyAroundPlayer(player, range) 	--local supplyIDList = HasReliefSupplyAroundPlayer(player, 60)
	if not player then return {} end
	local px, py = player:getX(), player:getY()
	range = range or 60
	local supplyIDList = {}
	local questMD_Events_ReliefSupply = GetModDataReliefSupplyEvent()
	
	for supplyID, data in pairs(questMD_Events_ReliefSupply) do
		if type(data) == "table" and data.x and data.y then
			if math.abs(px - data.x) <= range and math.abs(py - data.y) <= range then
				--print("Client---HasReliefSupplyAroundPlayer= ", supplyID, data.x, data.y)
				table.insert(supplyIDList, supplyID)
			end
		end
	end
	
	--print("Client---HasReliefSupplyAroundPlayer---#supplyIDList= ", #supplyIDList)
	return supplyIDList
end

--Kiểm tra square của Crate, nếu cùng tọa độ x, y mà tầng trên có sàn thì lấy square tầng trên, cứ thế đến khi phía trên không có sàn
--Nếu square là ô nước thì add trực tiếp lên trên ô nước
local function GetSquareToAddSupply(x, y)	--local square = GetSquareToAddSupply(x, y)
	local cell = getCell()
	if not cell then return nil end

	local MAX_Z = 29

	--bắt đầu từ tầng 0
	local z = 0
	local sq = cell:getGridSquare(x, y, z)
	if not sq then return nil end
	
	if sq:isOutside() and sq:isFree(true) then
		return sq
	end

	--tìm tầng cao nhất có sàn khi không phải isOutside()
	for zz = z + 1, MAX_Z do
		local testSq = cell:getGridSquare(x, y, zz)
		if testSq and testSq:isSolidFloor() then
			sq = testSq
		end
	end
		
	--nếu vẫn bên trong building thì destroy tất cả object ngoại trừ floor. Để giả định Crate phá mái nhà rơi vào trong.
	if sq:getBuilding() then
		RemoveAllObjectsExceptFloor(sq, true)
	end
	
	--trường hợp trên mái nhà, sàn là roof hoặc ceiling (getTextureName)
	local floorObj = sq:getFloor()
	if floorObj then
		--Xóa hết object rồi add ceilings_01_0 làm floor
		if string.find(floorObj:getTextureName(), "ceiling") or string.find(floorObj:getTextureName(), "roof") then
			RemoveObjectOnSquare(sq, nil, true, true)	--Remove all object
			AddObjectToSquare(sq, "ceilings_01_0", {isTransmit = true, x = -1, y = -1, z = 0, objType = "IsoObject"})
		end
		
	end

--[[
	--nếu square không isFree(true) thì check các ô xung quanh trong khoảng cách 5 ô. Check từ gần đến xa
	if not sq:isFree(true) then
		local range = 5
		local bestSq = nil

		for r = 1, range do
			for dx = -r, r do
				for dy = -r, r do
					--chỉ check viền ngoài (gần → xa)
					if math.abs(dx) == r or math.abs(dy) == r then	--tránh lặp lại các vòng trước
						local testSq = cell:getGridSquare(x + dx, y + dy, sq:getZ())
						if testSq and testSq:isFree(true) then
							bestSq = testSq
							break
						end
					end
				end
				if bestSq then break end
			end
			if bestSq then break end
		end

		if bestSq then
			sq = bestSq
		end
	end
	]]

	--print("Client---GetSquareToAddSupply---sq:getX(), sq:getY(), sq:getZ()= ", sq:getX(), sq:getY(), sq:getZ())
	return sq
end

--Crate đã bị player mở
local function CrateAlreadyLootedByPlayer(crate)
	local supplyID = crate:getModData().VL_ReliefSupplyID
	if supplyID then
		--print("Client---CrateAlreadyLootedByPlayer---Supply Crate Looted By Player---supplyID= ", supplyID)
		--xoa hien thi quest list ngay cho player looted
		EventRS_RemoveQuestList(supplyID, "looted")
		
		--show Halo text 
		HaloTextHelper.addGoodText(getPlayer(), getText("IGUI_VLQ_ReliefSupply_YouLooted", supplyID))
		
		--Cập nhật ModData sau khi Crate event bị lấy mất. --Xóa modData Crate. --Xóa data supplyID nếu player looted
		UpdateSupplyLootedData(supplyID, true, true)
		
		--if isClient() then
		--	sendClientCommand(getPlayer(), "Event_ReliefSupply", "SupplyLooted", {supplyID = supplyID})
		--end
	end
end

local looted = {}

--[[ Dùng ổn, nhưng đã có cách khác tốt hơn
local looted = {}
--Thêm vào function ISLootWindowContainerControls:arrange() của game để detect player đang mở hòm Event
local function OnGameStart_Edit_ISLootWindow()
	local old_arrange = ISLootWindowContainerControls.arrange	--ISLootWindowContainerControls.lua
	
	function ISLootWindowContainerControls:arrange()
		old_arrange(self)

		local objContainer = self:getDisplayedObject()
		if objContainer then
			local md = objContainer:getModData()
			if md and md.VL_ReliefSupplyID then
				local supplyID = md.VL_ReliefSupplyID
				if not looted[supplyID] then
					CrateAlreadyLootedByPlayer(objContainer)
					looted[supplyID] = true
					print("-----------= ", objContainer, self:getHeight(), self:isVisible(), self:isReallyVisible(), self:isEnabled())
				end
			end
		end
	end
end
Events.OnGameStart.Add(OnGameStart_Edit_ISLootWindow)
]]

local pTick = 1

--Kiểm tra có Relief Supply Crate nào cần spawn quanh player không. Nếu có thì check square rồi yêu cầu Server add Crate
--Kiểm tra Crate đã bị NPC loot chưa
--Kiểm tra player này có đang mở Crate Event không
local function OnPlayerUpdate_ERS(player)
	if not player then return end
	 
	if pTick % 30 == 0 then
		--Kiểm tra world đã tồn tại ít nhất 7 ngày
		if HasTimePassedInHours(requiredHoursToStartEvent) ~= true then return end
		
		--Hiển thị tất cả Relief Supply đã nghe được tin tức
		for supplyID, func in pairs(VLERS.displaySupplyOnQuestList) do				
			func(player, supplyID)
		end

		--Kiểm tra các Relief Supply Crate xung quanh player
		--Check các Crate xung quanh player
		local supplyIDList = HasReliefSupplyAroundPlayer(player, 60)
		if #supplyIDList > 0 then
			local questMD_Events_ReliefSupply = GetModDataReliefSupplyEvent()
			
			for i = #supplyIDList, 1, -1 do
				local supplyID = supplyIDList[i]
				local supplyData = questMD_Events_ReliefSupply[supplyID]
				
				if supplyData then
					--Crate chưa được spawn
					if supplyData.spawned == false then
						--Check tọa độ Crate để lấy square để spawn
						local square = GetSquareToAddSupply(supplyData.x, supplyData.y)
						if square then
							--Yêu cầu server Spawn Crate
							local x = square:getX()
							local y = square:getY()
							local z = square:getZ()
							if x and y and z then
								--print("Client---CheckSpawnCrate_ReliefSupply---Request Server Spawn Crate---supplyID, x, y, z= ", supplyID, x, y, z)
								sendClientCommand(player, "Event_ReliefSupply", "SpawnSupply", {supplyID = supplyID, x = x, y = y, z = z})
							end
						end
						
					--Crate đã spawn
					elseif supplyData.spawned == true then
						--Crate đã bị NPC loot
						if supplyData.looted == true and not supplyData.lootedByPlayer then
							--Kiểm tra có đang load sq và có Crate Supply tồn tại không
							local x, y, z = supplyData.addedX, supplyData.addedY, supplyData.addedZ
							if x and y and z then
								local sq = getCell():getGridSquare(x, y, z)
								if sq then
									--Tìm Crate Event trong square
									local objs = sq:getObjects()
									local hasCrateToRemove = false
									
									for j = 0, objs:size() - 1 do
										local obj = objs:get(j)
										if obj and obj:getSprite() and obj:getSprite():getName() == cSprite then
											if obj:getModData() and obj:getModData().VL_ReliefSupplyID == supplyID then
												--Yêu cầu server xóa modData Crate --Xóa moddata supplyID --Xóa item bên trong Crate
												sendClientCommand(player, "Event_ReliefSupply", "UpdateCrateFakeLootedByNPC", {supplyID = supplyID, x = x, y = y, z = z})
												hasCrateToRemove = true
											end
										end
									end
									
									--Khi không tìm được Crate nguyên nhân không rõ, thì vẫn xóa GMD supply
									if hasCrateToRemove == false then
										if isClient() then
											sendClientCommand(player, "Event_ReliefSupply", "RemoveDataSupplyID", {supplyID = supplyID})
										else --SP
											--print("-------XOA MD CRATE NHUNG KHONG XOA ITEMS---= ", supplyID)
											RemoveGMDSupplyID(supplyID, false)
										end
									end
								end
							end
						end
					end					
				end
			end
		end
	
		--Phát hiện player mở Relief Supply Crate -> Báo cho server
		--Check file ISPlayerDataObject.lua
		local playerIndex = player:getPlayerNum()
		local playerData = getPlayerData(playerIndex)

		if playerData and playerData.lootInventory then
			local lootPanel = playerData.lootInventory
			
			if lootPanel:isVisible() 
				and not lootPanel.isCollapsed	--loot panel không thu gọn
				and lootPanel.inventory 			--container
				and lootPanel.inventory:getType() ~= "floor" then
				
				local objContainer = lootPanel.inventory:getParent()
				if objContainer then
					local md = objContainer:getModData()
					if md and md.VL_ReliefSupplyID then
						local supplyID = md.VL_ReliefSupplyID
						if not looted[supplyID] then
							print("Client---OnPlayerUpdate_ShowNewsOnQuestList---Player Open RS Crate= ", supplyID)
							CrateAlreadyLootedByPlayer(objContainer)
							looted[supplyID] = true
						end
					end
				end
			end
		end
	end

	pTick = pTick + 1
end
Events.OnPlayerUpdate.Remove(OnPlayerUpdate_ERS)
Events.OnPlayerUpdate.Add(OnPlayerUpdate_ERS)

--Xóa hiển thị Quest List cho các Supply đã add được 72 tiếng trở lên
--Xử lý trường hợp player không có radio, quest list cũng tự xóa
local function EveryHours_UpdateExpiredSupplyData()
	local player = getPlayer()
	if not player then return end
	
	local playerGMD_Data_knewReliefSupplys = GetPlayerGMDReliefSupply(player)
	local questMD_Events_ReliefSupply = GetModDataReliefSupplyEvent()

	for supplyID, data in pairs(playerGMD_Data_knewReliefSupplys) do
		if type(data) == "table" and data.activateStartHour then
			--Kiểm tra supply đã drop bao nhiêu tiếng
			if data.activateStartHour >= 72 then	--FIXME:72
				local supplyData = questMD_Events_ReliefSupply[supplyID]
				
				--Nếu supplyID không tồn tại, hoặc đã bị loot trong md questMD_Events_ReliefSupply thì xóa hiển thị Quest List
				if not supplyData or (supplyData and supplyData["looted"] == true) then
					print("Client---EveryHours_UpdateExpiredSupplyData---EventRS_RemoveQuestList---supplyID= ", supplyID)
					EventRS_RemoveQuestList(supplyID, "looted")
					--HaloTextHelper.addBadText(player, getText("IGUI_VLQ_ReliefSupply_SomeoneLooted", supplyID))
				end
			end
		end
	end    
end
Events.EveryHours.Remove(EveryHours_UpdateExpiredSupplyData)
Events.EveryHours.Add(EveryHours_UpdateExpiredSupplyData)

--Khi login, nếu có playerGMD.Data["knewReliefSupplys"][supplyID] == true thì add lại VLERS.displaySupplyOnQuestList[supplyID] = AddToQuestList
local function OnGameStart_GetAllFuncSupplyID()
	local playerGMD_Data_knewReliefSupplys = GetPlayerGMDReliefSupply(getPlayer())

	for supplyID, data in pairs(playerGMD_Data_knewReliefSupplys) do
		if type(data) == "table" and data.active == true then
			--Tạo function theo supplyID để show trên Quest List
			VLERS.displaySupplyOnQuestList[supplyID] = AddToQuestList
			--print("Client---OnGameStart_GetAllFuncSupplyID---supplyID= ", supplyID)
		end
	end    
end
Events.OnGameStart.Remove(OnGameStart_GetAllFuncSupplyID)
Events.OnGameStart.Add(OnGameStart_GetAllFuncSupplyID)
 

--================= ONSERVERCOMMAND =================--
VLOSC["Event_ReliefSupply_C"] = VLOSC["Event_ReliefSupply_C"] or {}

VLOSC["Event_ReliefSupply_C"]["RegisterDataSpawn_C"] = function(args)	--{supplyID = supplyID, x = x, y = y, supplyTypeID = supplyTypeID, crateSprite = crateSprite, activateStartHour = activateStartHour, itemFNameList = itemFNameList, spawned = false, instantSpawn = instantSpawn}
	RegisterReliefCrateSpawn(args.x, args.y, args.supplyID, args.supplyTypeID, args.crateSprite, args.activateStartHour, args.itemFNameList, args.instantSpawn)
end

VLOSC["Event_ReliefSupply_C"]["UpdateSpawned_C"] = function(args)		--{supplyID = supplyID, spawned = true, addedX = x, addedY = y, addedZ = z}
	UpdateSpawnedData(args.supplyID, args.spawned, args.addedX, args.addedY, args.addedZ)	
end

VLOSC["Event_ReliefSupply_C"]["SupplyLooted_C"] = function(args)			--{supplyID = supplyID, isLootedByPlayer = isLootedByPlayer}
	UpdateSupplyLootedData(args.supplyID, false, args.isLootedByPlayer)
end
	
VLOSC["Event_ReliefSupply_C"]["BroadCastSupplyDropped_C"] = function(args)			--{supplyID = supplyID}
	BroadCastAboutSupplyDropped(getPlayer(), args.supplyID)
end

VLOSC["Event_ReliefSupply_C"]["RemoveDataSupplyID_C"] = function(args)			--{supplyID = supplyID}
	RemoveGMDSupplyID(args.supplyID, false)
end

VLOSC["Event_ReliefSupply_C"]["RemoveSupplysQuestList_C"] = function(args)			--{}
	RemoveSupplysQuestList()
end

VLOSC["Event_ReliefSupply_C"]["PlaySoundHelocopter_C"] = function(args)			--{x, y}
	PlaySound_Helicopter(args.x, args.y)
end

