hints_timer = sf.core.CTimerWrapper(sf.core.g_Application.GetTimeManager().GetTimer(_T("qe_level")).AttachTimer(_T("")))
hints_timer = sf.core.CTimerWrapper(sf.core.g_Application.GetTimeManager().GetTimer(_T("qe_level")).AttachTimer(_T("")))


hints_lua_widget = hints_lua_widget or {}

hints_lua_widget.hint_button_timer = sf.core.CTimerWrapper(sf.core.g_Application.GetTimeManager().GetTimer(_T("qe_level")).AttachTimer(_T("")))

hints_lua_widget.self = nil

hints_lua_widget.update_effect = nil

hints_lua_widget.show_time = 3000

hints_lua_widget.fly_time = 1000

hints_lua_widget.working_hints_count = 1000

hints_lua_widget.update_time = 5000

hints_lua_widget.koef_hint_refreshtime = 1.5

hints_lua_widget.pre_hint_tutorial_delay = 2000
hints_lua_widget.hint_tutorial_show_time = 2000
hints_lua_widget.tutorial_arrow_offset = sf.misc.FloatVector(0, -50)
hints_lua_widget.tutorial_image_id = "red_arrow"

hints_lua_widget.show_hint_tutorial = nil
hints_lua_widget.enable_hint_tutorial = true

hints_lua_widget.image_offset = sf.misc.FloatVector(-25, -14)
hints_lua_widget.traget_size = sf.misc.FloatVector(50, 28)

hints_lua_widget.progres_image_id = "gui_game_gui_button_hint_progress"

function hints_lua_widget.disable_hint_tutorial(_value)
    hints_lua_widget.enable_hint_tutorial = not _value
    tutorial.drop_timer()

end

function hints_lua_widget.get_disable_hint_tutorial()
    return not hints_lua_widget.enable_hint_tutorial
end


function hints_lua_widget.set_show_hint_tutorial(_value)
    hints_lua_widget.show_hint_tutorial = _value
end

function hints_lua_widget.get_show_hint_tutorial()
    return hints_lua_widget.show_hint_tutorial
end

hints_lua_widget.current_effects_map = {}

function hints_lua_widget.HideHint(_pos, _size)
    
    if _pos and _size and hints_lua_widget.current_hint_pos then
        local left_angle = _pos
        local right_angle = _pos + _size
        local widget_pos = hints_lua_widget.current_hint_pos
        if not (left_angle.X<widget_pos.X and left_angle.Y<widget_pos.Y and widget_pos.X<right_angle.X and widget_pos.Y<right_angle.Y) then
            return
        end
        
    end

    hints_lua_widget.InsertEffect("hint", nil)
end

function hints_lua_widget.InsertEffect(_effect_id, _effect)
    if hints_lua_widget.current_effects_map[_effect_id] ~= nil then
        hints_lua_widget.current_effects_map[_effect_id]:InstantApply()
    end
    hints_lua_widget.current_effects_map[_effect_id] = _effect
end

function hints_lua_widget.CreateObjectHintEffect()
    local new_effect = 
    {
        Init = function(_self, _scene_object_ptr, _start_time, _total_time, _start_pos )

            _self.start_pos = _start_pos
            _self.particle_effect = hints_lua_widget.effects_list:CreateEffect("ShowHint", _self.start_pos)            

            _self.start_time = _start_time
            _self.total_time = _total_time
            _self.end_time = _self.start_time + _self.total_time

        end,

        Draw = function(_self, _renderer)
        end,

        Update = function(_self, _time)
            if _time > _self.end_time then
                _self:InstantApply()
            end
        end,

        InstantApply = function(_self)
            if not _self.is_dead then
                _self.particle_effect:Kill(false)
            end
            _self.is_dead = true
        end,
        is_dead = false,
    }
    return new_effect
end

