-- много того, что здесь реализовано, уже не нужно
-- оставил на всякий случай
amulet_effect_widget = {}

__inherite(amulet_effect_widget, null_lua_widget_handler())

function amulet_effect_widget.__CreateInstance()
    return "amulet_effect_widget"
end

local state =
{
	start = 1,
	active = 2,
	down = 3,
	finish = 4
}
function amulet_effect_widget.EnableTutorial()
    amulet_effect_widget.show_tutorial = true
end

--amulet_effect_widget.show_tutorial = false
amulet_effect_widget.tutorial_clip_offset = sf.misc.FloatVector(100, 100)
amulet_effect_widget.tutorial_clip_id = "red_arrow"
amulet_effect_widget.tutorial_text_id = "tutorial for amulet"



function amulet_effect_widget.MouseEnter()
	local self = amulet_effect_widget
	if not self._self then return false end
	
	self._visible = true
end

function amulet_effect_widget.MouseLeave()
	local self = amulet_effect_widget
	if not self._self then return false end
	
	self._visible = false
end
-- вызывается из QE
function amulet_effect_widget.Activate(_scene)
    sound("amulet_use")
    local self = amulet_effect_widget
    self._active = true
    if game then
        amulet_effect_widget._max_music_volume =  game.GetMusicVolume()
        amulet_effect_widget._max_sound_volume =  game.GetSoundVolume()
    else
        amulet_effect_widget._max_music_volume =  100
        amulet_effect_widget._max_sound_volume =  100
    end
    hints_lua_widget.HideHint()
	quest.global_scene_widget.CloseChildScenes()
    self._CreateEffect(self.state_time[state.start], self.state_time[state.finish], _scene)
	sleep(qe.GetClipTime(self._amulet))
	if self._effect then 
		self._effect:Apply() 
		self._effect = nil
	end
end

function amulet_effect_widget.TakePart(_clip)
	local self = amulet_effect_widget
	if not self._self then return end
	
	local clip = sf.misc.anim.CClip()
	clip.Load(_clip)
	clip.SetPos(clip.GetSize()/2)
	self._current_clip = clip
	
	change_state_ex(false, 0, false, "gui_amulet", "gui_amulet02")
	sleep(qe.GetClipTime(self._current_clip))
	change_state_ex(false, 0, false, "gui_amulet", "gui_amulet03")
end

function amulet_effect_widget.DoUpdate(_this)
	local self = amulet_effect_widget
	if not self._self then return false end
	
	local freeze_time = true
	if self._effect then
		if not self._effect:Update() then freeze_time = false
		else self._effect = nil end
	end
	
	if freeze_time then
		self._amulet.SetTime(self.state_time[self._active and state.active or state.start])
	end
	
	if not (self._effect or self._active) then
		local alpha = self._amulet.GetColor().Alpha + (self._visible and 1 or -1) * self._show_speed * self._timer.Get().GetFrameDelta()
		local color = sf.graphics.Color(alpha, 255, 255, 255)
		color.Clamp()
		self._SetAmuletColor(color)
	end

	if amulet_effect_widget.tutorial_arrow and amulet_effect_widget.show_tutorial then
        amulet_effect_widget.tutorial_arrow.Update()
    end

	self._amulet.Update()
	self._apply_clip.Update()
	if self._current_clip then 
		self._current_clip.Update() 
	end
	return false
end

function amulet_effect_widget.DoDraw(_this, _renderer)
	local self = amulet_effect_widget
	if not self._self then return true end
	
	self._amulet.Draw(_renderer)
	if self._current_clip then self._current_clip.Draw(_renderer) end
    if amulet_effect_widget.show_tutorial then
        if amulet_effect_widget.tutorial_arrow then
            _renderer.ApplyMatrix(sf.misc.MatrixTranslation(amulet_effect_widget.tutorial_clip_offset.X, amulet_effect_widget.tutorial_clip_offset.Y))
            amulet_effect_widget.tutorial_arrow.Draw(_renderer)
        end
    end
    return true
end

function amulet_effect_widget.OnMouseDown(_this, _pos, _button, _state, _broadcast)
	local self = amulet_effect_widget
	if not self._self then return false end
    if amulet_effect_widget.show_tutorial and self._amulet_rect.IsContains(_pos.X, _pos.Y) then
        amulet_effect_widget.show_tutorial = false
    end

	if self._effect then return true end
	
	if self._active then 
		local apply = self._apply_rect.IsContains(_pos.X, _pos.Y)
		
		local start_time = self.state_time[apply and state.active or state.down]
		self._CreateEffect(start_time, self.state_time[state.finish], apply and self._new_scene or nil)
		if apply then return true end
	end
	
    return false
