dofile("../defs/item_slot_defs.lua")
dofile("../defs/inventory_defs.lua")

ItemSlot = class("ItemSlot")
function ItemSlot:new(slot_type)
	local slot = instance(self)
	slot.slot_type = slot_type
	slot.item = nil
	slot.def = ITEM_SLOTS[slot_type]
	return slot
end

function ItemSlot:clear_item()
	assert(self.item)
	self.item = nil
end

function ItemSlot:set_item(item)
	assert(not self.item)
	self.item = item
end

function ItemSlot:get_hud_info(compare)
	if self.item then
		local template = self.def.hud_template or "info"
		return self.item:get_hud(template, compare)
	end
end

function ItemSlot:get_item()
	return self.item
end

function ItemSlot:get_item_slot_type()
	if self.item then
		return self.item:get_slot_type()
	end
end

function ItemSlot:get_price()
	if self.item then
		return self.item:get_price()
	end
	return 0
end

function ItemSlot:set_attack_slot(attack_slot)
	self.attack_slot = attack_slot
end

function ItemSlot:set_changed_timer(v)	
	self.changed_timer = v
end

function ItemSlot:get_pressed_action()
	if self.item then
		return self.def.pressed_action
	else
		return nil
	end
end

function ItemSlot:update_hud(dt)
	if self.changed_timer then
		self.changed_timer = self.changed_timer - dt
		if self.changed_timer <= 0 then
			self.changed_timer = nil
		end
	end
end

function ItemSlot:pop_item()
	local item = self.item
	self.item = nil
	return item
end

Inventory = class("Inventory")

function Inventory:new(inventory_type)
	local inv = instance(self)
	inv.def = assert(INVENTORY[inventory_type], inventory_type, "no in INVENTORY")	
	inv:init_slots()
	return inv
end

function Inventory:init_slots()
	self.slots = {}
	self.selected_slots = {}
	local selected_slots = self.selected_slots
	for slot_type, num in pairs(self.def.slots) do
		local type_map = {}
		self.slots[slot_type] = type_map

		for i=1,num do
			local slot = ItemSlot:new(slot_type)
			table.insert(type_map, slot)
			if not selected_slots[slot_type] then
				selected_slots[slot_type] = slot
			end
		end
	end
end

function Inventory:add_item(item)
	local slot_type = item:get_slot_type()	
	local slots = self:get_slots_of_type(slot_type)
	if slots then
		if item.stack then
			for index, slot in ipairs(slots) do
				local current = slot.item
				if current and current.stack and current:is_stackable_with(item) then
					current:adjust_stack(item.stack)
					slot:set_changed_timer(1)
					return true
				end
			end	
		end
		for index, slot in ipairs(slots) do
			local current = slot.item
			if not current then
				slot:set_item(item)
				slot:set_changed_timer(1)
				return true
			end
		end
		for index, slot in ipairs(slots) do
			local current = slot.item
			if current then
				local popped = slot:pop_item()
				slot:set_item(item)
				slot:set_changed_timer(1)
				return true, popped
			end
		end
		return true
	end
	return false
end

function Inventory:has_free_slot_of_type(slot_type)
	for index, slot in ipairs(self.slots[slot_type]) do
		if not slot.item then
			return true
		end
	end
	return false
end

function Inventory:get_slots_of_type(slot_type)
	return self.slots[slot_type]
end

function Inventory:get_selected_slots()
	return self.selected_slots	
end

function Inventory:get_selected_slot_of_type(slot_type)
	local slot = self.selected_slots[slot_type]
	if slot then
		return slot
	end
end
function Inventory:get_selected_item_of_type(slot_type)
	local slot = self.selected_slots[slot_type]
	if slot then
		return slot.item
	end
end