function hints_lua_widget.CreateTakeHintEffect()
    local new_take_effect = 
    {
        Init = function(_self, _scene_object_ptr, _start_time, _total_time, _start_pos )

            _self.start_pos = _start_pos
            _self.fly_obj_pos = _start_pos
            _self.particle_effect = hints_lua_widget.effects_list:CreateEffect("TakeHint", _self.fly_obj_pos)            

            _self.DrawState = qe.FindObjectInventCondition(_scene_object_ptr)
            _self.start_time = _start_time
            _self.total_time = _total_time
            _self.end_time = _self.start_time + _self.total_time
        end,

        Draw = function(_self, _renderer)
                if _self.fly_obj_pos and _self.DrawState then
                    local object_pos = _self.DrawState.GetPos()
                    _renderer.PushState()
                    _renderer.ApplyMatrix( sf.misc.MatrixTranslation(-object_pos.X + _self.fly_obj_pos.X , - object_pos.Y + _self.fly_obj_pos.Y))
                    _self.DrawState.DrawGame(_renderer)
                    _renderer.PopState()
                end
        end,

        Update = function(_self, _time)
            local koef = (_time - _self.start_time)/_self.total_time

            _self.fly_obj_pos = objects_box_lua_widget.SimpleFlyFunction( _self.start_pos, sf.misc.FloatVector(0,  0), koef)

            _self.particle_effect:SetPos( sf.misc.FloatVector(_self.fly_obj_pos.X, _self.fly_obj_pos.Y))

            if _time > _self.end_time then
                _self:InstantApply()
            end
        end,

        InstantApply = function(_self)
            if not _self.is_dead then
                _self.particle_effect:Kill(false)
                quest.SetHints(quest.GetHints() + 1)
            end
            _self.is_dead = true
        end,
        is_dead = false,
    }
    return new_take_effect
end

function hints_lua_widget.hint_to_object(scene_object)
    local a = quest.GetHintsUseCount()
    local scene_object_ptr = qe.CBaseSceneObjectPtrT(scene_object)
    local obj_id = scene_object.GetId()
    
    local widget_pos, hint_scene_id = quest.get_object_pos(obj_id) 
    local closed_scenes_table = {}
    local current_widget = quest.global_scene_widget.GetWidgets()
    while not current_widget.IsEnd() do
        local scene_widget = __cast(current_widget.Get(), qe.CSceneWidget)     
        if scene_widget ~= nil then
            local scene_id = scene_widget.GetSceneId().c_str()
            if scene_id == hint_scene_id then
                break
            else
                local left_angle = scene_widget.GetAbsPos(false)
                local right_angle = left_angle + scene_widget.GetSize()


                if left_angle.X<widget_pos.X and left_angle.Y<widget_pos.Y and widget_pos.X<right_angle.X and widget_pos.Y<right_angle.Y then
                    table.insert(closed_scenes_table, scene_id)
                end
            end
         end
        current_widget.Next()
    end            
    for i,o in pairs(closed_scenes_table) do
        child_scenes.close_scene(o)
    end
    if widget_pos ~= nil then
        hints_lua_widget.current_hint_pos = widget_pos
        local hint_widget_pos = sf.misc.FloatVector(0,0)
        hint_widget_pos = hints_lua_widget.self.GetAbsPos(false)

        local new_hint_to_object_effect = hints_lua_widget.CreateObjectHintEffect()
        hints_lua_widget.InsertEffect("hint", new_hint_to_object_effect)
        local take_effect = nil
        local take_time = nil

        take_effect = new_take_effect
        take_time = hints_lua_widget.show_time

        new_hint_to_object_effect:Init(scene_object_ptr.get(), hints_timer.Get().GetTime(), take_time, widget_pos - hint_widget_pos)
      
        if hints_lua_widget.current_effects_map["hint"] == take_effect then
            hints_lua_widget.InsertEffect("hint", nil)
        end
        scene_object_ptr = nil

    else
        __message("Невозможно получить координаты объекта '"..tostring(obj_id).."', на который указывается подсказка", "Error")
    end
   
end

function hints_lua_widget.take_hint(scene_object)
    local obj_id = scene_object.GetId()

    local widget_pos = quest.get_object_pos(obj_id)
    if not widget_pos then
        widget_pos = sf.misc.FloatVector(0, 0)    
    end

 
    local hint_widget_pos = sf.misc.FloatVector(0,0)
    hint_widget_pos = hints_lua_widget.self.GetAbsPos(false)

    if widget_pos ~= nil then
        local scene_object_ptr = qe.CBaseSceneObjectPtrT(scene_object)
        quest.RemoveObject(obj_id)

        local new_take_hint_effect = hints_lua_widget.CreateTakeHintEffect()
        hints_lua_widget.InsertEffect("take", new_take_hint_effect)
        local take_effect = nil
        local take_time = nil

        take_effect = new_take_effect
        take_time = hints_lua_widget.fly_time

        new_take_hint_effect:Init(scene_object_ptr.get(), hints_timer.Get().GetTime(), take_time, widget_pos - hint_widget_pos)

      
        sleep(take_time)
        if hints_lua_widget.current_effects_map["take"] == take_effect then
            hints_lua_widget.InsertEffect("take", nil)
        end
        scene_object_ptr = nil
    end