end

function amulet_effect_widget.OnDoubleClick(_this, _pos, _state, _broadcast)
	return amulet_effect_widget.OnMouseDown(_this, _pos, _this.LeftButton, _state, _broadcast) 
end

function amulet_effect_widget.OnMouseMove(_this, _pos, _state, _broadcast)
	local self = amulet_effect_widget
	if not self._self then return false end
	
	if not self._effect then 
		if self._active and self._apply_rect.IsContains(_pos.X, _pos.Y) then 
			sf.gui.g_Cursor.Instance().SetCursor(sf.gui.CCursor.CursorHand)
			return true
		end
		
		if self._visible and self._amulet_rect.IsContains(_pos.X, _pos.Y) then 
			sf.gui.g_Cursor.Instance().SetCursor(sf.gui.CCursor.CursorHand)
			return true
		end
	end
		
    return self._effect~=nil
end

function amulet_effect_widget.Load(_this, _info, _templates)
	local self = amulet_effect_widget
	
	local constants = quest.game_resources.GetChild("Constants", false).GetChildRef("amulet_effect", false)
	__assert(constants, "'amulet_effect' не найден в 'properties\\constants.xml'")
	
	self.state_time = 
	{
		0,
		1000,
		4000,
		5000
	}
	self.state_time[state.active] = tonumber(constants.GetValue("active_time").c_str()) or self.state_time[state.active]
	self.state_time[state.down] = tonumber(constants.GetValue("down_time").c_str()) or self.state_time[state.down]
	self.state_time[state.finish] = tonumber(constants.GetValue("finish_time").c_str()) or self.state_time[state.finish]
	self._fade_time = tonumber(constants.GetValue("fade_time").c_str()) or 0
	
	self._change_scene_time = tonumber(constants.GetValue("change_scene_time").c_str()) or 0
	
	local amulet_clip_id = tostring(constants.GetValue("amulet_clip_id"))
	self._amulet = sf.misc.anim.CClip()
	self._amulet.Load(amulet_clip_id, true)
	self._amulet.SetPos(self._amulet.GetSize()/2)
	
	local amulet_object = qe.Clip_GetObjectById(self._amulet, "amulet")
	if amulet_object then
		self._amulet.SetTime(self.state_time[state.active])
		self._apply_rect = amulet_object.GetLocation().GetPoly().GetBoundingRect()
		self._amulet.SetTime(0)
		self._amulet_rect = amulet_object.GetLocation().GetPoly().GetBoundingRect()
	else
		__message("В клипе '"..amulet_clip_id.."' отсутствует объект с id='amulet'", "Error")
		self._apply_rect = sf.misc.FloatRect(0, 0, 100, 100)
		self._amulet_rect = sf.misc.FloatRect(0, 0, 100, 100)
	end
	

    local res = constants.GetValue("tutorial_clip").c_str()
    if res ~= "" then amulet_effect_widget.tutorial_clip_id = res end

    local res = constants.GetValue("tutorial_text_id").c_str()
    if res ~= "" then amulet_effect_widget.tutorial_text_id = res end
          
    res = tonumber(constants.GetValue("tutorial_offset_x").c_str())
    if res ~= nil then amulet_effect_widget.tutorial_clip_offset.X = res end
    res = tonumber(constants.GetValue("tutorial_offset_y").c_str())
    if res ~= nil then amulet_effect_widget.tutorial_clip_offset.Y = res end


    amulet_effect_widget.tutorial_arrow = sf.misc.anim.CClip()
    amulet_effect_widget.tutorial_arrow.Load(amulet_effect_widget.tutorial_clip_id)
    amulet_effect_widget.tutorial_arrow.SetPos(sf.misc.FloatVector(0, 0))
    amulet_effect_widget.tutorial_arrow.SetTime(0)



	local apply_clip_id = tostring(constants.GetValue("apply_clip_id"))
	self._apply_clip = sf.misc.anim.CClip()
	self._apply_clip.Load(apply_clip_id, true)
	self._apply_clip.SetPos(self._apply_clip.GetSize()/2)
	self._apply_clip.SetTime(30000) -- проматываем клип, чтобы он ничего не отображал
	over_scene_effect_widget.SetAmuletApplyEffectClip(self._apply_clip)
	
	self._timer = sf.core.CTimerWrapper(sf.core.g_Application.GetTimeManager().AttachTimer("", nil))
	self._active = false
	self._timer.Get().SetTime(self.state_time[state.start])
	
	self._show_speed = 255 / (tonumber(constants.GetValue("time_to_show").c_str()) or 500)
	self._visible = false
	
	self._SetAmuletColor(sf.graphics.Color(0, 255, 255, 255))
	
	self._self = _this
	
    return true
