-- функция, загружающая все lua файлы из определенной директории
function load_lua_scripts(_path)
	for f in lfs.dir(_path) do
		if string.find(f, ".*%.lua") then
			quest.g_Lua.LoadScript(_path..f)
		end
	end
end

function __assert(_value, _message, _not_break)
	if sf.core.g_Application.GetDebugLevel() < sf.core.g_Application.DebugLight then return end
	
	if not _message then 
        if not _value then 
            error("assertion failed\n"..debug.traceback(), 0) 
        end
	elseif not _value then 
		__message(_message, "assertion failed")
        if not _not_break and not _value then 
            error("assertion failed\n"..debug.traceback(), 0) 
        end
    end
end

function __message(_text)
	if sf.core.g_Application.GetDebugLevel() >= sf.core.g_Application.DebugLight then
		sf.misc.MessageBox(_text, "message", 0)
	end
end

function __create_timer(_id, _parent)
    local tm = sf.core.g_Application.GetTimeManager()
    if _parent then
        _parent = tm.GetTimer(_parent)
    end
    if not _id then _id = "" end
	return sf.core.CTimerWrapper(tm.AttachTimer(_id, _parent))
end

function string_to_color(_string)
    local c = {}
    c.a, c.r, c.g, c.b = string.match(_string, "#(%d+)%s+(%d+)%s+(%d+)%s+(%d+)")
    for k,v in pairs(c) do 
        if not c[k] then return sf.graphics.Color(255, 255, 255, 255) end
        c[k] = tonumber(c[k])
        assert(c[k])
    end
    return sf.graphics.Color(c.a, c.r, c.g, c.b)
end

function string_to_bool_or_numeral(_string)
    if _string == "true" then
        return true
    elseif _string == "false" then
        return false
    else
        return tonumber(_string)
    end
end


function set_widget_flag_value(_widget, _flag, _value)
    __assert(_widget)
	if _value then
		_widget.SetFlags(sf.misc.BitwiseOr(_widget.GetFlags(), _flag))
	else
		if sf.misc.BitwiseAnd(_widget.GetFlags(), _flag) == 0 then
		else
			_widget.SetFlags(sf.misc.BitwiseXor(_widget.GetFlags(), _flag))
		end
	end
end

function copy_table(_src)
	local ret = {}
	for k,v in pairs(_src) do
		ret[k] = v
	end
	return ret
end

-- возвращает true, если таблицы отличаются
function compare_tables(_1, _2)
	for k,_ in pairs(_1) do
		if _2[k]~=_1[k] then return true end
	end
	for k,_ in pairs(_2) do
		if _2[k]~=_1[k] then return true end
	end	
	return false
end

function copy_array(_src)
	local ret = {}
	for k,v in ipairs(_src) do
		ret[k] = v
	end
	return ret
end

-- возвращает true, если массивы отличаются
function compare_arrays(_1, _2)
	local s1,s2 = #_1, #_2
	if s1~=s2 then return true end
	for i = 1,s1 do
		if _1[i]~=_2[i] then return true end
	end
	return false
end

-- наследует одну таблицу от другой
function __inherite(_derived, _base)
	for key,value in pairs(_base) do
		if _derived[key]==nil then
			_derived[key] = value
		end
	end
	
	assert(_derived.__base==nil)
	_derived.__base = _base
	return _derived
end

function default_lua_widget_handler(_actions)
	return 
	{
		DoDraw = function(_this, _renderer)
			return false
		end,

		DoUpdate = function(_this)
			return false
		end,

		OnChar = function(_this, _char, _keyboard_state, _state, _broadcast)
			return _this.SuperOnChar(_char, _keyboard_state, _state, _broadcast)
		end,

		OnKeyDown = function(_this, _key, _keyboard_state, _state, _broadcast)
			return _this.SuperOnKeyDown( _key, _keyboard_state, _state, _broadcast)
		end,

		OnKeyUp = function(_this, _key, _keyboard_state, _state, _broadcast)
			return _this.SuperOnKeyUp( _key, _keyboard_state, _state, _broadcast)
		end,

		OnMouseMove = function(_this, _pos, _state, _broadcast)
			return _this.SuperOnMouseMove( _pos, _state, _broadcast)
		end,

		OnMouseDown = function(_this, _pos, _button, _state, _broadcast)
			return _this.SuperOnMouseDown( _pos, _button, _state, _broadcast) 
		end,

		OnMouseUp = function(_this, _pos, _button, _state, _broadcast)
			return _this.SuperOnMouseUp( _pos, _button, _state, _broadcast) 
		end,

		OnDoubleClick = function(_this, _pos, _state, _broadcast)
			return _this.SuperOnDoubleClick( _pos, _state, _broadcast) 
		end,

		OnMouseWheel = function(_this, _pos, _delta, _state, _broadcast)
			return _this.SuperOnMouseWheel( _pos, _delta, _state, _broadcast)
		end,

		OnChildAction = function(_this, _action, _child)
			if not _actions or not _child then return false end
			local handler = _actions[_child.GetId().c_str()]
			if handler then handler = handler[_action.c_str()] end
			if handler then 
				local result = handler(_this, _child) 
				if result == nil then return true end
			end
			return false
		end,

		Load = function(_this, _info, _templates)
		    return true
		end
	}
end

function null_lua_widget_handler(_actions)
	return 
	{
		DoDraw = function(_this, _renderer)
			return false
		end,

		DoUpdate = function(_this)
			return false
		end,

		OnChar = function(_this, _char, _keyboard_state, _state, _broadcast)
			return false
		end,

		OnKeyDown = function(_this, _key, _keyboard_state, _state, _broadcast)
			return false
		end,

		OnKeyUp = function(_this, _key, _keyboard_state, _state, _broadcast)
			return false
		end,

		OnMouseMove = function(_this, _pos, _state, _broadcast)
			return false
		end,

		OnMouseDown = function(_this, _pos, _button, _state, _broadcast)
			return false
		end,

		OnMouseUp = function(_this, _pos, _button, _state, _broadcast)
			return false
		end,

		OnDoubleClick = function(_this, _pos, _state, _broadcast)
			return false
		end,

		OnMouseWheel = function(_this, _pos, _delta, _state, _broadcast)
			return false
		end,

		OnChildAction = function(_this, _action, _child)
			if not _actions or not _child then return false end
			
			local handler = _actions[_child.GetId().c_str()]
			if handler then handler = handler[_action.c_str()] end
			if handler then 
				local result = handler(_this, _child) 
				if result == nil then return true end
			end
			return false
		end,

		Load = function(_this, _info, _templates)
		    return true
		end
	}
end

__or = sf.misc.BitwiseOr
__and = sf.misc.BitwiseAnd
__xor = sf.misc.BitwiseXor

function get_child_widget(_parent_widget, _child_widget_id, _type_for_cast, _text )
        local casted_widget = nil
        __assert(_parent_widget)
        __assert(_child_widget_id and (_child_widget_id ~= ""))
        __assert(_type_for_cast)
        local widget = _parent_widget.GetWidget(_child_widget_id, true).get()
        if widget then
            casted_widget = __cast(widget, _type_for_cast)            
        end
        if not casted_widget and _text then
            __message(_text, "Ошибка получения виджета")
        end
        return casted_widget
end

function MoveWindowToCenter(_owner, _child_window)
	local owner_size = _owner.GetSize()
	local owner_offset = _owner.GetOffset()
	local child_size = _child_window.GetSize()
	_child_window.SetOffset(owner_size.X/2 - child_size.X/2, owner_size.Y/2 - child_size.Y/2)
end

