level_hints = {}

function level_hints.Init()
	__assert(qe.CLevelHints, "qe.CLevelHints")
	
	if level_hints._generate_hints then
		level_hints.GenerateLevelHints(quest.global_quest_window, quest.global_played_level, quest.global_cursor, objects_box_lua_widget.objects_list, quest.global_scene_widget)
	else
		level_hints.LoadHints(quest.global_played_level, quest.global_level_box, quest.global_scene_widget)
	end
end

function level_hints.EnableHintGeneration(_win_minigame_table)
	level_hints._generate_hints = true
	level_hints._win_minigame_table = _win_minigame_table
end

function level_hints.LoadHints(_level, _inventory, _scene_widget)
	level_hints._hints = qe.CLevelHints(_level, _inventory, _scene_widget)
end

function level_hints.ShowHint()
	if not level_hints._hints then return end
	
	local object = level_hints._hints.GetHintObject()
	if not object.empty() then
		hint_to_object(tostring(object))
	end
end

function level_hints.GetCursorsTable()
	if not level_hints._hints then return {} end
	
	local actions = qe.CLevelHints.ObjectsActionsT()
	level_hints._hints.GetObjectActions(actions)
	
	local cursor_table = {}
	
	local can_apply_cursor = level_hints._cursors[qe.CLevelHints.ActionCanApply]
	cursor_table[can_apply_cursor] = {}
	local obj_in_cursor = quest.global_cursor.GetCursorObject()
	if obj_in_cursor then
		local can_apply_actions = actions.at(qe.CLevelHints.ActionCanApply)
		local i, e = can_apply_actions.begin(), can_apply_actions._end()
		while i~=e do
			if i.value.first.GetIdRef() == obj_in_cursor.GetIdRef() then
				cursor_table[can_apply_cursor][tostring(i.value.second.GetIdRef())] = true
			end
			i.inc()
		end
	else
		-- иконка на миниигры и минисцены меняется только с пустым курсором
		local miniscene_cursor = level_hints._cursors[qe.CLevelHints.ActionMiniscene]
		cursor_table[miniscene_cursor] = cursor_table[miniscene_cursor] or {}
		local open_miniscene_action = actions.at(qe.CLevelHints.ActionMiniscene)
		local i, e = open_miniscene_action.begin(), open_miniscene_action._end()
		while i~=e do
			local obj = tostring(i.value.first.GetIdRef())
			cursor_table[miniscene_cursor][obj] = true
			i.inc()
		end
		
		local minigame_cursor = level_hints._cursors[qe.CLevelHints.ActionMinigame]
		cursor_table[minigame_cursor] = cursor_table[minigame_cursor] or {}
		local open_minigame_action = actions.at(qe.CLevelHints.ActionMinigame)
		local i, e = open_minigame_action.begin(), open_minigame_action._end()
		while i~=e do
			local obj = tostring(i.value.first.GetIdRef())
			cursor_table[minigame_cursor][obj] = true
			i.inc()
		end
	end
	
	local exit_cursor = level_hints._cursors[qe.CLevelHints.ActionCompleteLevel]
	cursor_table[exit_cursor] = cursor_table[exit_cursor] or {}
	local end_level_action = actions.at(qe.CLevelHints.ActionCompleteLevel)
	local i, e = end_level_action.begin(), end_level_action._end()
	while i~=e do
		local obj = tostring(i.value.first.GetIdRef())
		cursor_table[exit_cursor][obj] = true
		i.inc()
	end
	
	return cursor_table
end

function level_hints.GetPossibleTakeObjects()
	if not level_hints._hints then return nil end
	
	local objects = qe.CLevelHints.ObjectsT()
	level_hints._hints.GetPossibleTakeObjects(objects)
	
	local result = {}
	local i, e = objects.begin(), objects._end()
	while i~=e do
		table.insert(result, i.value)
		i.inc()
	end
	return result
end

function level_hints.GenerateLevelHints(_window, _level, _cursor, _inventory, _scene_widget)
	add_task = function() end
	complete_task = function() end
	reopen_task = function() end
	say = function() end
	show_scene = function(_id) level_hints._leveltester.SceneOpened(_id) end
	complete_level = function() level_hints._leveltester.LevelComplete() end
	pre_click_event = function() end
	post_click_event = function() end
	commit_score = function() end
	add_score = function() end
	drop_incorect_click = function() end
	add_incorect_click = function() end
	local last_take = take
	take = function(...) 
		local taken_id = last_take(...) 
		if taken_id then level_hints._leveltester.ObjectTaken(taken_id) end 
	end
	minigame = function(_id) 
		level_hints._leveltester.Minigame()
		if not level_hints._win_minigame_table then return true end
		
		local level_minigame_win_table = level_hints._win_minigame_table[tostring(level_hints._level.GetId())]
		if not level_minigame_win_table then return true end
		local win_table = level_minigame_win_table[_id]
		if not win_table then return true end
		
		for _,scene in ipairs(win_table.scenes or {}) do
			if not level_hints._leveltester.IsSceneOpened(scene) then return false end
		end
		
		for obj,state_id in pairs(win_table.objects_states or {}) do
			if not state(obj, state_id) then return false end
		end
		
		return true 
	end
	
	visual_effects._DisableEffects(true)
	
	level_hints._hints = nil
	level_hints._level = _level
	
	level_hints._leveltester = qe.CLevelHintsGenerator(_level, _cursor, _inventory, _scene_widget)
	level_hints._mainwindow = _window
	form_event([[
		local file = io.open("hints.log", "a+")
		file:write("Generating hints for level ']].._level.GetId().c_str()..[['...\n")
		file:flush()

		local time = os.time()
		local success = level_hints._leveltester.Generate() 
		if success then
			file:write("... end generation ( time: "..os.difftime(os.time(), time).." sec, states: "..level_hints._leveltester.GetStatesCount().." )\n")
		else
			file:write("... generation FAILED( time: "..os.difftime(os.time(), time).." sec )\n")
		end
		file:close()
		
		level_hints._mainwindow.EndModal(2) 
		level_hints._mainwindow = nil
	]])
	
	CreateScript = function (_funcname, ...)
		local chunk, err = loadstring(_funcname.."(...)")
		if chunk then chunk(...) else g_ThreadManager.Error(err) end
	end 
	form_event = function() end
	sleep = function() end
	Wait = function() end
end

function level_hints._UpdateMainScene(_main_scene)
	quest.global_current_main_scene = _main_scene
end

level_hints._generate_hints = false
level_hints._hints = nil
level_hints._leveltester = nil
level_hints._win_minigame_table = nil
level_hints._level = nil
level_hints._cursors = 
{
	[qe.CLevelHints.ActionCanApply] = "gui_cursors_pointer_use",
	[qe.CLevelHints.ActionMinigame] = "gui_cursors_magnifier",
	[qe.CLevelHints.ActionMiniscene] = "gui_cursors_magnifier",
	[qe.CLevelHints.ActionCompleteLevel] = "gui_cursors_exit",
	[qe.CLevelHints.ActionTaken] = ""
}