end

function amulet_effect_widget.UserClick(_new_scene) -- DEPRECATED
	local self = amulet_effect_widget
	if not self._effect then 
		self._new_scene = _new_scene
		self._CreateEffect(self.state_time[state.start], self.state_time[state.active]) 
	end
end

function amulet_effect_widget._SetAmuletColor(_color)
	local self = amulet_effect_widget
	
	self._amulet.SetColor(_color)
	self._apply_clip.SetColor(_color)
end

function amulet_effect_widget._CreateEffect(_from_time, _to_time, _new_scene)
	local self = amulet_effect_widget
	
	assert(quest.global_current_script_object)
	local current_amulet_id = tostring(quest.global_current_script_object.GetIdRef())
	--assert(current_amulet_id=="gui_amulet_past" or current_amulet_id=="gui_amulet_present")
	--local other_amulet_id = (current_amulet_id=="gui_amulet_past" and "gui_amulet_present") or "gui_amulet_past"
	
	self._SetAmuletColor(sf.graphics.Color(255, 255, 255, 255))
	self._timer.Get().SetTime(_from_time)
	self._amulet.SetTime(_from_time)
	
	quest.global_cursor.SetHintText("", false)
	
	--change_state_ex(false, 0, false, current_amulet_id, current_amulet_id.."02")
	
	if _new_scene then self._apply_clip.SetTime(0) end
	
	self._effect = 
	{
		to_time = _to_time,
		need_apply = _new_scene ~= nil,
		new_scene = _new_scene,
		current_amulet = current_amulet_id,
		other_amulet = other_amulet_id,
		last_scene = nil,
		
		Apply = function(self)
			local amulet = amulet_effect_widget
			
			if self.need_apply then
				show_scene(self.new_scene)
			end
			
		--	change_state_ex(false, 0, false, self.current_amulet, self.current_amulet.."01")
		--	change_state_ex(false, 0, false, self.other_amulet, self.other_amulet.."01")
			amulet._timer.Get().SetTime(self.to_time)
			amulet._active = not amulet._active
			over_scene_effect_widget.SetScene(nil)
            if self.last_scene then child_scenes.disable_scene_sounds(self.last_scene.GetScene()) end
            amulet_effect_widget.MouseLeave()
		end,
		
		Update = function(self)
			local amulet = amulet_effect_widget
			local cur_time = amulet._timer.Get().GetTime()
			
			if self.need_apply and cur_time >= amulet._change_scene_time then
				-- момент перехода между сценами
				self.need_apply = false
			--	change_state_ex(false, 0, false, self.other_amulet, self.other_amulet.."02")
				
				self.last_scene = qe.CSceneWidget("standart", false, quest.game_resources.GetChild("GUITemplates", true))
				self.last_scene.SetScene(quest.global_scene_widget.GetScene())
				local scene_pos = quest.global_scene_widget.GetAbsPos(true)
				self.last_scene.SetOffset(scene_pos.X, scene_pos.Y)
				over_scene_effect_widget.SetScene(self.last_scene)
				show_scene(self.new_scene)
			end
            if self.need_apply then
				-- меняем громкость звуков до смены сцены
                local koef = cur_time / amulet._change_scene_time
               -- sf.core.g_Application.GetAudioManager().SetGroupVolume("sound", (1 - koef) * amulet_effect_widget._max_sound_volume)
               -- sf.core.g_Application.GetAudioManager().SetGroupVolume("music", (1 - koef) * amulet_effect_widget._max_music_volume)
            end
			if cur_time < self.to_time then
                if not self.need_apply then
					-- меняем громкость звуков после смены сцены
                    local koef = (cur_time - amulet._change_scene_time)/(self.to_time - amulet._change_scene_time)
					local mus_volume = (koef) * amulet_effect_widget._max_music_volume
					local sound_volume = (koef) * amulet_effect_widget._max_sound_volume
                 --   sf.core.g_Application.GetAudioManager().SetGroupVolume("sound", sound_volume)
                 --   sf.core.g_Application.GetAudioManager().SetGroupVolume("music", mus_volume)
					
					-- плавно прячем предыдущую сцену
					local fade_koef = amulet._fade_time>0 and (cur_time - amulet._change_scene_time)/(amulet._fade_time) or 1
					local color = sf.graphics.Color(255*(1 - fade_koef), 255, 255, 255)
					color.Clamp()
					self.last_scene.SetColor(color)
                end
                return false
            end
			-- момент завершения эффекта смена сцен
			self:Apply()
			return true
		end
	}
end
