take_objects_list = {}


local function invert_widget_effect(_current_time, _widget_table, _new_total_time, _new_direction)
    local k = (_current_time - _widget_table._start_time)/_widget_table._total_time
    _widget_table._start_time = _current_time - _new_total_time*k
    _widget_table._total_time = _new_total_time
    _widget_table._direction = _new_direction
end

take_objects = take_objects or {}

take_objects.widget_list ={}

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

take_objects.label_widget_times = {
change_size= { 400, 400 },
change_alpha= { 300, 300 },
change_color= { 300, 300 }
}
local function kill_left_divider(_current_time, _current_pos)
    local i = _current_pos
    local current_time = _current_time
    local find_alive_labels = false
    for j = i + 1, #take_objects.widget_list do
        if take_objects.widget_list[j]._type == 1 and take_objects.widget_list[j]._direction == 1 and not find_alive_labels then
            find_alive_labels = true
        end 
    end
    if not find_alive_labels then
        if take_objects.widget_list[i - 1] and take_objects.widget_list[i - 1]._type == 2 then
            if take_objects.widget_list[i - 1]._status == "normal" then

                take_objects.widget_list[i - 1]._status = "change_alpha"
                take_objects.widget_list[i - 1]._start_time = current_time
                take_objects.widget_list[i - 1]._total_time = take_objects.label_widget_times["change_alpha"][2]
                take_objects.widget_list[i - 1]._direction = 2

            elseif take_objects.widget_list[i - 1]._status == "change_alpha" then
                if take_objects.widget_list[i - 1]._direction == 1 then
                    invert_widget_effect(current_time, take_objects.widget_list[i - 1], take_objects.label_widget_times["change_alpha"][2], 2)
                end
            end
        end

    end


end

