-- модуль дополнительного инвентаря
-- описание настроек: http://wiki/ProjectS12/IgrovyeNastrojjki
additional_inventory = {}

-- список предметов в доп. инвентаре
additional_inventory._init_objects = 
{
    "Knife",
    "Crowbar",
    "Brush",
    "Magnifier",
    "Earth",
	"Water",
	"Fire"
}


local self = additional_inventory
self._constants = 
{
    udata_hidden = "addinv,hidden"
}


function self.Load(_this)
    self._this = _this
    return true
end

-- инициализирует дополнительный инвентарь
-- Init должен вызываться в Level Init Script
-- проверяет все объекты в списке, если объекта нет на уровне, то прячет соответствующую ему кнопку
function self.Init()
	__assert(self._this)
    
    local widget = self._this.GetWidgets()
    while not widget.IsEnd() do
        local button = __cast(widget.Get().get(), sf.gui.CButtonWidget)
        if button then
            self._DisableItemButton(button)
        end
        widget.Next()
    end
    
    self._objects = {}
    
    -- находим все доступные объекты из списка
    for _, item in ipairs(self._init_objects) do
        local object = quest.find_object_by_id(item, false, false)
        local button = __cast(self._this.GetWidget(item.."_button", true), sf.gui.CButtonWidget)
        __assert(button)
		self._objects[item] = { object = object, button = button }
    end
	
	form_event("additional_inventory._ShowEnabledObjects()")
end

-- вызывается как часть инициализации
-- показывает все предметы инвентаря, которые не были спрятаны с помощью HideItem
function self._ShowEnabledObjects()
	for _, item in pairs(additional_inventory._objects) do
	    if item.object and not self._IsObjectDisabled(item.object) then
			-- объект есть на уровне,  и он не спрятан с помощью HideItem
            self._DisableItemButton(item.button, false)
        end
	end
end

-- возвращает true, если _object доступен в дополнительном инвентаре
function self.IsContainsItem(_object)
    __assert(self._objects)
    
    return self._objects[_object] and tostring(self._objects[_object].object.GetUserData()) ~= self._constants.udata_hidden
end

-- прячет кнопку, соответствующую объекту _object
-- помечает объект как спрятанный, используя userdata, чтобы после загрузки кнопка не стала снова видимой
function self.HideItem(_object)
    __assert(self._objects)
    __assert(self._objects[_object], "additional_inventory,HideItem: объект '".._object.."' не найден."..
        "Вероятно, он не прописан в списке объектов доп. инвентаря или отсутствует на уровне.")
        
    local item = self._objects[_object]
    __assert(item.object.GetUserData().empty() or (tostring(item.object.GetUserData()) == self._constants.udata_hidden))
    item.object.SetUserData(self._constants.udata_hidden)
    
    self._DisableItemButton(item.button)
end

-- показывает кнопку, соответствующую объекту _object
-- очищает юзердату объекта
function self.ShowItem(_object)
    __assert(self._objects)
    __assert(self._objects[_object], "additional_inventory.HideItem: объект '".._object.."' не найден."..
        "Вероятно, он не прописан в списке объектов доп. инвентаря или отсутствует на уровне.")
        
    local item = self._objects[_object]
    __assert(item.object.GetUserData().empty() or (tostring(item.object.GetUserData()) == self._constants.udata_hidden))
    item.object.SetUserData("")
    
    self._DisableItemButton(item.button, false)
end

-- отключает кнопки доп. инвентаря
function self.Disable()
	if not self._objects then return end
	
	for _, item in pairs(self._objects) do
		item.button.AddFlags(item.button.FlagDisabled)
	end
end

-- включает кнопки доп. инвентаря
function self.Enable()
	if not self._objects then return end
	
	for _, item in pairs(self._objects) do
		if not self._IsObjectDisabled(item.object) then
			item.button.RemFlags(item.button.FlagDisabled)
		end
	end
end

-- возвращает true, если объект спрятан
function self._IsObjectDisabled(_object)
	__assert(_object)
	return not _object.GetUserData().empty() and tostring(_object.GetUserData()) == self._constants.udata_hidden
end

-- helper function
-- прячет/показывает кнопку для объекта доп. инвентаря
function self._DisableItemButton(_button, disable)
    if disable or disable == nil then
        _button.AddFlags(__or(_button.FlagHidden, _button.FlagDisabled))
    else
        _button.RemFlags(__or(_button.FlagHidden, _button.FlagDisabled))
    end
end

