/**
   * Calculates how much of the given goods type this settlement wants and should retain.
   *
   * @param type The <code>GoodsType</code>.
   * @return The amount of goods wanted.
   */
  protected int getWantedGoodsAmount(GoodsType type) {
    if (getUnitCount() <= 0) return 0;

    final Specification spec = getSpecification();
    final UnitType unitType = getFirstUnit().getType();
    final Role militaryRole =
        Role.getAvailableRoles(getOwner(), unitType, spec.getMilitaryRoles()).get(0);

    if (type.isMilitaryGoods()) {
      // Retain enough goods to fully arm.
      int need = 0;
      for (Unit u : ownedUnits) {
        if (u.getRole() == militaryRole) continue;
        List<AbstractGoods> required = u.getGoodsDifference(militaryRole, 1);
        need += AbstractGoods.getCount(type, required);
      }
      return need;
    }

    int consumption = getConsumptionOf(type);
    if (type == spec.getPrimaryFoodType()) {
      // Food is perishable, do not try to retain that much
      return Math.max(40, consumption * 3);
    }
    if (type.isTradeGoods() || type.isNewWorldLuxuryType() || type.isRefined()) {
      // Aim for 10 years supply, resupply is doubtful
      return Math.max(80, consumption * 20);
    }
    // Just keep some around
    return 2 * getUnitCount();
  }
  /**
   * Gets the amount of gold this <code>IndianSettlment</code> is willing to sell the given <code>
   * Goods</code> for.
   *
   * <p>It is only meaningful to call this method from the server, since the settlement's {@link
   * GoodsContainer} is hidden from the clients.
   *
   * @param type The type of <code>Goods</code> to price.
   * @param amount The amount of <code>Goods</code> to price.
   * @return The price.
   */
  public int getPriceToSell(GoodsType type, int amount) {
    if (amount > GoodsContainer.CARGO_SIZE) {
      throw new IllegalArgumentException("Amount > " + GoodsContainer.CARGO_SIZE);
    }
    final int full = GOODS_BASE_PRICE + getType().getTradeBonus();

    // Base price is purchase price plus delta.
    // - military goods at double value
    // - trade goods at +50%
    int price = amount + Math.max(0, 11 * getPriceToBuy(type, amount) / 10);
    if (type.isMilitaryGoods()) {
      price = Math.max(price, amount * full * 2);
    } else if (type.isTradeGoods()) {
      price = Math.max(price, 150 * amount * full / 100);
    }
    return price;
  }
  /** {@inheritDoc} */
  @Override
  public int getImportAmount(GoodsType goodsType, int turns) {
    if (goodsType.limitIgnored()) return Integer.MAX_VALUE;

    int present = Math.max(0, getGoodsCount(goodsType) - turns * getTotalProductionOf(goodsType));
    int capacity = getWarehouseCapacity();
    return capacity - present;
  }
  /**
   * Price some goods according to the amount present in the settlement.
   *
   * @param type The type of goods for sale.
   * @param amount The amount of goods for sale.
   * @return A price for the goods.
   */
  private int getNormalGoodsPriceToBuy(GoodsType type, int amount) {
    final int tradeGoodsAdd = 20; // Fake additional trade goods present
    final int capacity = getGoodsCapacity();
    int current = getGoodsCount(type);

    // Increase effective stock if its raw material is produced here.
    GoodsType rawType = type.getInputType();
    if (rawType != null) {
      int rawProduction = getMaximumProduction(rawType);
      int add =
          (rawProduction < 5)
              ? 10 * rawProduction
              : (rawProduction < 10)
                  ? 5 * rawProduction + 25
                  : (rawProduction < 20) ? 2 * rawProduction + 55 : 100;
      // Decrease bonus in proportion to current stock, up to capacity.
      add = add * Math.max(0, capacity - current) / capacity;
      current += add;
    } else if (type.isTradeGoods()) {
      // Small artificial increase of the trade goods stored.
      current += tradeGoodsAdd;
    }

    // Only interested in the amount of goods that keeps the
    // total under the threshold.
    int retain = Math.min(getWantedGoodsAmount(type), capacity);
    int valued = (retain <= current) ? 0 : Math.min(amount, retain - current);

    // Unit price then is maximum price plus the bonus for the
    // settlement type, reduced by the proportion of goods present.
    int unitPrice =
        (GOODS_BASE_PRICE + getType().getTradeBonus()) * Math.max(0, capacity - current) / capacity;

    // But farmed goods are always less interesting.
    // and small settlements are not interested in building.
    if (type.isFarmed() || type.isRawBuildingMaterial()) unitPrice /= 2;

    // Only pay for the portion that is valued.
    return (unitPrice < 0) ? 0 : valued * unitPrice;
  }
  /**
   * Price some goods that have military value to the settlement.
   *
   * @param type The type of goods for sale.
   * @param amount The amount of goods for sale.
   * @return A price for the goods.
   */
  private int getMilitaryGoodsPriceToBuy(GoodsType type, int amount) {
    final int full = GOODS_BASE_PRICE + getType().getTradeBonus();
    int required = getWantedGoodsAmount(type);
    if (required == 0) return 0; // Do not pay military price

    // If the settlement can use more than half of the goods on offer,
    // then pay top dollar for the lot.  Otherwise only pay the premium
    // price for the part they need and refer the remaining amount to
    // the normal goods pricing.
    int valued = Math.max(0, required - getGoodsCount(type));
    int price =
        (valued > amount / 2)
            ? full * amount
            : valued * full + getNormalGoodsPriceToBuy(type, amount - valued);
    logger.finest(
        "Military price(" + amount + " " + type + ")" + " valued=" + valued + " -> " + price);
    return price;
  }
 /** {@inheritDoc} */
 @Override
 public int getExportAmount(GoodsType goodsType, int turns) {
   int present = Math.max(0, getGoodsCount(goodsType) + turns * getTotalProductionOf(goodsType));
   int wanted = getWantedGoodsAmount(goodsType);
   return present - wanted;
 }