take_objects_list = 
{
	UpdateObjects = function()
   		local xstring = tostring(sf.misc.g_StringTable.Instance().GetString(take_objects_list.x_string))

        local current_time = take_objects.timer.Get().GetTime()
		if not take_objects_list.this then return end
		
		local take_objects_table = level_hints.GetPossibleTakeObjects()
		if not take_objects_table then return end

		local take_objects_repetition = {}
		for _,i in ipairs(take_objects_table) do
			local name = tostring(i.GetHint())
			if name ~= "" then
				if take_objects_repetition[name] then
					take_objects_repetition[name] = take_objects_repetition[name] + 1
				else
					take_objects_repetition[name] = 1
				end
			end
		end
        
        for obj_id,obj_count in pairs(take_objects_repetition) do
            local find = false
            local find_live_label = false
            for i,o in ipairs(take_objects.widget_list) do
                if o._obj_id == obj_id then
                    if o._direction == 2 and (o._status == "change_size" or o._status == "dead") then
                        find = false -- нашли, но виджет уже захлопывается
                    else
                        find = i
                    end
                end
                if o._type == 1 and o._status ~= "dead" and o._status ~= "change_size" then
                    find_live_label = true
                end
            end
            if find then
                local o = take_objects.widget_list[find]
                if o._type == 1 and o._obj_count ~= obj_count then
                    o._obj_count = obj_count
                    text = o._obj_id
                    if obj_count > 1 then
                        text = o._obj_id .. string.format(xstring, o._obj_count)
                    end
                    o._widget.SetText(text)
                    o._widget.ResizeToFitText(true)
                    local temp_size = o._size
                    o._size = sf.misc.FloatVector(o._widget.GetSize().X + take_objects_list.offset, temp_size.Y)
                end
                
                if o._direction == 2 and o._status ~= "change_size" and o._status ~= "dead" then
                    -- виджет пропадает, но это обратимо ... поварачиваем эффект пропадания вспять
                    if o._status == "change_alpha" then
                        local pre_obj = take_objects.widget_list[find - 1]
                        if pre_obj then
                            if pre_obj._type == 2 and pre_obj._status ~= "dead" then
                                if pre_obj._status == "change_alpha" and pre_obj._direction == 2 then
                                    invert_widget_effect(current_time, pre_obj, take_objects.label_widget_times["change_alpha"][1], 1)
                                end
                            end
                        end
                    end

                    invert_widget_effect(current_time, o, take_objects.label_widget_times[o._status][1], 1)
                end
            else
                --- не нашли виджет .... добавляем новый виджет
                local size = #take_objects.widget_list
                local insert_offset_x = 0
                if size > 0 then
                    insert_offset_x = take_objects.widget_list[size]._offset.X + take_objects.widget_list[size]._size.X
                end

                if find_live_label then
                    -- нужен разделитель однако
                        local new_table = {
                            _obj_id="",
                            _obj_count=0,
                            _size = sf.misc.FloatVector(0, 0),
                            _offset = sf.misc.FloatVector(insert_offset_x, 0),
                            _widget = sf.gui.CImageWidget(take_objects_list.offset_image, "", 0, 0),
                            _type = 2,
                            _status = "change_alpha",
                            _direction = 1,
                            _start_time = current_time,
                            _total_time = take_objects.label_widget_times["change_alpha"][1],


                        }
                        new_table._widget.SetColor(sf.graphics.Color(255, 255, 255, 255))


                        new_table._offset.Y = (take_objects_list.this.GetSize().Y - new_table._widget.GetSize().Y)/2
                        new_table._widget.SetOffset(insert_offset_x - take_objects_list.offset_image_size.X/2, new_table._offset.Y)

                        take_objects_list.this.AddWidget(new_table._widget)
                        take_objects.widget_list[size + 1] = new_table
                        size = #take_objects.widget_list
                end
                -- вставялем виджет с объектом
                local text = obj_id
                if obj_count > 1 then
                    text = obj_id .. string.format(xstring, obj_count)
                end


                local label = sf.gui.CLabelWidget(take_objects_list.font, text, "", 0, 0)

                local temp_height = take_objects_list.this.GetSize().Y


                label.SetSize(0, temp_height) 

                --label.SetSize(0, take_objects_list.this.GetSize().Y)
                label.SetOffset(insert_offset_x + take_objects_list.offset/2, 0)
                label.SetJustifications(sf.gui.JustifyLeft, sf.gui.JustifyCenterV)
                label.ResizeToFitText(false)
                label.SetColor(take_objects.start_color)


                local new_label_table = {
                    _obj_id=obj_id,
                    _obj_count=obj_count,
                    _size = sf.misc.FloatVector(label.GetSize().X + take_objects_list.offset, label.GetSize().Y),
                    _offset = sf.misc.FloatVector(insert_offset_x, 0),
                    _widget = label,
                    _type = 1,
                    _status = "change_alpha",
                    _direction = 1,
                    _start_time = current_time,
                    _total_time = take_objects.label_widget_times["change_alpha"][1],
                }
			    take_objects_list.this.AddWidget(label)
                take_objects.widget_list[size + 1] =  new_label_table
            end
        end
        -- обходим список виджетов что бы понять какие из них удалять
        for i,o in ipairs(take_objects.widget_list) do
            if o._type == 1 and o._direction == 1 and o._status ~= "dead" then
                if take_objects_repetition[o._obj_id] == nil then
                    if o._status == "normal" then
                        o._status = "change_color"
                        o._start_time = current_time
                        o._total_time = take_objects.label_widget_times["change_color"][2]
                        o._direction = 2
                    else
                        invert_widget_effect(current_time, o, take_objects.label_widget_times[o._status][2], 2)
                    end
                end
            end
        end
	end,

	DoUpdate = function(_this)
        local current_time = take_objects.timer.Get().GetTime()
        local start_offset_x = 0
        local last_type = nil
        local last_label = nil
        local last_status = nil
        local last_direction = nil

        for i,o in ipairs(take_objects.widget_list) do
            if i == 1 and o._type == 2 then
                if o._status == "normal" then
                    o._status = "change_alpha"
                    o._start_time = current_time
                    o._total_time = take_objects.label_widget_times["change_alpha"][2]
                    o._direction = 2
                elseif o._status == "change_alpha" and  o._direction == 1 then
                    invert_widget_effect(current_time, o, take_objects.label_widget_times["change_alpha"][2], 2)
                end
            end
            if o._start_time then
                local k = (current_time - o._start_time)/o._total_time
                if k >= 1 then
                    k = 1
                end
                if o._type == 1 then
                    if o._status == "change_alpha" then
                        if o._direction == 1 then
                            o._widget.SetColor(sf.graphics.Color(255*k, 255, 255, 255))
                            if k >= 1 then
                                o._status = "change_color"
                                o._start_time = current_time
                                o._total_time = take_objects.label_widget_times["change_color"][1]
                            end
                        elseif o._direction == 2 then    
                            o._widget.SetColor(sf.graphics.Color(255*(1 - k), 255, 255, 255))
                            if k >= 1 then
                                o._status = "change_size"
                                o._original_size = o._size.X
                                o._start_time = current_time
                                o._total_time = take_objects.label_widget_times["change_size"][1]
                                kill_left_divider(current_time, i)

                            end
                        end
                    elseif o._status == "change_color" then
                        if o._direction == 1 then

                            local color = sf.graphics.Color(
                                    take_objects.start_color.Alpha - (take_objects.start_color.Alpha - take_objects.normal_color.Alpha)* k,
                                    take_objects.start_color.Red - (take_objects.start_color.Red - take_objects.normal_color.Red)* k,
                                    take_objects.start_color.Green - (take_objects.start_color.Green - take_objects.normal_color.Green)* k,
                                    take_objects.start_color.Blue - (take_objects.start_color.Blue - take_objects.normal_color.Blue)* k )

                            o._widget.SetColor(color)
                            if k >= 1 then
                                o._status = "normal"
                                o._start_time = nil
                                o._total_time = nil
                            end
                        elseif o._direction == 2 then    
                            local color = sf.graphics.Color(
                                    take_objects.normal_color.Alpha - (take_objects.normal_color.Alpha - take_objects.start_color.Alpha)* k,
                                    take_objects.normal_color.Red - (take_objects.normal_color.Red - take_objects.start_color.Red)* k,
                                    take_objects.normal_color.Green - (take_objects.normal_color.Green - take_objects.start_color.Green)* k,
                                    take_objects.normal_color.Blue - (take_objects.normal_color.Blue - take_objects.start_color.Blue)* k )


                            o._widget.SetColor(color)
                            if k >= 1 then
                                o._status = "change_alpha"
                                o._start_time = current_time
                                o._total_time = take_objects.label_widget_times["change_alpha"][2]

                                kill_left_divider(current_time, i)
                            end
                        end                    
                    elseif o._status == "change_size" then
                        if o._direction == 1 then
                            _asset(false, "ширина виджета не может увеличиваться")
                        elseif o._direction == 2 then    
                                o._size.X = o._original_size*(1-k)
                            if k >= 1 then
                                o._size.X = 0
                                o._status = "dead"
                                o._start_time = nil
                                o._total_time = nil
                                if i == 1 then
                                    if take_objects.widget_list[i + 1] and take_objects.widget_list[i + 1]._type == 2 then
                                        if take_objects.widget_list[i + 1]._status == "normal" then

                                            take_objects.widget_list[i + 1]._status = "change_alpha"
                                            take_objects.widget_list[i + 1]._start_time = current_time
                                            take_objects.widget_list[i + 1]._total_time = take_objects.label_widget_times["change_alpha"][2]
                                            take_objects.widget_list[i + 1]._direction = 2

                                        elseif take_objects.widget_list[i + 1]._status == "change_alpha" then
                                            if take_objects.widget_list[i + 1]._direction == 1 then
                                                invert_widget_effect(current_time, take_objects.widget_list[i + 1], take_objects.label_widget_times["change_alpha"][2], 2)
                                            end
                                        end
                                    end
                                end    
                            end
                        end
                    end
                elseif o._type == 2 then
                    if o._status == "change_alpha" then
                        if o._direction == 1 then
                            o._widget.SetColor(sf.graphics.Color(255*k, 255, 255, 255))
                            if k >= 1 then
                                o._status = "normal"
                                o._start_time = nil
                                o._total_time = nil
                            end
                        elseif o._direction == 2 then    
                            o._widget.SetColor(sf.graphics.Color(255*(1 - k), 255, 255, 255))
                            if k >= 1 then
                                o._status = "dead"
                                o._start_time = nil
                                o._total_time = nil
                            end
                        end
                    end
                end

            end            

            if o._status ~= "dead" then
                o._offset.X = start_offset_x
                if o._type == 1 then
                    o._widget.SetOffset(o._offset.X + take_objects_list.offset/2, o._offset.Y)
                    last_label = i
                elseif o._type == 2 then
                    o._widget.SetOffset(o._offset.X - take_objects_list.offset_image_size.X/2, o._offset.Y)
                    if last_type == 2 and last_status ~= "dead"then
                        if last_status == "normal" then
                            o._status = "dead"
                        else
                            if last_direction == 1 then
                                o._status = "dead"
                            end
                        end
                        
                    end
                end
                last_type = o._type
                last_status = o._status
                last_direction = o._direction
                start_offset_x = start_offset_x + o._size.X
            end
        end
        if last_label then
            if take_objects.widget_list[last_label]._status == "cahnge_size" then
                take_objects.widget_list[last_label]._status = "dead"
                take_objects.widget_list[last_label]._start_time = nil
                take_objects.widget_list[last_label]._total_time = nil
            end
        end


        local size = #(take_objects.widget_list)
        if size ~= 0 then
            local i = 1
            while i <= size do
                if take_objects.widget_list[i]._status=="dead" then
                    take_objects_list.this.RemoveWidget(take_objects.widget_list[i]._widget)
                    table.remove(take_objects.widget_list, i)
                    size = size - 1
                    i = i - 1
                end
                i = i + 1
            end
        end

        return true
    end,

	Load = function(_this, _info, _templates)
		take_objects_list.this = _this
		take_objects_list.font = nil
		take_objects_list.labels = {}
		take_objects_list.images = {}
		
		local constants = quest.game_resources.GetChild("Constants", false).GetChildRef("take_objects_list", false)
		__assert(constants, "'take_objects_list' не найден в 'properties\\constants.xml'")
		
		local font_name,font = constants.GetValue("font").c_str(), nil
		if font_name~='' then font = sf.core.g_Application.GetResourceManager().GetFont(font_name) end
		__assert(font_name~='' and font, "Шрифт из take_objects_list не найден ('"..font_name.."')!")
		take_objects_list.font = font

        take_objects.start_color = string_to_color(constants.GetValue('start_color').c_str())
        take_objects.normal_color = string_to_color(constants.GetValue('normal_color').c_str())


        local res = tonumber(constants.GetValue("chnage_color_time").c_str())
        if res ~= nil then
            take_objects.label_widget_times.change_color[1] = res
            take_objects.label_widget_times.change_color[2] = res
        end

        res = tonumber(constants.GetValue("change_alpha_time").c_str())
        if res ~= nil then
            take_objects.label_widget_times.change_alpha[1] = res
            take_objects.label_widget_times.change_alpha[2] = res
        end
        res = tonumber(constants.GetValue("change_size_time").c_str())
        if res ~= nil then
            take_objects.label_widget_times.change_size[1] = res
            take_objects.label_widget_times.change_size[2] = res
        end

		
		take_objects_list.offset = tonumber(constants.GetValue("offset").c_str()) or 0
		
		__assert(constants.IsValue("x_string"), "constants.xml: атрибут 'x_string' не найден в 'take_objects_list'")
		take_objects_list.x_string = tonumber(tostring(constants.GetValue("x_string"))) or 0
		
		local offset_image = tostring(constants.GetValue("offset_image"))
		take_objects_list.offset_image = sf.core.g_Application.GetResourceManager().GetTexture(offset_image)
		if take_objects_list.offset_image then
			local width = take_objects_list.offset_image.GetWidth()
			if take_objects_list.offset < width then take_objects_list.offset = width end
			take_objects_list.offset_image = sf.graphics.CImage(take_objects_list.offset_image)
            local rect = take_objects_list.offset_image.GetRect()
            take_objects_list.offset_image_size = sf.misc.FloatVector(rect.Width, rect.Height)
		end
		return true
	end,
	
	__CreateInstance = function() return "take_objects_list" end
}

__inherite(take_objects_list, null_lua_widget_handler())
