class_name Inventory
const Item = preload("res://item/Item.gd")
const ItemStack = preload("res://item/ItemStack.gd")

var items:Array[ItemStack] = []

enum InventorySortType {
  ITEM_TYPE,
  ITEM_KEY
}

signal itemAdded(item:Item)
signal itemRemoved(item:Item)
signal itemQuantityChanged(item:Item, quantity:int)
signal inventorySorted(sortBy:InventorySortType, reverse:bool)

func setItem(item:Item, quantity:int) -> void:
  if quantity < 0:
    push_error("Cannot set item quantity to negative value, using 0")
    quantity = 0

  # Is item already in inventory?
  for itemStack in items:
    if itemStack.item != item:
      continue
    
    # Item stack already present.
    if quantity == 0:
      items.erase(itemStack)
      itemRemoved.emit(item)
      itemQuantityChanged.emit(item, 0)
    else:
      itemStack.quantity = quantity
      itemQuantityChanged.emit(item, quantity)
    return

  # Not in stack, create new stack
  var stack:ItemStack = ItemStack.new()
  stack.item = item
  stack.quantity = quantity
  items.append(stack)
  itemAdded.emit(item)
  itemQuantityChanged.emit(item, quantity)

func getItemQuantity(item:Item) -> int:
  for itemStack in items:
    if itemStack.item == item:
      return itemStack.quantity
  return 0

func addItem(item:Item, quantity:int = 1) -> void:
  # Add can only take positive quantities, otherwise use set or remove
  if quantity <= 0:
    push_error("Cannot add non-positive item quantity")
    return
  self.setItem(item, self.getItemQuantity(item) + quantity)

func removeItem(item:Item) -> void:
  self.setItem(item, 0)

func sort(sortBy:InventorySortType, reverse:bool = false) -> void:
  match sortBy:
    InventorySortType.ITEM_TYPE:
      items.sort_custom(_sortByItemType)
    InventorySortType.ITEM_KEY:
      items.sort_custom(_sortByItemKey)
  
  if reverse:
    items.reverse()

  inventorySorted.emit(sortBy, reverse)

# Sorters
func _sortByItemType(a:ItemStack, b:ItemStack) -> int:
  return int(a.item.itemType) - int(b.item.itemType)

func _sortByItemKey(a:ItemStack, b:ItemStack) -> int:
  return a.item.key.casecmp_to(b.item.key)