-- модуль который занимается отображением различных туториалов
tutorial_window = {}

__inherite(tutorial_window, null_lua_widget_handler())

function tutorial_window.__CreateInstance()
    return "tutorial_window"
end

function tutorial_window.SetPostShowEvent(_function)
	tutorial_window._post_show_function = _function
end

function tutorial_window.Show(_owner, _event, _widget_info, _obj_pos, _effect_pos1, _effect_pos2, _effect_pos3, _text)
	tutorial_window._post_show_function = nil
	local app = sf.core.g_Application
	
	tutorial_window._target_widget_info = _widget_info
	
	local tutorial_info = app.GetSettings().GetChild("Constants", false).GetChildRef("tutorial", false)
	assert(tutorial_info, "В файле constants.xml не найдены настройки туториала")
	if not tutorial_info then 
		return
	end
	
	assert(tutorial_info.IsValue("fade_in_time"))
	assert(tutorial_info.IsValue("fade_out_time"))
	
	tutorial_window._fade_in_time = tonumber(tutorial_info.GetValue("fade_in_time").c_str())
	tutorial_window._fade_out_time = tonumber(tutorial_info.GetValue("fade_out_time").c_str())
	
	
	tutorial_window._timer = __create_timer()
	tutorial_window._pressed = false
	
	local event_info = tutorial_info.GetChildByAttributeRef("event", "id", _event, false)
	assert(event_info, "В файле constants.xml не найдены настройки туториала на событие \"".._event.."\"")
	if not event_info then 
		return
	end

	tutorial_window._disable_pause = nil
	if event_info.GetValue("disable_pause").c_str() == "true" then
		tutorial_window._disable_pause = true
	end
	
	tutorial_window._close_on_click = nil
	if event_info.GetValue("close_on_click").c_str() == "true" then
		tutorial_window._close_on_click = true
	end
		
	tutorial_window._mask_texture = nil
	if event_info.IsValue("mask_texture") then
		tutorial_window._mask_texture = app.GetResourceManager().GetTexture(event_info.GetValue("mask_texture"))			
	end	
	
	tutorial_window._mask_pos = nil
	if tutorial_window._mask_texture then
		if event_info.IsValue("mask_pos") then
			tutorial_window._mask_pos = StringToFloatVector(event_info.GetValue("mask_pos").c_str())
		end
	else
		tutorial_window._fade_in_time = 0
		tutorial_window._fade_out_time = 0
	end
	
	tutorial_window._can_close = false
	
	tutorial_window._mask_color = sf.graphics.Color(150,0,0,0)
	if event_info.IsValue("mask_color") then
		tutorial_window._mask_color = string_to_color(event_info.GetValue("mask_color").c_str())
	end
	
	tutorial_window._obj_pos = _obj_pos
	if event_info.IsValue("obj_pos") then
		tutorial_window._obj_pos = StringToFloatVector(event_info.GetValue("obj_pos").c_str())
	end
	
	
	
	tutorial_window._dialog = nil
	if event_info.IsValue("dialog_id") then
		tutorial_window._dialog = sf.gui.CWindow()
		tutorial_window._dialog.Load(
			app.GetSettings().GetChild("GUI", false).GetChildByAttribute("window", "id", event_info.GetValue("dialog_id"), true), 
			app.GetSettings().GetChild("GUITemplates", false))
		
		if _text then
			local text_widget = get_child_widget(tutorial_window._dialog, "tutorial_text", sf.gui.CLabelWidget, "ошибка" )
			if text_widget then
				text_widget.SetText(_text)
			end
		end
		
		tutorial_window._dialog.UpdateLayout()
	end
	
	if not tutorial_window._disable_pause then
		app.GetTimeManager().GetTimer("game_timer").SetK(0)
	end
	
	tutorial_window._window = sf.gui.CWindow()
	tutorial_window._window.Load(
		app.GetSettings().GetChild("GUI", false).GetChildByAttribute("window", "id", "tutorial_window", true), 
		app.GetSettings().GetChild("GUITemplates", false))
	tutorial_window._window.UpdateLayout()
	
	_owner.AddChildWindow(tutorial_window._window)
	
	if tutorial_window._obj_pos then	
		local window_size = tutorial_window._window.GetSize()
		--[[
				|
			1	|	2
		----------------|----------------
			3	|	4
				|
		]]
		local location = 1
		if tutorial_window._obj_pos.X > window_size.X / 2 then
			location = location + 1
		end
		if tutorial_window._obj_pos.Y > window_size.Y / 2 then
			location = location + 2
		end
		
		local angles = { -math.pi / 4, math.pi / 4, -3 * math.pi / 4, 3 * math.pi / 4}
		
		if tutorial_window._obj_pos.X < 0 and tutorial_window._obj_pos.Y < 0 then
			MoveWindowToCenter(tutorial_window._window, tutorial_window._dialog)
			tutorial_window._window.AddChildWindow(tutorial_window._dialog)
		else
		
		
			local pointer = sf.gui.CClipWidget("", 1, 0)
			pointer.GetClip().Load("red_arrow_resources_window")
			local pointer_size = pointer.GetClip().GetViewSize()
			tutorial_window._window.AddWidget(pointer)
			
			local m = sf.misc.MatrixTranslation(-pointer_size.X / 2, 0)
			m = m * sf.misc.MatrixRotation(angles[location], 0, 0)
			m = m * sf.misc.MatrixTranslation(tutorial_window._obj_pos.X, tutorial_window._obj_pos.Y)
			pointer.SetRotation(m)
			
			if tutorial_window._dialog then
				local dialog_size = tutorial_window._dialog.GetSize()
				local offsets = { {0,0}, {-dialog_size.X,0}, {0,-dialog_size.Y}, {-dialog_size.X,-dialog_size.Y} }
				
				local o = sf.misc.FloatVector(0, pointer_size.Y)
				o = o * sf.misc.MatrixRotation(angles[location], 0, 0)
				o = o * sf.misc.MatrixTranslation(tutorial_window._obj_pos.X, tutorial_window._obj_pos.Y)

				tutorial_window._dialog.SetOffset(o.X + offsets[location][1], o.Y + offsets[location][2])		
				tutorial_window._window.AddChildWindow(tutorial_window._dialog)
			end
		end
	else
		MoveWindowToCenter(tutorial_window._window, tutorial_window._dialog)
		tutorial_window._window.AddChildWindow(tutorial_window._dialog)
	end
	
	tutorial_window.visual_effects = nil
	
	local poss = {_effect_pos1, _effect_pos2, _effect_pos3}
	for i=1,3 do
		local attr_effect_id = "effect"..i.."_id"
		local attr_effect_pos = "effect"..i.."_pos"
		if event_info.IsValue(attr_effect_id) and not event_info.GetValue(attr_effect_id).empty() then
			local effect_pos = poss[i]
			if event_info.IsValue(attr_effect_pos) and not event_info.GetValue(attr_effect_pos).empty() then
				effect_pos = StringToFloatVector(event_info.GetValue(attr_effect_pos).c_str())
			end
			if effect_pos then
				if not tutorial_window.visual_effects then
					tutorial_window.visual_effects = visual_effects.CreateEffectsList()
				end
				tutorial_window.visual_effects:CreateInstantEffect(event_info.GetValue(attr_effect_id).c_str(), effect_pos, __create_timer().Get())
			end
		end
	end
