-- common functions

common_swf_table = {}
elemProps = {}
element_fly_animation = { elem_props = {} }

elementUpdateFuncs = {}
common_event_listeners = {}
common = {}
common.hintEffect = "firework"
common.hintable_elements = {}
common.hidden_elements = {}
local hidden_elements_all = 0
local hidden_elements_found = 0
common_all_hidden_clickable = false

common.chapter = "unknown"
common.hidEffect = "Item_onPick_up"
common.hidFlyEffect = "item_fly"

global_hack_mode = false

----------------------------------------------------------------------------------------------------
function print_pos(elem, world)
	console:print(elem:getName().." pos: "..elem:getPos(world).x.." "..elem:getPos(world).y)
end

----------------------------------------------------------------------------------------------------
function common.set_chapter(name)
	common.chapter = name
	common.hidEffect = "Item_onPick_up_"..common.chapter
	common.hidFlyEffect = "item_fly_"..common.chapter
end

----------------------------------------------------------------------------------------------------
function common.clear_level()
	log_message("common.clear_level()")
	inventory.reset()
	---------------------------------------main_panel():hideMsg(true)
	elemProps = {}
	element_fly_animation.elem_props = {}
	common.hintable_elements = {}
	
	common.hidden_elements = {}
	hidden_elements_all = 0
	hidden_elements_found = 0
	
	--inventory.Elems = {}
	--inventory.collectElems = {}
	--inventory.incrementElems = {}		
end

----------------------------------------------------------------------------------------------------
function show_msg(text)
	getMainPanel():showMsg(text, 0)
end

----------------------------------------------------------------------------------------------------
function show_msg_ex(text, script)
	getMainPanel():showMsgEx(text, 0, script)
end

function set_no_check_win_by_script(val, lev)
	if lev == nil then
		lev = get_current_level():getName()
	end
	set_no_check_win_by_script_c(val, lev)
end

----------------------------------------------------------------------------------------------------
function create_ioc_element(name, no_check_exist, no_add_to_main_panel)
	
	--create_script_element(name)
	
	local el = find_element(name)
	
	table.insert(common.hintable_elements, name)
										
--	set_roll(name, true, "over_hand")
	
	el:setEventHandler(eiLeftClick, "common_event_listeners.to_inventory(\""..name.."\")")
	el:setActive(true)
	--set_callback_for_element(name, )
	
end

----------------------------------------------------------------------------------------------------
function create_ioc_elements(elem_table, no_check_exist)

	for i = 1, #elem_table do
		create_ioc_element(elem_table[i], no_check_exist)
	end
	
end

----------------------------------------------------------------------------------------------------
function printVec(v)
	console:print("Vector: x="..v.x.." y="..v.y.." z="..v.z)
end

----------------------------------------------------------------------------------------------------
function common.init_level()
	hidden_elements_all = 0
	hidden_elements_found = 0
end

----------------------------------------------------------------------------------------------------
function common.get_hids_all()
	return hidden_elements_all
end

----------------------------------------------------------------------------------------------------
function common.get_hids_left()
	return hidden_elements_all - hidden_elements_found
end

----------------------------------------------------------------------------------------------------
function common.get_hids_found()
	return hidden_elements_found
end


----------------------------------------------------------------------------------------------------
function common.hack_show_hids(val)

	for i = 1, #common.hidden_elements do
	
		local el = get_current_level():getElementByName(common.hidden_elements[i])
		if el ~= nil then
		
			if val == true then
				el:setEventListener(eiUpdate, "elements_rotate")
			else
				el:rotate(0)
				el:setEventListener(eiUpdate, "")
			end		
		end	
	end
		
end

local ang = 0
----------------------------------------------------------------------------------------------------
function elements_rotate(elem, dt)

	ang = ang + dt*3
	elem:rotate(ang)
	
end