end

hints_lua_widget.actions = hints_lua_widget.actions or {}

function hints_lua_widget.__CreateInstance()
    return "hints_lua_widget"
end

function hints_lua_widget.DoDraw(_this, _renderer)
    hints_lua_widget.effects_list:PreDraw(_renderer)

    if hints_lua_widget.update_effect then
        if hints_lua_widget.image and hints_lua_widget.button_koef > 0 then
            _renderer.PushState()
            _renderer.ApplyMatrix(sf.misc.MatrixTranslation(hints_lua_widget.image_offset.X, hints_lua_widget.image_offset.Y))
            hints_lua_widget.image.Draw(_renderer)
            _renderer.PopState()
        end
    end

    for i,o in pairs(hints_lua_widget.current_effects_map) do
        hints_lua_widget.current_effects_map[i]:Draw(_renderer)
    end

    hints_lua_widget.effects_list:PostDraw(_renderer)

    if hints_lua_widget.show_hint_tutorial then
        _renderer.ApplyMatrix( sf.misc.MatrixTranslation(hints_lua_widget.tutorial_arrow_offset.X, hints_lua_widget.tutorial_arrow_offset.Y))
        hints_lua_widget.tutorial_arrow.Draw(_renderer)
    end

    return true
end

function hints_lua_widget.DoUpdate(_this)

    local hints_count =  quest.GetHints()
    
    if hints_count < hints_lua_widget.working_hints_count and not hints_lua_widget.update_effect then
        hints_lua_widget.update_effect = true
        hints_lua_widget.current_effect_time = hints_lua_widget.update_time
        for i = 0, quest.GetHintsUseCount(_value) - 2 do
            hints_lua_widget.current_effect_time = hints_lua_widget.current_effect_time*hints_lua_widget.koef_hint_refreshtime
        end



        
        hints_lua_widget.hint_button_timer.Get().SetTime((hints_count/hints_lua_widget.working_hints_count)*hints_lua_widget.current_effect_time)
    end

    if hints_lua_widget.update_effect then
        local current_time = hints_lua_widget.hint_button_timer.Get().GetTime()
        local koef = current_time / hints_lua_widget.current_effect_time
        if current_time > hints_lua_widget.current_effect_time then
            koef = 1
        end
        hints_lua_widget.button_koef = koef
        hints_lua_widget.image.SetRect(sf.misc.FloatRect(0, 0, hints_lua_widget.traget_size.X*koef, hints_lua_widget.traget_size.Y) )
        hints_lua_widget.image.SetSourceRect(sf.misc.FloatRect(0, 0, hints_lua_widget.image_size.X*koef, hints_lua_widget.image_size.Y) )
        
        quest.SetHints(koef * hints_lua_widget.working_hints_count)
        if koef == 1 then
            hints_lua_widget.update_effect = nil
            hints_lua_widget.enable_hint_effect = hints_lua_widget.effects_list:CreateInstantEffect("NewHint", sf.misc.FloatVector(0, 0))
        end
    end
    
    local current_time = hints_timer.Get().GetTime()    
    for i,o in pairs(hints_lua_widget.current_effects_map) do
        hints_lua_widget.current_effects_map[i]:Update(current_time)
        if hints_lua_widget.current_effects_map[i].is_dead == true then
            hints_lua_widget.current_effects_map[i] = nil
        end
    end

    if hints_lua_widget.enable_hint_tutorial then
        local hints_use_count = quest.GetHintsUseFlag()
        if hints_use_count > 0 then
            hints_lua_widget.enable_hint_tutorial = nil
            hints_lua_widget.show_hint_tutorial = nil
        else
            if not hints_lua_widget.show_hint_tutorial and not tutorial.is_pre_arrow_delay(hints_lua_widget.pre_hint_tutorial_delay) then
                hints_lua_widget.show_hint_tutorial = true
                hints_lua_widget.start_show_time = current_time    
            end
            if hints_lua_widget.show_hint_tutorial and current_time - hints_lua_widget.start_show_time  > hints_lua_widget.hint_tutorial_show_time then
                tutorial.drop_timer()
                hints_lua_widget.show_hint_tutorial = false
            end
        end    
    end

    hints_lua_widget.effects_list:Update()
    if hints_lua_widget.show_hint_tutorial then
        hints_lua_widget.tutorial_arrow.Update()
    end

    return true