end

function tutorial_window._Close()
	if not tutorial_window._disable_pause then
		sf.core.g_Application.GetTimeManager().GetTimer("game_timer").SetK(1)
	end
	tutorial_window._window.AddFlags(tutorial_window._window.FlagDead)
	if tutorial_window._post_show_function then
		tutorial_window._post_show_function()
	end
end

function tutorial_window.Close()
	tutorial_window._timer.Get().SetK(-1)
	tutorial_window._timer.Get().SetTime(tutorial_window._fade_out_time)
end

function tutorial_window.DoUpdate(_this)
	if tutorial_window._target_widget_info and tutorial_window._target_widget_info.flags.update then
		tutorial_window._target_widget_info.widget.Update()
	end

	if tutorial_window.visual_effects then
		tutorial_window.visual_effects:Update()
	end
	
	local k = tutorial_window._timer.Get().GetK()
	local t = tutorial_window._timer.Get().GetTime()
	
	if k > 0 and t >= tutorial_window._fade_in_time then
		tutorial_window._can_close = true
	end
	
	if k < 0 and t <= 0 then
		tutorial_window._Close()
	end
	
	return false
end

function tutorial_window.DoDraw(_this, _renderer)
	if tutorial_window._mask_texture and tutorial_window._mask_pos then
		local alpha = tutorial_window._mask_color.Alpha
		local k = 0
		if tutorial_window._timer.Get().GetK() > 0 then
			k = tutorial_window._timer.Get().GetTime() / tutorial_window._fade_in_time
			if k > 1 then k = 1 end
		else
			k = tutorial_window._timer.Get().GetTime() / tutorial_window._fade_out_time
			if k < 0 then k = 0 end
		end
		alpha = alpha * k
		local color = sf.graphics.Color(alpha, tutorial_window._mask_color.Red, tutorial_window._mask_color.Green, tutorial_window._mask_color.Blue)
		s11.misc.RenderBorderedImage(_renderer, tutorial_window._mask_texture, tutorial_window._mask_pos.X, tutorial_window._mask_pos.Y, color, nil)
	end
	if tutorial_window._target_widget_info and tutorial_window._target_widget_info.flags.draw then
		tutorial_window._target_widget_info.widget.Draw(_renderer)
	end
	if tutorial_window.visual_effects then
		tutorial_window.visual_effects:PreDraw(_renderer)
		tutorial_window.visual_effects:PostDraw(_renderer)
	end
    return false
