--[[
MCM keybind wrapper
28may2022
This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License
Author: RavenAscendant

Wraps engine keybinds in an MCM keybind to allow using MCM keybind modifiers and modes on those keys
--]]

local free_keys_t = ini_file_ex("plugins\\mcm_key_wrap\\free_keys.ltx"):collect_section("free")
local free_keys = {}
for k,v in pairs(free_keys_t) do free_keys[#free_keys+1] = k end
local action_names = ini_file_ex("plugins\\mcm_key_wrap\\action_names.ltx"):collect_section("names")
local wraps = ini_file_ex("plugins\\mcm_key_wrap\\wraps.ltx")
local key_to_dik = ini_file_ex("plugins\\mcm_key_wrap\\key_to_DIK.ltx"):collect_section("keys")
local dik_to_key = invert_table(key_to_dik)
local blocked = wraps:collect_section("blocked")
local virtual = wraps:collect_section("virtual")
local virtualized = wraps:collect_section("virtualized")
for k,v in pairs(virtualized) do  virtualized[k] = str_explode(v,",") end
local commented = wraps:collect_section("commented")
local custom_handeling = wraps:collect_section("custom_handeling")
for k,v in pairs(custom_handeling) do  custom_handeling[k] = str_explode(v,",") end
local missing_keys = {	kQUICK_USE_1 = 61,	kQUICK_USE_2= 62,	kQUICK_USE_3 =63,	kQUICK_USE_4=64, kACTIVE_JOBS = 51, kARTEFACT = 28,kDETECTOR= 21, kSPRINT_TOGGLE= 7, kPREV_SLOT= 58,kPAUSE =38, kNEXT_SLOT =57}




local mcm_keybinds = ui_mcm and ui_mcm.key_hold and true --there will be a better way to test for MCM versions soon, but this will always be a solid way to check for keybind support

local ui_keybinding_tbl = utils_xml.XmlParser:loadFile(getFS():update_path('$game_config$', '').."ui\\ui_keybinding.xml") --if they have a moded version of this file it will be loaded
if not ui_keybinding_tbl then
	ui_keybinding_tbl = utils_xml.XmlParser:loadFile(getFS():update_path('$game_config$', '').."plugins\\mcm_key_wrap\\ui_keybinding.xml") --if no moded version load referance copy
end

dbg = mcm_log.new("DBG")
dbg.enabled = true
dbg.continuous = true
--dbg:log_table(ui_keybinding_tbl, "key xml")

local function allowed(key)
	return  not (blocked[key.exe] or commented[key.id])
end



local options 
local all_keys = {}
local handeling_funcs = {}
local modifier_dik = {[DIK_keys.DIK_RCONTROL] = true, [DIK_keys.DIK_LCONTROL] = true, [DIK_keys.DIK_RSHIFT] = true, [DIK_keys.DIK_LSHIFT] = true, [DIK_keys.DIK_RMENU] = true, [DIK_keys.DIK_LMENU] = true}
local display_key = {}
local mm = nil
local function save_mm(m) mm = m end
function unbind_disabled()
	for exe, path in pairs(all_keys) do
		if path and (ui_mcm.get("mcm/key_wrapper/"..path.."/".. exe .. "_enable") == false) then
			ui_mcm.set("mcm/key_wrapper/"..path.."/".. exe .. "_key", -1)
		end
	end
end

local function level_present() return ui_options.level_present() or AddScriptCallback end
local process_settings
function on_mcm_load()
	if AddScriptCallback then
		RegisterScriptCallback("mcm_option_change", process_settings)
	end
	RegisterScriptCallback("main_menu_on_init",save_mm)
	RegisterScriptCallback("on_option_change",on_option_change)
	if not mcm_keybinds then return end --do nothing if old mcm
	if options then return options, "mcm" end --gets niled if there is a reason to remake it, so other wise recycle
	all_keys = {}
	options = {
	id = "key_wrapper",
	sh = false,
	text = "ui_mcm_key_wrapper",
	
	gr = {
		{id = "about", sh = true,text = "ui_mcm_key_wrap_about", gr ={
			{id = "key_wrap", type = "slide", link = "ui_options_slider_control", text = "ui_mcm_key_wrap_about", size = {512, 50}, spacing = 20},
			{ id= "desc_mcm"    	 	,type= "desc"     ,text= "ui_mcm_key_wrap_about_text"			 },
			{ id= "unbind_disabled"  		       ,type= "button"   ,functor_ui= {unbind_disabled}      },

		}}
		}
    }
	for j =1, #ui_keybinding_tbl.ChildNodes do		
		local node =  ui_keybinding_tbl.ChildNodes[j]
		t = {
			{id = node.Attributes.name, type = "slide", link = "ui_options_slider_control", text = node.Attributes.name, size = {512, 50}, spacing = 20},

		}
		local first = true
		for i=1, #node.ChildNodes do	
			local key = node.ChildNodes[i].Attributes
			if allowed(key) then
				all_keys[key.exe] = node.Attributes.name
				display_key[key.exe] = key.id
				if not first then
					table.insert(t,{ id= "line"					,type= "line"	  })
				else
					first = false
				end
				table.insert(t,{ id= "desc_mcm"    	 	,type= "title", align = "l"     ,text= key.id			 } )
				local func = custom_handeling[key.exe] and custom_handeling[key.exe][1] or "default_mcm"
				handeling_funcs[func](t,key)
			end
			
		end
	
		if not first then table.insert(options.gr,{id = node.Attributes.name, sh = true, gr = t, text = node.Attributes.name, precondition = {level_present} ,output = "ui_mcm_key_wrapper_not_level_present",}) end
		
		
	end
	return options, "mcm"
end

	
local function insert_type(t, key)
	if virtual[key.exe] then
		table.insert(t,{ id= "desc_mcm"   ,type= "desc"   ,text= "ui_mcm_key_wrapper_virtual"	 ,clr= {255,0,175,0}	})
	elseif virtualized[key.exe] then
		table.insert(t,{id = key.exe .. "_v", type = "check", val = 1, def=true, hint = "key_wrapper_v"}	)
	else
		table.insert(t,{ id= "desc_mcm"   ,type= "desc"   ,text= "ui_mcm_key_wrapper_redirect"	 ,clr= {255,175,0,0}	})
	end
end

local function insert_enable(t,key)
	table.insert(t,{id = key.exe .. "_enable", type = "check", val = 1, def=false, hint = "key_wrapper_enable"}	)
end

local function def_bind(key)
	local temp = bind_to_dik(key_bindings[action_names[key.exe]] or missing_keys[action_names[key.exe]], 0)
	return temp == 0 and -1 or temp
end

local function insert_bind(t,key)
	table.insert(t,  {id = key.exe .. "_key",type = "key_bind",hint = "key_wrapper_bind", val = 2, def= -1})
	table.insert(t,{ id= "desc_mcm"   ,type= "desc"   ,text= "ui_mcm_key_wrapper_modkey"	 ,clr= {255,175,0,0}	, precondition = {function () return modifier_dik[ui_mcm.get("mcm/key_wrapper/"..all_keys[key.exe].."/"..key.exe .. "_key")] end}})
end


local function insert_m_and_m(t,key)
	table.insert(t,{id = key.exe .. "_modifier", type = ui_mcm.kb_mod_radio, val = 2, def = 0, hint = "mcm_kb_modifier" , content= { {0,"mcm_kb_mod_none"} , {1,"mcm_kb_mod_shift"},{2,"mcm_kb_mod_ctrl"} ,{3,"mcm_kb_mod_alt"}}})
    table.insert(t,{id = key.exe .. "_mode", type = ui_mcm.kb_mod_radio, val = 2, def = 0, hint = "mcm_kb_mode" , content= { {0,"mcm_kb_mode_press"} , {1,"mcm_kb_mode_dtap"} , {2,"mcm_kb_mode_hold"}}})
end


function handeling_funcs.default_mcm(t,key)
	insert_enable(t,key)
	insert_type(t, key)
	insert_bind(t,key)
	insert_m_and_m(t,key)
end

function handeling_funcs.geiger_mcm(t,key)
	insert_enable(t,key)
	insert_type(t, key)
	insert_bind(t,key)
	table.insert(t,{ id= "desc_mcm"   ,type= "desc"   ,text= "ui_mcm_key_wrapper_geiger"	 ,clr= {255,175,0,0}	})
end
local toggles = {
		crouch = "control/general/crouch_toggle",
		llookout = "control/general/lookout_toggle",
		rlookout = "control/general/lookout_toggle",
		sprint_toggle = "control/general/sprint_toggle",
		accel = "control/general/walk_toggle",
	}

function handeling_funcs.toggle_mcm(t,key)
		
		table.insert(t,{ id= "desc_mcm"   ,type= "desc"   ,text= "ui_mcm_key_wrapper_toggle"	 ,clr= {255,175,0,0}, precondition = {function () return not ui_options.get(toggles[key.exe]) end} 	})
		table.insert(t,{id = key.exe .. "_enable", type = "check", val = 1, def=false, hint = "key_wrapper_enable", precondition = {function () return ui_options.get(toggles[key.exe]) end}} 	)		
		table.insert(t,  {id = key.exe .. "_key",type = "key_bind",hint = "key_wrapper_bind", val = 2, def= def_bind(key), precondition = {function () return ui_options.get(toggles[key.exe]) end}})
		table.insert(t,{ id= "desc_mcm"   ,type= "desc"   ,text= "ui_mcm_key_wrapper_modkey"	 ,clr= {255,175,0,0}	, precondition = {function () return modifier_dik[ui_mcm.get("mcm/key_wrapper/"..all_keys[key.exe].."/"..key.exe .. "_key")] and ui_options.get(toggles[key.exe]) end}} )
		table.insert(t,{id = key.exe .. "_modifier", type = ui_mcm.kb_mod_radio, val = 2, def = 0, hint = "mcm_kb_modifier" , content= { {0,"mcm_kb_mod_none"} , {1,"mcm_kb_mod_shift"},{2,"mcm_kb_mod_ctrl"} ,{3,"mcm_kb_mod_alt"}}, precondition = {function () return ui_options.get(toggles[key.exe]) end}})
		table.insert(t,{id = key.exe .. "_mode", type = ui_mcm.kb_mod_radio, val = 2, def = 0, hint = "mcm_kb_mode" , content= { {0,"mcm_kb_mode_press"} , {1,"mcm_kb_mode_dtap"} , {2,"mcm_kb_mode_hold"}}, precondition = {function () return ui_options.get(toggles[key.exe]) end}})

end

function handeling_funcs.mtoggle_mcm(t,key)
	handeling_funcs.toggle_mcm(t,key)
end

local wraps_by_key = {}
local rebound_actions_by_key = {}
local rebound_keys_by_action = {}
local virtualized_listeners = {}
local active_redirects = {}
local active_virtuals = {}
local virtual_DIK = 1001
local free_key_idx = 1
local wraps_disabled_msgs = {}
local dik_num_to_bind




local function create_virtuals(list, removed_virtuals)
	dbg:log_table(list, "create_virtuals" )
	for exe, path in pairs(list) do
		
		if custom_handeling[exe] and custom_handeling[exe][2] and handeling_funcs[custom_handeling[exe][2]] then
			handeling_funcs[custom_handeling[exe][2]](exe, path, removed_virtuals)--custom handeling will need to acomplish the same results as the code below
		else
			local mcm_bind = ui_mcm.get("mcm/key_wrapper/"..path.."/".. exe .. "_key")
			if modifier_dik[mcm_bind] then
				removed_virtuals[exe] = path
				wraps_disabled_msgs[exe] = "ui_mcm_key_wrapper_bind_modifier"
			else
				local modifier = ui_mcm.get("mcm/key_wrapper/"..path.."/".. exe .. "_modifier")
				local mode = ui_mcm.get("mcm/key_wrapper/"..path.."/".. exe .. "_mode")
				wraps_by_key[mcm_bind] = wraps_by_key[mcm_bind] or {}
				wraps_by_key[mcm_bind][mode] = wraps_by_key[mcm_bind][mode] or {}
				if wraps_by_key[mcm_bind][mode][modifier] then
					removed_virtuals[exe] = path
					wraps_disabled_msgs[exe] = "ui_mcm_key_wrapper_bind_conflict"
				else
					
					active_virtuals[exe] = path
					rebound_actions_by_key[virtual_DIK] = key_bindings[action_names[exe]] or missing_keys[action_names[exe]]
					rebound_keys_by_action[key_bindings[action_names[exe]] or missing_keys[action_names[exe]]] = virtual_DIK
					dbg:log("virtuals: %s:%s", exe, virtual_DIK)
					wraps_by_key[mcm_bind][mode][modifier] = virtual_DIK
					if  axr_main.config:r_value("mcm_key_wrap", exe, 0,"") == "" then --only store the previus key bind if none is stored
						axr_main.config:w_value("mcm_key_wrap", exe,    dik_num_to_bind[bind_to_dik(key_bindings[action_names[exe]]  or missing_keys[action_names[exe]])])
						axr_main.config:save()
					end
					exec_console_cmd("unbind "..exe)
					virtual_DIK = virtual_DIK + 1
				end
			end
		end
	end
	dbg:log_table(rebound_actions_by_key, "rebound_actions_by_key" )
end


		
	
local function create_redirects(list, removed_redirects)
	dbg:log_table(list, "create_redirects" )
	for exe, path in pairs(list) do
		
		if free_key_idx > #free_keys then
			removed_redirects[exe] = path
			wraps_disabled_msgs[exe] = "ui_mcm_key_wrapper_too_many_redirects" 
		elseif custom_handeling[exe] and custom_handeling[exe][2] and handeling_funcs[custom_handeling[exe][2]] then
			dbg:log("custom handeling, exe:%s ch:%s",exe,custom_handeling[exe][2])
			handeling_funcs[custom_handeling[exe][2]](exe, path, removed_redirects)--custom handeling will need to acomplish the same results as the code below
		else
			local mcm_bind = ui_mcm.get("mcm/key_wrapper/"..path.."/".. exe .. "_key")
			if modifier_dik[mcm_bind] then
				removed_redirects[exe] = path
				wraps_disabled_msgs[exe] = "ui_mcm_key_wrapper_bind_modifier" 
			else
				local modifier = ui_mcm.get("mcm/key_wrapper/"..path.."/".. exe .. "_modifier")
				local mode = ui_mcm.get("mcm/key_wrapper/"..path.."/".. exe .. "_mode")
				wraps_by_key[mcm_bind] = wraps_by_key[mcm_bind] or {}
				wraps_by_key[mcm_bind][mode] = wraps_by_key[mcm_bind][mode] or {}
				if wraps_by_key[mcm_bind][mode][modifier] then
					removed_redirects[exe] = path
					wraps_disabled_msgs[exe] = "ui_mcm_key_wrapper_bind_conflict"
				else
					active_redirects[exe] = path
					if  axr_main.config:r_value("mcm_key_wrap", exe, 0,"") == "" then --only store the previus key bind if none is stored
						axr_main.config:w_value("mcm_key_wrap", exe,    dik_num_to_bind[bind_to_dik(key_bindings[action_names[exe]]  or missing_keys[action_names[exe]])])
						axr_main.config:save()
					end
					exec_console_cmd("bind "..exe .. " " .. free_keys[free_key_idx])
					dbg:log("re bind: ".."bind "..exe .. " " .. free_keys[free_key_idx])
					wraps_by_key[mcm_bind][mode][modifier] = DIK_keys[key_to_dik[free_keys[free_key_idx]]]
					free_key_idx = free_key_idx + 1
				end
			end
		end
	end
end

function virtualize(list, removed_virtuals)
	for exe, path in pairs(list) do
		
		if custom_handeling[exe] and custom_handeling[exe][2] and handeling_funcs[custom_handeling[exe][2]] then
			dbg:log("custom handeling, exe:%s ch:%s",exe,custom_handeling[exe][2])
			handeling_funcs[custom_handeling[exe][2]](exe, path, removed_virtuals)--custom handeling will need to acomplish the same results as the code below
		else
			local mcm_bind = ui_mcm.get("mcm/key_wrapper/"..path.."/".. exe .. "_key")
			if modifier_dik[mcm_bind] then
				removed_virtuals[exe] = path
				wraps_disabled_msgs[exe] = "ui_mcm_key_wrapper_bind_modifier"
			else
				local modifier = ui_mcm.get("mcm/key_wrapper/"..path.."/".. exe .. "_modifier")
				local mode = ui_mcm.get("mcm/key_wrapper/"..path.."/".. exe .. "_mode")
				wraps_by_key[mcm_bind] = wraps_by_key[mcm_bind] or {}
				wraps_by_key[mcm_bind][mode] = wraps_by_key[mcm_bind][mode] or {}
				if wraps_by_key[mcm_bind][mode][modifier] then
					removed_virtuals[exe] = path
					wraps_disabled_msgs[exe] = "ui_mcm_key_wrapper_bind_conflict"
				else
					active_virtuals[exe] = path
					rebound_actions_by_key[virtual_DIK] = key_bindings[action_names[exe]] or missing_keys[action_names[exe]]
					rebound_keys_by_action[key_bindings[action_names[exe]] or missing_keys[action_names[exe]]] = virtual_DIK
					wraps_by_key[mcm_bind][mode][modifier] = virtual_DIK
					virtualized_listeners[virtual_DIK] = function () this[virtualized[exe][1]](unpack(virtualized[exe],2)) end
					if  axr_main.config:r_value("mcm_key_wrap", exe, 0,"") == "" then --only store the previus key bind if none is stored
						axr_main.config:w_value("mcm_key_wrap", exe,    dik_num_to_bind[bind_to_dik(key_bindings[action_names[exe]]  or missing_keys[action_names[exe]])])
						axr_main.config:save()
					end
					exec_console_cmd("unbind "..exe)

					
					virtual_DIK = virtual_DIK + 1
				end
			end
		end
	end
end



function handeling_funcs.geiger_post(exe, path, removed_virtuals)
			local mcm_bind = ui_mcm.get("mcm/key_wrapper/"..path.."/".. exe .. "_key")
			if modifier_dik[mcm_bind] then
				removed_virtuals[exe] = path
				wraps_disabled_msgs[exe] = "ui_mcm_key_wrapper_bind_modifier"
			else
				wraps_by_key[mcm_bind] = wraps_by_key[mcm_bind] or {}
				wraps_by_key[mcm_bind][0] = wraps_by_key[mcm_bind][0] or {}
				if wraps_by_key[mcm_bind][0][0] or wraps_by_key[mcm_bind][0][1] then
					removed_virtuals[exe] = path
					wraps_disabled_msgs[exe] = "ui_mcm_key_wrapper_bind_conflict"
				else
					active_virtuals[exe] = path
					rebound_actions_by_key[virtual_DIK] = key_bindings[action_names[exe]] 
					rebound_keys_by_action[key_bindings[action_names[exe]]] = virtual_DIK
					dbg:log("geiger_post: %s:%s", exe, virtual_DIK)
					wraps_by_key[mcm_bind][0][0] = virtual_DIK
					wraps_by_key[mcm_bind][0][1] = virtual_DIK
					virtual_DIK = virtual_DIK + 1
				end
			end
end

function handeling_funcs.toggle_post(exe, path, removed_redirects)
		dbg:log("toggle_post")
		
		if toggles[exe] and not ui_options.get(toggles[exe]) then
			removed_redirects[exe] = path
			wraps_disabled_msgs[exe] = "ui_mcm_key_wrapper_bind_toggle" 
		else
			local mcm_bind = ui_mcm.get("mcm/key_wrapper/"..path.."/".. exe .. "_key")
			if modifier_dik[mcm_bind] then
				removed_redirects[exe] = path
				wraps_disabled_msgs[exe] = "ui_mcm_key_wrapper_bind_modifier" 
			else
				local modifier = ui_mcm.get("mcm/key_wrapper/"..path.."/".. exe .. "_modifier")
				local mode = ui_mcm.get("mcm/key_wrapper/"..path.."/".. exe .. "_mode")
				wraps_by_key[mcm_bind] = wraps_by_key[mcm_bind] or {}
				wraps_by_key[mcm_bind][mode] = wraps_by_key[mcm_bind][mode] or {}
				if wraps_by_key[mcm_bind][mode][modifier] then
					removed_redirects[exe] = path
					wraps_disabled_msgs[exe] = "ui_mcm_key_wrapper_bind_conflict"
					dbg:log("%s %s  mcm_bind=%s mode=%s, modifier=%s", game.translate_string("ui_mcm_key_wrapper_bind_conflict"),exe,mcm_bind , mode,modifier)
				else
					active_redirects[exe] = path
					if  axr_main.config:r_value("mcm_key_wrap", exe, 0,"") == "" then --only store the previus key bind if none is stored
						axr_main.config:w_value("mcm_key_wrap", exe,    dik_num_to_bind[bind_to_dik(key_bindings[action_names[exe]]  or missing_keys[action_names[key.exe]])])
						axr_main.config:save()
					end
					exec_console_cmd("bind "..exe .. " " .. free_keys[free_key_idx])
					dbg:log("re bind: ".."bind "..exe .. " " .. free_keys[free_key_idx])
					dbg:log("wrap:mcm_bind=%s mode=%s, modifier=%s dik=%s",mcm_bind , mode,modifier,DIK_keys[key_to_dik[free_keys[free_key_idx]]])
					wraps_by_key[mcm_bind][mode][modifier] = DIK_keys[key_to_dik[free_keys[free_key_idx]]]
					free_key_idx = free_key_idx + 1
				end
			end
		end
end
			




local function remove_redirects(removed_redirects)
	for exe, path in pairs(removed_redirects) do
		ui_mcm.set("mcm/key_wrapper/"..path.."/".. exe .. "_enable", false)
		local old_bind = axr_main.config:r_value("mcm_key_wrap", exe, 0,"")
		if  old_bind ~= "" then --only rebind if the previus key is stored
			exec_console_cmd("bind "..exe .. " " .. old_bind)
			dbg:log("old bind: ".."bind "..exe .. " " .. old_bind)
			axr_main.config:remove_line("mcm_key_wrap", exe)
			axr_main.config:save()
		end
	end
end
function quick_use(num)
	if level.present() and (not Check_UI()) then
			local quick_item = get_console_cmd(0,"slot_" .. (num-1))
			if quick_item and ini_sys:section_exist(quick_item) then
				local obj = db.actor:object(quick_item)
				if obj then
					if (CInventory__eat(obj) == false) then
						return
					end
					actor_menu.set_msg(2, "Used: "..game.translate_string(SYS_GetParam(0, obj:section(), "inv_name")))
					db.actor:eat(obj)
				end
			end
	end
end




function process_settings(initial) --declared local at top of script
	if initial then ui_mcm.get("mcm/mcm_log/debug_logging2") end
	if not dik_num_to_bind then
		dik_num_to_bind = {}
		for key, dik in pairs(key_to_dik) do
			dik_num_to_bind[DIK_keys[dik]] = key
		end
	end
	--dbg:log_table(all_keys,"all_keys")
	local virtuals_parse = {}
	local removed_virtuals = {}
	local staying_redirects = {}
	local new_redirects = {}
	local removed_redirects = {}
	local to_virtualize = {}
	for exe, path in pairs(all_keys) do
		if path and ui_mcm.get("mcm/key_wrapper/"..path.."/".. exe .. "_enable") then
			if virtual[exe] then
				virtuals_parse[exe] = path
			elseif virtualized[exe] and ui_mcm.get("mcm/key_wrapper/"..path.."/".. exe .. "_v") then
				to_virtualize[exe] = path
			elseif active_redirects[exe] then
				staying_redirects[exe] = path
			else
				new_redirects[exe] = path
			end
		end
	end
	for exe, path in pairs(active_redirects) do
		if not staying_redirects[exe] then
			removed_redirects[exe] = path
		end
	end

	for exe, path in pairs(active_virtuals) do
		if not virtuals_parse[exe] or to_virtualize[exe] then
			removed_virtuals[exe] = path
		end
	end
	wraps_by_key = {}
	wraps_disabled_msgs = {}
	active_redirects = {}
	free_key_idx = 1
	create_redirects(staying_redirects, removed_redirects)
	create_redirects(new_redirects, removed_redirects)
	remove_redirects(removed_redirects)
	
	rebound_actions_by_key = {}
	rebound_keys_by_action = {}

	virtual_DIK = 1001
	active_virtuals = {}
	create_virtuals(virtuals_parse, removed_virtuals)
	virtualized_listeners = {}
	virtualize(to_virtualize, removed_virtuals)
	remove_redirects(removed_virtuals)
	dbg:log_table(wraps_by_key, "wraps_by_key")
end

local function show_messages()
	if is_empty(wraps_disabled_msgs) or not mm then return end
	
	local txt = ""
	local cnt = 0
	for k, v in pairs(wraps_disabled_msgs) do
		txt = txt ..game.translate_string(display_key[k]).." : "..game.translate_string(v)
		cnt = cnt + 1
	end
	--local GUI = main_menu.get_main_menu()
	mm.mbox_mode = 0
	mm.message_box:InitMessageBox("message_box_error")
	mm.message_box:SetText(cnt.." "..game.translate_string("ui_mcm_key_wrapper_wraps_were_disabled")..txt)
	mm.message_box:ShowDialog(true)
	--mm:SetMsg(txt,20)
	wraps_disabled_msgs = {}

end



local toggle_start_v = {}

function on_option_change(mcm)
	local toggle_change = false
	
	for k, path in pairs(toggles) do
		local t = ui_options.get(path)
		if t ~= toggle_start_v[k] then
			toggle_start_v[k] = t
			toggle_change = true
		end
	end
	if toggle_change or mcm and not AddScriptCallback then
		process_settings()
	end
end


	
local function on_key_press(key)
	if wraps_by_key[key] then
		for i = 0, 3 do 
			if ui_mcm.get_mod_key(i)  then
				if wraps_by_key[key][0] and wraps_by_key[key][0][i] then
					ui_mcm.simple_press("mcm_key_wrap" .. wraps_by_key[key][0][i]..i, key, function () 
																	level.press_action(wraps_by_key[key][0][i])
																	level.release_action(wraps_by_key[key][0][i])
																end)
				end
				if  wraps_by_key[key][1] and wraps_by_key[key][1][i] and ui_mcm.double_tap("mcm_key_wrap"..wraps_by_key[key][1][i],key..i) then
					level.press_action(wraps_by_key[key][1][i])
					level.release_action(wraps_by_key[key][1][i])
				end
				
			end
		end
	end
				
end

local function on_key_hold(key)
	if wraps_by_key[key] and wraps_by_key[key][2] then
		for i = 0, 3 do 
			if wraps_by_key[key][2][i] and ui_mcm.get_mod_key(i) and ui_mcm.key_hold("mcm_key_wrap"..wraps_by_key[key][2][i]..i,key) then 
				level.press_action(wraps_by_key[key][2][i])
				level.release_action(wraps_by_key[key][2][i])
			end
		end
	end	
end

local function on_key_release(key)
	if virtualized_listeners[key] then
		 virtualized_listeners[key]()
	end
end
local function GUI_on_hide(gui)
	if gui == "UIMCM" or gui == "UIOptions" then
		show_messages()
	end
end


local function save_mm2(a,b, m)
	mm = m
end

function on_game_start()
    RegisterScriptCallback("on_option_change",on_option_change)
    RegisterScriptCallback("GUI_on_hide",GUI_on_hide)
    RegisterScriptCallback("main_menu_on_keyboard",save_mm2)
    RegisterScriptCallback("on_key_hold",on_key_hold)
    RegisterScriptCallback("on_key_press",on_key_press)
    RegisterScriptCallback("on_key_release",on_key_release)
	process_settings(true)
	if AddScriptCallback then
		RegisterScriptCallback("mcm_option_change", process_settings)
	end
	local old_dik_to_bind = _G.dik_to_bind
	function _G.dik_to_bind(num)
		return rebound_actions_by_key[num] or old_dik_to_bind(num)
	end

	local old_bind_to_dik = _G.bind_to_dik
	function _G.bind_to_dik(num)
		return rebound_keys_by_action[num] or old_bind_to_dik(num)
	end
end