/**
   * Sell a specified amount of an item for the player.
   *
   * @param player The player on behalf of which these actions will be carried out.
   * @param item The desired item in the form of the item name.
   * @param amount The desired amount of the item to sell.
   * @return true on success, false on failure.
   */
  public boolean sell(Player player, String item, int amount) {

    // Be sure we have a positive amount
    if (amount < 1) {
      player.sendMessage(ChatColor.RED + "Invalid amount.");
      player.sendMessage("No negative numbers or zero, please.");
      return false;
    }

    // retrieve the commodity in question
    Commodities commodity =
        plugin.getDatabase().find(Commodities.class).where().ieq("name", item).findUnique();

    if (commodity == null) {
      player.sendMessage(ChatColor.RED + "Not allowed to buy that item.");
      player.sendMessage("Be sure you typed the correct name");
      return false;
    }

    // determine what it will pay
    Invoice invoice = generateInvoice(0, commodity, amount);

    // If the player has enough of the item, perform the transaction.
    int id = commodity.getNumber();
    Byte byteData = Byte.valueOf(String.valueOf(commodity.getData()));

    ItemStack its = new ItemStack(id, amount, (short) 0, byteData);

    if (player.getInventory().contains(id)) {

      // Figure out how much is left over
      int left = getAmountInInventory(player, its) - amount;

      if (left < 0) { // this indicates the correct id, but the wrong bytedata value
        // give nice output even if they gave a bad name.
        player.sendMessage(ChatColor.RED + "You don't have enough " + item);
        player.sendMessage(
            ChatColor.GREEN
                + "In Inventory: "
                + ChatColor.WHITE
                + getAmountInInventory(player, its));
        player.sendMessage(ChatColor.GREEN + "Attempted Amount: " + ChatColor.WHITE + amount);
        return false;
      }

      // Take out all of the item
      int x = 0;

      for (@SuppressWarnings("unused")
      ItemStack stack :
          player
              .getInventory()
              .getContents()) { // we do it this way incase a user has an expanded inventory via
                                // another plugin

        ItemStack slot = player.getInventory().getItem(x);

        if (slot != null) {
          Byte slotData = Byte.valueOf("0");

          try {
            slotData = slot.getData().getData();
          } catch (NullPointerException e) {
          }

          if ((slot.getTypeId() == id) && (slotData.compareTo(byteData) == 0)) {
            player.getInventory().clear(x);
          }
        }
        x++;
      }

      // put back what was left over
      if (left > 0) {
        ItemStack itsLeft = its;
        itsLeft.setAmount(left);
        player.getInventory().addItem(itsLeft);
      }

      // record the change in value
      commodity.setValue(invoice.getValue());
      plugin.getDatabase().save(commodity);

      // use BigDecimal to format value for output
      double v = commodity.getValue();
      double max = commodity.getMaxValue();
      double min = commodity.getMinValue();
      BigDecimal value;
      if (v < max && v > min) {
        value = BigDecimal.valueOf(v).setScale(2, RoundingMode.HALF_UP);
      } else if (v <= min) {
        value = BigDecimal.valueOf(min).setScale(2, RoundingMode.HALF_UP);
      } else {
        value = BigDecimal.valueOf(max).setScale(2, RoundingMode.HALF_UP);
      }
      BigDecimal spread = BigDecimal.valueOf(commodity.getSpread());

      // give some nice output
      BigDecimal sale =
          BigDecimal.valueOf((invoice.getTotal() + spread.doubleValue()))
              .setScale(2, RoundingMode.HALF_UP);

      player.sendMessage(ChatColor.GREEN + "--------------------------------");
      player.sendMessage(
          ChatColor.GREEN
              + "Old Balance: "
              + ChatColor.WHITE
              + BigDecimal.valueOf(economy.getBalance(player.getName()))
                  .setScale(2, RoundingMode.HALF_UP));

      // deposit the money
      economy.depositPlayer(player.getName(), invoice.getTotal());

      player.sendMessage(ChatColor.GREEN + "Sale: " + ChatColor.WHITE + sale);
      player.sendMessage(ChatColor.GREEN + "Selling Fee: " + ChatColor.WHITE + spread);
      player.sendMessage(ChatColor.GREEN + "--------------------------------");
      player.sendMessage(
          ChatColor.GREEN
              + "Net Gain: "
              + ChatColor.WHITE
              + BigDecimal.valueOf(invoice.getTotal()).setScale(2, RoundingMode.HALF_UP));
      player.sendMessage(
          ChatColor.GREEN
              + "New Balance: "
              + ChatColor.WHITE
              + BigDecimal.valueOf(economy.getBalance(player.getName()))
                  .setScale(2, RoundingMode.HALF_UP));
      player.sendMessage(ChatColor.GREEN + "--------------------------------");
      player.sendMessage(
          ChatColor.GRAY + item + ChatColor.GREEN + " New Price: " + ChatColor.WHITE + value);
      return true;
    } else { // give nice output even if they gave a bad number.

      player.sendMessage(ChatColor.RED + "You don't have enough " + item);
      player.sendMessage(
          ChatColor.GREEN + "In Inventory: " + ChatColor.WHITE + getAmountInInventory(player, its));
      player.sendMessage(ChatColor.GREEN + "Attempted Amount: " + ChatColor.WHITE + amount);
      return false;
    }
  }
  /**
   * Buy a specified amount of an item for the player.
   *
   * @param player The player on behalf of which these actions will be carried out.
   * @param item The desired item in the form of the item name.
   * @param amount The desired amount of the item to purchase.
   * @return true on success, false on failure.
   */
  public boolean buy(Player player, String item, int amount) {

    // Be sure we have a positive amount
    if (amount < 1) {
      player.sendMessage(ChatColor.RED + "Invalid amount.");
      player.sendMessage("No negative numbers or zero, please.");
      return false;
    }

    // retrieve the commodity in question
    Commodities commodity =
        plugin.getDatabase().find(Commodities.class).where().ieq("name", item).findUnique();

    // check that we found something
    if (commodity == null) {
      player.sendMessage(ChatColor.RED + "Not allowed to buy that item.");
      player.sendMessage("Be sure you typed the correct name");
      return false;
    }

    // determine what it will cost
    Invoice invoice = generateInvoice(1, commodity, amount);

    // check the player's wallet
    if (economy.has(player.getName(), invoice.getTotal())) {

      // give 'em the items and drop any extra
      Byte byteData = Byte.valueOf(String.valueOf(commodity.getData()));
      int id = commodity.getNumber();

      HashMap<Integer, ItemStack> overflow =
          player.getInventory().addItem(new ItemStack(id, amount, (short) 0, byteData));
      for (int a : overflow.keySet()) {
        player.getWorld().dropItem(player.getLocation(), overflow.get(a));
      }

      // save the new value
      commodity.setValue(invoice.getValue());
      getDatabase().save(commodity);

      // use BigDecimal to format value for output
      double v = commodity.getValue();
      double max = commodity.getMaxValue();
      double min = commodity.getMinValue();
      BigDecimal value;
      if (v < max && v > min) {
        value = BigDecimal.valueOf(v).setScale(2, RoundingMode.HALF_UP);
      } else if (v <= min) {
        value = BigDecimal.valueOf(min).setScale(2, RoundingMode.HALF_UP);
      } else {
        value = BigDecimal.valueOf(max).setScale(2, RoundingMode.HALF_UP);
      }

      // Give some nice output.
      player.sendMessage(ChatColor.GREEN + "--------------------------------");
      player.sendMessage(
          ChatColor.GREEN
              + "Old Balance: "
              + ChatColor.WHITE
              + BigDecimal.valueOf(economy.getBalance(player.getName()))
                  .setScale(2, RoundingMode.HALF_UP));
      // Subtract the invoice (this is an efficient place to do this)
      economy.withdrawPlayer(player.getName(), invoice.getTotal());

      player.sendMessage(
          ChatColor.GREEN
              + "Cost: "
              + ChatColor.WHITE
              + BigDecimal.valueOf(invoice.getTotal()).setScale(2, RoundingMode.HALF_UP));
      player.sendMessage(
          ChatColor.GREEN
              + "New Balance: "
              + ChatColor.WHITE
              + BigDecimal.valueOf(economy.getBalance(player.getName()))
                  .setScale(2, RoundingMode.HALF_UP));
      player.sendMessage(ChatColor.GREEN + "--------------------------------");
      player.sendMessage(
          ChatColor.GRAY + item + ChatColor.GREEN + " New Price: " + ChatColor.WHITE + value);
      return true;
    } else { // Otherwise, give nice output anyway ;)

      // The idea here is to show how much more money is needed.
      BigDecimal difference =
          BigDecimal.valueOf(economy.getBalance(player.getName()) - invoice.getTotal())
              .setScale(2, RoundingMode.HALF_UP);
      player.sendMessage(ChatColor.RED + "You don't have enough money");
      player.sendMessage(
          ChatColor.GREEN
              + "Balance: "
              + ChatColor.WHITE
              + BigDecimal.valueOf(economy.getBalance(player.getName()))
                  .setScale(2, RoundingMode.HALF_UP));
      player.sendMessage(
          ChatColor.GREEN
              + "Cost: "
              + ChatColor.WHITE
              + BigDecimal.valueOf(invoice.getTotal()).setScale(2, RoundingMode.HALF_UP));
      player.sendMessage(ChatColor.GREEN + "Difference: " + ChatColor.RED + difference);
      return true;
    }
  }