end

function hints_lua_widget.OnChar(_this, _char, _keyboard_state, _state, _broadcast)
	return false --return _this.SuperOnChar(_char, _keyboard_state, _state, _broadcast)
end

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

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

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

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

function hints_lua_widget.OnMouseUp(_this, _pos, _button, _state, _broadcast)
	return false --return _this.SuperOnMouseUp( _pos, _button, _state, _broadcast) 
end

function hints_lua_widget.OnDoubleClick(_this, _pos, _state, _broadcast)
	return false --return _this.SuperOnDoubleClick( _pos, _state, _broadcast) 
end

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

function hints_lua_widget.OnChildAction(_this, _action, _child)
	if not _child then return end
	local handler = hints_lua_widget.actions[_child.GetId().c_str()]
	if handler then handler = handler[_action.c_str()] end
	if handler then handler(_this, _child) end
end

function hints_lua_widget.Load(_info, _templates)


    local hints_info = quest.game_resources.GetChild("Constants", false).GetChildRef("game_hints", false)
    if hints_info then

        local res = tonumber(hints_info.GetValue("show_hint_delay").c_str())
        if res ~= "" then hints_lua_widget.show_time = res end

        res = tonumber(hints_info.GetValue("hint_fly_time").c_str())
        if res ~= "" then hints_lua_widget.fly_time = res end

        res = tonumber(hints_info.GetValue("progres_offset_x").c_str())
        if res ~= "" then hints_lua_widget.image_offset.X = res end

        res = tonumber(hints_info.GetValue("progres_offset_y").c_str())
        if res ~= "" then hints_lua_widget.image_offset.Y = res end

        res = tonumber(hints_info.GetValue("progres_size_x").c_str())
        if res ~= "" then hints_lua_widget.traget_size.X = res end

        res = tonumber(hints_info.GetValue("progres_size_y").c_str())
        if res ~= "" then hints_lua_widget.traget_size.Y = res end

        res = hints_info.GetValue("progres_image_id").c_str()
        if res ~= "" then hints_lua_widget.progres_image_id = res end
    end

    local hints_info = quest.game_resources.GetChild("Constants", false).GetChildRef("hint_tutorial", false)
    if hints_info then

        res = tonumber(hints_info.GetValue("pre_hint_tutorial_delay").c_str())
        if res ~= "" then hints_lua_widget.pre_hint_tutorial_delay = res end

        res = tonumber(hints_info.GetValue("hint_tutorial_show_time").c_str())
        if res ~= "" then hints_lua_widget.hint_tutorial_show_time = res end

        res = tonumber(hints_info.GetValue("tutorial_arrow_offset_x").c_str())
        if res ~= "" then hints_lua_widget.tutorial_arrow_offset.X = res end

        res = tonumber(hints_info.GetValue("tutorial_arrow_offset_y").c_str())
        if res ~= "" then hints_lua_widget.tutorial_arrow_offset.Y = res end

        res = hints_info.GetValue("tutorial_image_id").c_str()
        if res ~= "" then hints_lua_widget.tutorial_image_id = res end
    end


    hints_lua_widget.effects_list = visual_effects.CreateEffectsList()

    hints_lua_widget.image = sf.graphics.CImage(hints_lua_widget.progres_image_id)

    local rect = hints_lua_widget.image.GetRect()

    hints_lua_widget.image_size = sf.misc.FloatVector(rect.Width, rect.Height )

    hints_lua_widget.tutorial_arrow = sf.misc.anim.CClip()
    hints_lua_widget.tutorial_arrow.Load(hints_lua_widget.tutorial_image_id)
    hints_lua_widget.tutorial_arrow.SetPos(sf.misc.FloatVector(0, 0))
    hints_lua_widget.tutorial_arrow.SetTime(0)

    return true
end