end

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

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

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

function tutorial_window.OnMouseMove(_this, _pos, _state, _broadcast)
	if 	tutorial_window._target_widget_info and tutorial_window._target_widget_info.flags.on_mouse_move then
		if _broadcast or tutorial_window._target_widget_info.widget.GetPoly().IsContains(_pos.X, _pos.Y) then
			tutorial_window._target_widget_info.widget.OnMouseMove(
				tutorial_window._target_widget_info.widget.AdaptPos(_pos), _state, _broadcast)
		end
	end
	return _this.SuperOnMouseMove(_pos, _state, _broadcast) 
end

function tutorial_window.OnMouseDown(_this, _pos, _button, _state, _broadcast)
	if tutorial_window._close_on_click or (tutorial_window._mask_texture and tutorial_window._can_close) then
		tutorial_window._pressed = true
		if 	tutorial_window._target_widget_info and tutorial_window._target_widget_info.flags.on_mouse_down and 
			tutorial_window._target_widget_info.widget.GetPoly().IsContains(_pos.X, _pos.Y) then
				tutorial_window._target_widget_info.widget.OnMouseDown(tutorial_window._target_widget_info.widget.AdaptPos(_pos), _button, _state, _broadcast)
		end
	end
	return _this.SuperOnMouseDown(_pos, _button, _state, _broadcast) 
end

function tutorial_window.OnMouseUp(_this, _pos, _button, _state, _broadcast)
	if tutorial_window._target_widget_info and tutorial_window._target_widget_info.flags.on_mouse_up then
		tutorial_window._target_widget_info.widget.OnMouseUp(tutorial_window._target_widget_info.widget.AdaptPos(_pos), _button, _state, _broadcast)
	end
	if tutorial_window._pressed then
		tutorial_window.Close()
	end
	return _this.SuperOnMouseUp(_pos, _button, _state, _broadcast) 
end

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

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

function tutorial_window.OnChildAction(_this, _action, _child)
end

tutorial_dialog = {}

function tutorial_dialog.DoDraw(_this, _renderer) 
    return false 
end

function tutorial_dialog.DoUpdate(_this) 
    return false 
end

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

function tutorial_dialog.OnKeyDown(_this, _key, _keyboard_state, _state, _broadcast)
	if _key == 27 or _key == 13 then
		tutorial_window.Close()
	end
    return _this.SuperOnKeyDown( _key, _keyboard_state, _state, _broadcast)
end

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

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

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

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

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

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

function tutorial_dialog.OnChildAction(_this, _action, _child)
	if not _child then return end
	if _action.c_str() ~= "pressed" then return end
	tutorial_window.Close()
end

