//----[  eraseItems  ]---------------------------------------------------------
int ClientItemsInterface::eraseItems(unsigned int item_type, int quantity) {
  for (unsigned int i = 0; (quantity > 0) && (i < items_in_inventory_);) {
    ItemInstance* item = inventory_[i].item.dereference();
    if (!item) {
      repackInventory();
      break;
    } else {
      if (item->getDescription()->type_index == item_type) {
        quantity = item->removeQuantity(quantity);
        update_inventory_ = true;
        equipment_changed_ = equipment_changed_ || inventory_[i].equipped;
        inventory_dirty_bits_.set(i);

        // check to see if this item was destroyed by removing
        // the given quantity.
        if (quantity >= 0) {
          GlobalDatabaseManager::singleton()
              ->itemOnAvatarErased(item->getUniqueID());
          GlobalItemManager::singleton()->releaseItem(&inventory_[i].item);
          shiftDownToEraseInInventory(i);
        }

        // If the quantity has been consumed, we're done!
        if (quantity <= 0) return 0;
      } else {
        ++i;
      }
    }
  }

  return quantity;
}
//----[  onDeath  ]------------------------------------------------------------
bool ClientItemsInterface::onDeath(Magic::MagicIndex* on_death_magic,
                                   int* wishing_percent) {
  assert(on_death_magic);
  assert(wishing_percent);
  bool found_on_death_magic = false;
  int wishing_percent_sum = 0;

  // iterate backward because we might remove an element
  for (int i = items_in_inventory_; i > 0;) {
    --i;
    if (!inventory_[i].equipped) continue;
    ItemInstance* item = inventory_[i].item.dereference();
    assert(item);
    Magic::MagicIndex death_magic = item->getDescription()->on_death_magic;
    wishing_percent_sum += item->getDescription()->wishing_percent;
    if (!found_on_death_magic &&
        (death_magic != Magic::INVALID_MAGIC_INDEX)) {
      found_on_death_magic = true;
      *on_death_magic = death_magic;
      update_inventory_ = true;
      GlobalDatabaseManager::singleton()
        ->itemOnAvatarErased(item->getUniqueID());
      GlobalItemManager::singleton()
        ->releaseItem(&inventory_[i].item);
      shiftDownToEraseInInventory(i);
    }
  }
  *wishing_percent = wishing_percent_sum;
  return found_on_death_magic;
}
//----[  setStorageItem  ]-----------------------------------------------------
void ClientItemsInterface::setStorageItem(unsigned int index,
                                          ItemPointer* item_pointer) {
  ItemInstance* item = item_pointer->dereferenceAssumingValid();
  storage_[index].id = item->getUniqueID();
  storage_[index].quantity = item->getQuantity();
  storage_[index].type = item->getDescription()->type_index;
  GlobalItemManager::singleton()->releaseItem(item_pointer);
  storage_dirty_bits_.set(index);
  update_storage_ = true;
}
//----[  setInventoryItem  ]---------------------------------------------------
void ClientItemsInterface::setInventoryItem(unsigned int index,
                                            ItemPointer& item_pointer) {
  ItemInstance* item = item_pointer.dereferenceAssumingValid();
  inventory_[index].item.copy(item_pointer);
  inventory_[index].stackable = item->isStackable();
  inventory_[index].equipped = false;
  inventory_dirty_bits_.set(index);
  update_inventory_ = true;

  { // become the owner of this item
    //inventory_[index].item.becomeUniquePointer();
    GlobalDatabaseManager::singleton()->itemChangeOwner(item->getUniqueID(),
                                                        account_id_,
                                                        character_id_,
                                                        session_id_);
  }
}
//----[  isCarryingNew  ]------------------------------------------------------
bool ClientItemsInterface::isCarryingNew(unsigned int item_type,
                                         int quantity,
                                         ItemIDType oldest_id) {
  for (unsigned int i = 0; i < items_in_inventory_; ++i) {
    ItemInstance* item = inventory_[i].item.dereference();
    if (!item) {
      repackInventory();
      return false;
    } else {
      if (item->getDescription()->type_index == item_type &&
          item->getUniqueID() >= oldest_id) { // consider only new items
        quantity -= item->getQuantity();
        if (quantity <= 0) return true;
      }
    }
  }
  return false;
}
//----[  consumeItem  ]--------------------------------------------------------
bool ClientItemsInterface::consumeItem(unsigned int index,
                                       Magic::MagicIndex* magic_index) {
  assert(magic_index);
  if (!inventoryItemIsValid(index)) return false;
  ItemInstance* item = inventory_[index].item.dereferenceAssumingValid(); // guaranteed OK
  const Item::ItemServerDescription* description
    = item->getDescription();
  if (description->consumable_magic ==
        Magic::INVALID_MAGIC_INDEX) return false;
  *magic_index = description->consumable_magic;
  if (item->removeQuantity(1) >= 0) {
    // this item has been fully consumed
    GlobalDatabaseManager::singleton()->itemOnAvatarErased(item->getUniqueID());
    GlobalItemManager::singleton()->releaseItem(&inventory_[index].item);
    shiftDownToEraseInInventory(index);
  } else {
    // item is still available
    update_inventory_ = true;
    inventory_dirty_bits_.set(index);
  }
  todo("karl","if equipped consumable and consumed, change equipment");
  return true;
}