----------------------------------------------------------------------------------------------------
function common_hint()

	console:print("common.hint")
	if #common.hintable_elements == 0 then
		return 0
	end
	
	--[[local htable = common.hintable_elements
	while #htable ~= 0 do
		local rand = get_random(1, #htable + 1)
		if can_be_hinted(htable[rand]) then
			start_effect(common.hintEffect, htable[rand])
			play_sound("rcuh")
			return 1
		end
		table.remove(htable, rand)
	end]]
	for i = 1, #common.hintable_elements do
		if can_be_hinted(common.hintable_elements[i]) then
			start_effect(common.hintEffect, common.hintable_elements[i])
			console:print("hinted: "..common.hintable_elements[i])
			return 1
		end
	end
	
	return 0
	
end

----------------------------------------------------------------------------------------------------
function table.find(table1, val)

	for i = 1, #table1 do
		if table1[i] == val then
			return i
		end	
	end
	
	return -1
		
end

----------------------------------------------------------------------------------------------------
function get_element(name)
	return find_element(name)
	--return get_current_level():getElementByName(name)
end

----------------------------------------------------------------------------------------------------
function common_event_listeners.hidden_click(name)
	
	if true then --main_panel():isElementVisible(name) or common_all_hidden_clickable == true then
		local el = get_current_level():getElementByName(name)
		play_sound("rcuh")
		
		hidden_elements_found = hidden_elements_found + 1
		set_callback_for_element(name, "")
		el:rotate(0)
		el:setEventListener(eiUpdate, "")
		
		element_fly_to_main_panel(el);
		play_movie_clip_ex(name, 1,1)
		table.remove(common.hintable_elements, table.find(common.hintable_elements, name))
	else
		ret_wrong_click()
		add_wrong_click()
	end
	
end

----------------------------------------------------------------------------------------------------
function common.create_hidden_element(name)

	console:print("create_hidden_element "..name)
	local elem = create_script_element(name)
	
	table.insert(common.hidden_elements, name)
	
	hidden_elements_all = hidden_elements_all + 1
	set_callback_for_element(name, "common_event_listeners.hidden_click(\""..name.."\")")
	add_element_to_main_panel(name)

	return elem
end

----------------------------------------------------------------------------------------------------
function common.create_elements(params)
	elements_list = {}
	get_all_chars("_char_parse_handler", false)
	
	console:print("common.create_elements")
	
	local hidStr = "_hid"
	
	if params.hiddenStr ~= nil then
		hidStr = params.hiddenStr
	end
	
	for i = 1, #elements_list do
		local bg, en, name
		name = elements_list[i]
		
		if get_element(name) == nil then
			if params.noCreateHids == nil then
				be, en = string.find(name, hidStr)
					
				if en == string.len(name) then
					if params.checkNameFunc == nil or params.checkNameFunc(name) == true then
						common.create_hidden_element(name)
					end
				end
			end
			
			
			if params.noCreateAng == nil then
				be, en = string.find(name, "_ang")
					
				if en == string.len(name) then
					if params.checkNameFunc == nil or params.checkNameFunc(name) == true then
						create_script_element(name)
						play_movie_clip_loop(name, -1, -1)				
					end
				end
			end
		else
			log_message("common.create_elements: element "..name.." already exists.")
		end
	end
end


----------------------------------------------------------------------------------------------------
function _char_parse_handler(name)
	table.insert(elements_list, name)
end

----------------------------------------------------------------------------------------------------
function get_char_list()
	
	elements_list = {}
	get_all_chars("_char_parse_handler", false)
	return elements_list
		
end

----------------------------------------------------------------------------------------------------
function get_chars_by_full_name(partname)
	
	elements_list = {}
	get_all_chars("_char_parse_handler", false)
	
	local el_list = {}
	
	for i = 1, #elements_list do
		local full_name = get_char_full_name(elements_list[i])
		if string.find(full_name, partname) ~= nil then
			table.insert(el_list, elements_list[i])
		end
	end	
	
	return el_list		
end

----------------------------------------------------------------------------------------------------
function for_elements_in(name, func)
	console:print("for_elements_in "..name)
	local count = 0
	for a, name in pairs(get_chars_by_full_name(name.."\\")) do
		console:print("   element "..name)
		func(name)
		count = count + 1
	end
	
	return count
end

----------------------------------------------------------------------------------------------------
function print_all_chars()

	local chars = get_char_list()
	
	for i = 1, #chars do
		console:print(chars[i])
	end
end

----------------------------------------------------------------------------------------------------
function start_level_fade(level)
	set_fade_cb_script("start_level(\""..level.."\")")
	start_fade_out()
end

----------------------------------------------------------------------------------------------------
function add_hintable_element(name)
	table.insert(common.hintable_elements, name)
end

----------------------------------------------------------------------------------------------------
function remove_hintable_element(name)
	local ind = table.find(common.hintable_elements, name)
	if ind ~= -1 then
		table.remove(common.hintable_elements, ind)
	end
end

----------------------------------------------------------------------------------------------------
function add_element_to_main_panel(name, no_add_hintable)

	--[[
	main_panel():addElement(name)
	if no_add_hintable == nil then
		add_hintable_element(name)
	end
	]]
end

----------------------------------------------------------------------------------------------------
function delete_element_from_main_panel(name)
	--main_panel():notify(name)
	--remove_hintable_element(name)	
end

----------------------------------------------------------------------------------------------------
function print_hintable()
	for i = 1, #common.hintable_elements do
		console:print(common.hintable_elements[i])
	end
end


----------------------------------------------------------------------------------------------------
--function common.create_ao_element(name)
--	create_element(name)
--	set_callback_for_element(name, "play_movie_clip(\""..name.."\") set_callback_for_element(\""..name.."\", \"\")")
--end

----------------------------------------------------------------------------------------------------
function play_sound_rnd(snd_name, soundsCount)

	local needIndex = math.random(soundsCount)
	console:print("play_sound_rnd: "..snd_name..needIndex)
	play_sound(snd_name..needIndex)
	
end

----------------------------------------------------------------------------------------------------
function dbg_log_state()

	log_message("DEBUG GAME STATE -----------------------------------------------------------------")
	log_message("Hids: total:"..common.get_hids_all()..", found:"..common.get_hids_found()..", left:"..common.get_hids_left())
	
	if #common.hidden_elements > 0 then
		log_message("Hidden elements:")
		
		for i = 1, #common.hidden_elements do
			log_message("   "..common.hidden_elements[i])
		end
	end

	log_message("")
	if #common.hintable_elements > 0 then
		log_message("Hintable elements:")
		
		for i = 1, #common.hintable_elements do
			log_message("   "..common.hintable_elements[i])
		end
	end
	
	log_message("")
	log_message("Named characters:")
	local chars = get_char_list()
	table.sort(chars)
	
	for i = 1, #chars do
		log_message(chars[i])
	end
	
	log_message("-----------------------------------------------------------------")

end

----------------------------------------------------------------------------------------------------
function play_ambient_sound(snd)

	if is_sound_playing(snd) == false then
		stop_sounds()
		play_sound_loop(snd)
	end
	
end

----------------------------------------------------------------------------------------------------
common_delta_volume = 0

----------------------------------------------------------------------------------------------------
function music_fade_out()
	common_delta_volume = get_volume(false) / 10
	common_prev_volume = get_volume(false)

	add_timer("set_volume(false, get_volume(false) - "..common_delta_volume..")", 0.2, 8);
end

----------------------------------------------------------------------------------------------------
function music_fade_in()
	add_timer("set_volume(false, get_volume(false) + "..common_delta_volume..")", 0.2, 8);
end

----------------------------------------------------------------------------------------------------
function add_frame_listener(clipName, frameIndex, scriptFunc)
	add_timer("__frame_listener(\""..clipName.."\", "..frameIndex..", \""..scriptFunc.."\")", 0.1, 0)
end

----------------------------------------------------------------------------------------------------
function __frame_listener(clipName, frameIndex, scriptFunc)
	--log_message("__frameListener "..clipName.." "..frameIndex)
	if get_current_frame(clipName) >= frameIndex then
		exec_string(scriptFunc)
		delete_current_timer()
	end
end

----------------------------------------------------------------------------------------------------
function set_frame_listener(elem, label, func)

    local frame = 0
    if type(label) == "number" then -- frame passed
        frame = label
    else							
        frame = elem:getCharacter():get_labeled_frame(label) -- label name passed
    end
    
    timer_mgr:add_timer(
        function()
            if elem:getCharacter():get_current_frame() >= frame then
                func()
                log_message("remove on_clip_label "..frame)
                timer_mgr:remove_current_timer() --timer(clipName.."_wait_timer"..label)
            else
                log_message("wait frame:"..frame..", cur frame:"..elem:getCharacter():get_current_frame())
            end
        end, 0) -- each frame

end

----------------------------------------------------------------------------------------------------
function test_levels()

end

----------------------------------------------------------------------------------------------------
function play_sounds_all()
	add_timer("play_sound(get_random_sound())", 1, 0)
end

----------------------------------------------------------------------------------------------------
function trace(msg)
    if decoda_output ~= nil then 
        decoda_output(msg)
    end
    log_message(msg)
end

local fails = {}
function ids_fail(ids)
    if fails[ids] == nil and decoda_output ~= nil then
        --trace(ids..'\tString ID not found')
        decoda_output(ids)
        --trace(ids)
        log_message(ids)
        fails[ids] = 1
    end
end

local warnings = {}
function ids_warning(ids)
    if warnings[ids] == nil then
        trace('WARNING: Non localized string: '..ids)
        warnings[ids] = 1
    end
end

function on_key(aChar, aScan)
    Input:onKey({char = aChar, scan = aScan})
end

function get_sys_time()
    local gentable = loadstring("return "..getCurrentTime())
    return gentable()
end

local ids_reg = {}
function register_ids(ids, str)
    ids_reg[ids] = str
end

function flush_ids_reg()
    local outfile = io.open('used_ids.txt', 'wt')
    table.foreach(ids_reg, function(ids) outfile:write(ids..';'..ids_reg[ids]..'\n') end)   
	outfile:close()
end

function quit_confirm()
    --shutdown()
    QuitConfirm:show()
end

----------------------------------------------------------------------------------------------------

exec_script("Version.lua")

--exec_script("complex.lua")
exec_script("Pickle.lua")
exec_script("matrix.lua")

exec_script("Profile.lua")
exec_script("ProfileList.lua")

exec_script("_testHid.lua")
exec_script("_inventory.lua")
exec_script("_from_code.lua")
exec_script("_update.lua")
exec_script("Input.lua")

exec_script("FlowChart.lua")
exec_script("Media.lua")

exec_script("level_mgr.lua")
exec_script("inventory.lua")
exec_script("common.lua")
exec_script("ho.lua")
exec_script("Hint.lua")
exec_script("inv.lua")

exec_script("Scheduler.lua")

exec_script("FlyPath_2.lua")
exec_script("FlyPath.lua")

exec_script("Tutorial.lua")

exec_script("Closeup.lua")
exec_script("HOLevel.lua")
exec_script("Location.lua")
exec_script("EditTextElement.lua")

exec_script("Level.lua")
exec_script("Levels.lua")

exec_script("Water.lua")

exec_script("CollapseChip.lua")
exec_script("CollapseCore.lua")

exec_script("Match2Core.lua")

exec_script("TextTwist.lua")

exec_script("Match2Layout1.lua")
exec_script("Match2Layout2.lua")
exec_script("Match2Layout3.lua")
exec_script("Match2Layout4.lua")
exec_script("Match2Layout5.lua")
exec_script("Match2Layout6.lua")
exec_script("Match2Layout7.lua")
exec_script("Match2Layout8.lua")
exec_script("Match2Layout9.lua")
exec_script("Match2Layout10.lua")
exec_script("Match2Layout11.lua")

exec_script("HOLevelExtra.lua")

--set_func_on_activate("exec_script(\"_testHid.lua\")")