--------------------------------------------------------------------------------
--  File     : _load.lua
--  Author(s): Prokopovich Larisa
--
--  Summary  : Скрипт управления загрузкой комнат.
--
--  Copyright © 2012 Floodlight Games.  All rights reserved.
--------------------------------------------------------------------------------
locations = 
{

["Trunk"]				=	{},

["Gate"]				=	{"Gate_Stub"},
				
["Hut_1st_floor"]		=	{"Hut_1st_floor_Cabinet[puzzle_piece:1]",				--получение ключа от миниигры
							"Hut_1st_floor_Cabinet_MG", 
							"Hut_1st_floor_Chest", 			
							"Hut_1st_floor_Lantern_MG[Close_up_Lantern:1]", 		--получение медальона
							"Hut_1st_floor_Shelf_HO[Shelf_HO:0|Shelf_HO:2]",
							"Hut_1st_floor_Statuette", 
							"Hut_1st_floor_Stool_puzzle"},
						
["Hut_2nd_floor"]		=	{"Hut_2nd_floor_Cage", 
							"Hut_2nd_floor_Telescope"},
						
["Scary_glade"]			=	{"Scary_glade_Boat_HO[Sleep_Powder:1]"}, 				--получение порошка
						
["Witch's_house_ext"]	=	{"Witch's_house_ext_Flowerbed", 
							"Witch's_house_ext_Flytrap", 
							"Witch's_house_ext_Magic_place"},
						
["Witch's_house_int"]	=	{"Witch's_house_int_Scull_h", 
							"Witch's_house_int_Cache[Hut_1st_floor_Chest:2]", 		--получение глаза для черепа
							"Witch's_house_int_Witch_book_MG"},						
						
["Scary_place_exit"]	=	{"Scary_place_exit_Hollow_HO[Hollow_HO:0|Hollow_HO:2]",
							"Scary_place_exit_Skeleton"},
						
["Tavern_ext"]			=	{"Tavern_ext_Doghouse",		
							"Tavern_ext_Well"},
						
["Tavern_int"]			=	{"Tavern_int_Witch_box_MG"},
				
["Bridge"]				=	{"Bridge_Garbage_HO[Garbage_HO:0]",
							"Bridge_Senry_box"},
							
["Village_street"]		=	{"Village_street_Smithy_door"},

["Smithy"]				=	{"Smithy_Chemical_lab",
							"Smithy_Workplace"},							
					
["Chapel_ext"]			=	{"Chapel_ext_Door_MG"},
						
["Chapel_int"]			=	{"Chapel_int_Casket", 			
							"Chapel_int_Cupboard_HO[Cupboard_HO:0]"},	
						
["Cemetery"]			=	{"Cemetery_Statue"},
						
["Mill_ext"]			=	{"Mill_ext_Cellar[Mill_Ghosts:1]"},						--духи упокоены
				
["Mill_int"]			=	{"Mill_int_Tools_HO[Tools_HO:0]"},

["Dam"]					=	{},

["Wizard's_tower_ext"]	=	{},
					
["Wizard's_tower_int"]	=	{"Wizard's_tower_int_Maze_MG",
							"Wizard's_tower_int_Console[TowerIntMG:true]",			--миниигра Лабиринт пройдена
							"Wizard's_tower_int_Tank[TowerIntMG:true]"},

["Wizard's_tower_lab"]	=	{"Wizard's_tower_lab_Table[Close_up_Tank:2]",			--трансмукер найден
							"Wizard's_tower_lab_Unit[Close_up_Tank:2]",
							"Wizard's_tower_lab_Cache_HO[Close_up_Tank:2]"}
}

max_count_group_rooms_in_mem	= 6		-- максимальное кол-во групп комнат в памяти

group_time =
{
}
--------------------------------------------------------------------------------
function OnSerialize(system)
	local elements = 0;
	if system:IsSaving() then
		for key, value in pairs(group_time) do
			elements = elements + 1
		end
	end
	
	elements = system:Serialize(elements)

	if system:IsSaving() then
		for key, value in pairs(group_time) do
			system:Put(key)
			system:Put(value)
		end
	else
		local k, v
		for c = 1, elements do
			k = system:Serialize(k)
			v = system:Serialize(v)		
			group_time[k] = v
		end
	end
	
end
--------------------------------------------------------------------------------
function FindGroupByRoom(room_name)
	local room, countLocs, i

	for key, value in pairs(locations) do
	
		if (key == room_name) then
			return key
		end
	
		countLocs = #value
		for i = 1, countLocs do
			room = value[i]
			i = string.find(room, "[", 1, true)
			if i ~= nil then
				room = string.sub(room, 1, i - 1)
			end		
		
			if room == room_name then
				return key
			end
		end	
	end	
	
	return nil
end
--------------------------------------------------------------------------------
function AutoUnloadRooms(roomName)

	if room == nil then return
	end
	
	local room_name = room:GetName()
	
	local cur_time = os.time()
	-- ищем группу комнаты из которой выходим
	local find_group = FindGroupByRoom(room_name)
	local jump_group = FindGroupByRoom(roomName)
	
	if jump_group == nil then
		LogError("Error find group for location: " .. roomName)
	end
	
	if find_group == nil then
		LogError("Error find group for location: " .. room_name)
	else
		group_time[find_group] = cur_time
	end

--	LogError("-------------------------------")
	
	-- Лог прошедшего времени по комнатам
	local elements = 0
	for key, value in pairs(group_time) do