function self.OnChildAction(_this, _action, _child)
    if not _child then return false end
    
    local action = tostring(_action)
    if action ~= "pressed" then return false end
    
    __assert(self._objects, "Не был вызван additional_inventory.Init!")
   
    -- обрабатываем нажатия на кнопки предметов в доп. инвентаре
    local widget_id = _child.GetId()
    for _, item in pairs(self._objects) do
        if item.button.GetId() == widget_id then
            -- нашли объект, соответствующий кнопке
            -- помещаем объект в курсор
            quest.global_cursor.SetCursorObject(item.object)
            cursor_lua_widget.UpdateCursorsTable()
            return true
        end
    end
   
    return false
end

function self.__CreateInstance()
    return "additional_inventory"
end


function self._CreateTakeEffect()
	local new_take_effect = 
    {
        Init = function(_self, _invent_object, _start_time, _total_time, _start_pos, _end_pos )
            _self.start_pos = _start_pos
			_self.end_pos = _end_pos
            _self.fly_obj_pos = _start_pos
            _self.particle_effect = objects_box_lua_widget.effects_list:CreateEffect("TakeObject", _self.fly_obj_pos)            

			_self._object = _invent_object
			_self._pos = _invent_object.GetPos()
            _self.start_time = _start_time
            _self.total_time = ((sf.misc.CalculateFloatVectorModule(_start_pos - _end_pos))/objects_box_lua_widget.take_speed)*1000
            _self.end_time = _self.start_time + _self.total_time
            return _self.total_time
        end,

        Draw = function(_self, _renderer)
                if _self.fly_obj_pos ~= nil then
                    local object_pos = _self._pos
                    _renderer.PushState()
                    _renderer.ApplyMatrix( sf.misc.MatrixTranslation(-object_pos.X + _self.fly_obj_pos.X , - object_pos.Y + _self.fly_obj_pos.Y))
                    _self._object.DrawGame(_renderer)
                    _renderer.PopState()
                end
        end,

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

            _self.fly_obj_pos = _self.start_pos + (_self.end_pos - _self.start_pos)*koef
			if koef >= 1 then
			--	__message("end_pos=".._self.end_pos.X.." ".._self.end_pos.Y.." fly_pos= ".. _self.fly_obj_pos.X.." ".. _self.fly_obj_pos.Y ..
				---" start=".._self.start_pos.X.." ".._self.start_pos.Y)
			end			
            _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)
            end
            _self.is_dead = true
        end,
        
        end_pos = nil, -- куда летим
        is_dead = false, -- долетели ли
        object_InventState = nil, -- инв.состояние - его передвигаем
        end_time = nil, -- конец передвижения
        total_time = nil, -- время передвижения
        start_time = nil, -- начало передвижения
        start_pos = nil, -- начальное положение
        fly_obj_pos = nil -- где сейчас находимся
    }
    return new_take_effect
end
-- функция взятия объекта в инвентарь
-- _additional_object - какой объект доп. инвентаря берем?

function self.TakeItem(_additional_object)
	__assert(self._objects)
    __assert(self._objects[_additional_object], "additional_inventory,HideItem: объект '".._additional_object.."' не найден."..
        "Вероятно, он не прописан в списке объектов доп. инвентаря или отсутствует на уровне.")
        
    local item = self._objects[_additional_object]
	
	-- для какого объекта вызван скрипт?
	local current_object = quest.global_current_script_object 
	if _object_on_scene ~= nil then
		current_object = quest.FindRootObjectById(_additional_object)
        quest.show_object_find_error(_additional_object, current_object)
	end
	
	-- позиция объекта
	local widget_pos = quest.get_object_pos(current_object.GetId()) 
    if not widget_pos then
        widget_pos = sf.misc.FloatVector(0, 0)    
    end
	
	--смещение объектов относительно окна	
	local object_list_abs_pos = sf.misc.FloatVector(0,0)
    object_list_abs_pos = objects_box_lua_widget.self.GetAbsPos(false)  
	-- создаем эффект
	if current_object ~= nil and objects_box_lua_widget.objects_list ~= nil then
		sound("add_to_inventory")
		local new_take_effect = self._CreateTakeEffect() -- новая таблица
		-- инициализируем
		local end_pos = item.button.GetOffset()- object_list_abs_pos + item.button.GetSize()/2
		local taked_object = item.object
		local group_object = __cast(taked_object, qe.CSceneGroup)
		if group_object then
			taked_object = group_object.GetStateById("__inv") 
		end
		__assert(taked_object, "Вы все мешки!!!! У объекта доп инвентаря должно быть состояние __inv")
		
		local take_time = new_take_effect:Init(taked_object, invent_timer.Get().GetTime(), "take_time", widget_pos - object_list_abs_pos, end_pos)
		objects_box_lua_widget.InsertEffect(new_take_effect)
		quest.RemoveObject(item.object.GetId().c_str())
		sleep(take_time)
		self.ShowItem(_additional_object)
	end
end
__inherite(self, null_lua_widget_handler())