--		LogError( key .. " - " .. tostring(cur_time - value) )
		elements = elements + 1
	end

	-- если загруженных групп больше х
	if elements > max_count_group_rooms_in_mem then
		
		local elapsed
		local max_val = 0
		local del_group
		
		-- выбираем группу с большим временем, кроме группы в которую переходим
		for key, value in pairs(group_time) do
			if key ~= jump_group then
				elapsed = cur_time - value
				if elapsed > max_val then
					max_val = elapsed
					del_group = key
				end
			end		
		end

--		LogError("Delete group: " .. del_group)
		
		-- и удаляем
		if del_group ~= nil then
			for key, value in pairs(locations) do
				if key == del_group then
					chapter:SafeDeleteRoom(key)					
					local countLocs = #value
					local grp_room
					for i = 1, countLocs do
						chapter:SafeDeleteRoom(value[i])					
					end
					-- удаляем группу
					group_time[del_group] = nil
					break
				end
			end
		end
		
	end
	
--	LogError("------AUTO_CLEAN_AFTER--------")
--	for key, value in pairs(group_time) do
--		LogError( key .. " - " .. tostring(cur_time - value) )
--	end

end
--------------------------------------------------------------------------------
function OnJumpRoom(roomName)
	AutoUnloadRooms(roomName)
	
	for key, value in pairs(locations) do
		if key == roomName then
			local countLocs = #value				--связанные локации
			for i = 1, countLocs do
				AddLoad(value[i])					
			end
			break
		end
	end
end
--------------------------------------------------------------------------------
function AddLoad(expression)
	local i = string.find(expression, "[", 1, true)
		
	--условий нет
	if i == nil then									
		chapter:AddRoomToLoadTask(expression)
	else	
		local location = string.sub(expression, 1, i - 1)
		
		local j = string.find(expression, "]", 1, true)
		
		if j == nil then													
			LogError("Error: Wrong loading rules for locations: location " .. location .. " - expected ']'!")
	--условия есть	
		else											
			if location == "" then
				LogError("Error: Wrong loading rules for locations: empty location!")
				
			else
				local rule = string.sub(expression, i + 1, j - 1)
				if rule == "" then
					LogError("Error: Wrong loading rules for locations: location " .. location .. " - empty rule!")
					
				else
					if Parse(rule, location) then
						chapter:AddRoomToLoadTask(location)
					end
				end
			end
		end
	end
end
--------------------------------------------------------------------------------
function Parse(rule, location)
	
	--заменить условия на 1 или 0
	local ruleParse = ""
	local i = 1
	local n = string.len(rule)
	local part = ""
	local partConv = ""
	
	while i <= n  do
		local t = string.sub(rule, i, i)
		
		if (t ~= "!") and (t ~= "&") and (t ~= "|") then
			part = part .. t
		else
			if part ~= "" then
				partConv = Conversion(part, location)
				if partConv == "-1" then
					break
				end
				ruleParse = ruleParse .. partConv
			end
			ruleParse = ruleParse .. t
			part = ""
		end
	
		if i == n then
			partConv = Conversion(part, location)
			ruleParse = ruleParse .. partConv
		end
		
		i = i + 1
	end
	
	if partConv == "-1" then
		return false
	
	else	
		--обработать логическую операцию не - !
		ruleParse = Operation(ruleParse, "!")
	
		--обработать логическую операцию и - &
		ruleParse = Operation(ruleParse, "&")
	
		--обработать логическую операцию или - |
		ruleParse = Operation(ruleParse, "|")
	
		--вернуть соответствующее значение 
		if ruleParse == "1" then
			return true
		else
			return false
		end
	end
end
--------------------------------------------------------------------------------
function Conversion(part, location)
	local len = string.len(part)
	local k = string.find(part, ":", 1, true)
	if k == nil then
		LogError("Error: Wrong loading rules for locations: location " .. location .. " - no separator!")
		return "-1"
	end
	
	local key = string.sub(part, 1, k - 1)
	local value = string.sub(part, k + 1, len)
	if (key == "")  or (value == "") then
		LogError("Error: Wrong loading rules for locations: location " .. location .. " - empty key or value!")
		return "-1"
	end

	local val = cstore[key]
	if val ~= nil and tostring(val) == value then
		part = "1"
	else
		part = "0"
	end
	
	return part
end
--------------------------------------------------------------------------------
function Operation(ruleParse, op)
	local i = 1
	local n = string.len(ruleParse)
	local part = ""
	
	repeat
		local t = string.sub(ruleParse, i, i)
		
		if t == op then
			
			if op == "!" then
			
				t = string.sub(ruleParse, i + 1, i + 1)
				part = string.sub(ruleParse, 1, i - 1)
			
				if t == "1" then
					t = "0"
				elseif t == "0" then
					t = "1"
				end
					
				ruleParse = part .. t .. string.sub(ruleParse, i + 2, n)
			else
				
				local t1 = string.sub(ruleParse, i - 1, i - 1)
				local t2 = string.sub(ruleParse, i + 1, i + 1)
				part = string.sub(ruleParse, 1, i - 2)
			
				if op == "&" then
					if t1 == "1" and t2 == "1" then
						t = "1"
					else
						t = "0"
					end
				end
			
				if op == "|" then
					if t1 == "1" or t2 == "1" then
						t = "1"
					else
						t = "0"
					end
				end
			
				ruleParse = part .. t .. string.sub(ruleParse, i + 2, n)
				i = i - 1
			end
 			
		end
		
		i = i + 1
		n = string.len(ruleParse)
	until i > n
	
	return ruleParse
end