package com.kickstarter.libs;
import android.os.Parcelable;
import android.support.annotation.NonNull;
import com.kickstarter.libs.utils.NumberUtils;
import com.kickstarter.models.Project;
import java.math.RoundingMode;
import auto.parcel.AutoParcel;
public final class KSCurrency {
private final CurrentConfigType currentConfig;
public KSCurrency(final @NonNull CurrentConfigType currentConfig) {
this.currentConfig = currentConfig;
}
/**
* Returns a currency string appropriate to the user's locale and location relative to a project.
*
* @param initialValue Value to display, local to the project's currency.
* @param project The project to use to look up currency information.
*/
public @NonNull String format(final float initialValue, final @NonNull Project project) {
return format(initialValue, project, false, false, RoundingMode.DOWN);
}
/**
* Returns a currency string appropriate to the user's locale and location relative to a project.
*
* @param initialValue Value to display, local to the project's currency.
* @param project The project to use to look up currency information.
* @param excludeCurrencyCode If true, hide the currency code, even if that makes the returned value ambiguous.
* This is used when space is constrained and the currency code can be determined elsewhere.
*/
public @NonNull String format(final float initialValue, final @NonNull Project project,
final boolean excludeCurrencyCode) {
return format(initialValue, project, excludeCurrencyCode, false, RoundingMode.DOWN);
}
/**
* Returns a currency string appropriate to the user's locale and location relative to a project.
*
* @param initialValue Value to display, local to the project's currency.
* @param project The project to use to look up currency information.
* @param excludeCurrencyCode If true, hide the currency code, even if that makes the returned value ambiguous.
* This is used when space is constrained and the currency code can be determined elsewhere.
* @param preferUSD Attempt to convert a project from it's local currency to USD, if the user is located in
* the US.
*/
public @NonNull String format(final float initialValue, final @NonNull Project project,
final boolean excludeCurrencyCode, final boolean preferUSD, final @NonNull RoundingMode roundingMode) {
final CurrencyOptions currencyOptions = currencyOptions(initialValue, project, preferUSD);
final boolean showCurrencyCode = showCurrencyCode(currencyOptions, excludeCurrencyCode);
final NumberOptions numberOptions = NumberOptions.builder()
.currencyCode(showCurrencyCode ? currencyOptions.currencyCode() : "")
.currencySymbol(currencyOptions.currencySymbol())
.roundingMode(roundingMode)
.build();
return NumberUtils.format(currencyOptions.value(), numberOptions);
}
/**
* Build {@link CurrencyOptions} based on the project and whether we would prefer to show USD. Even if USD is preferred,
* we only show USD if the user is in the US.
*/
private @NonNull CurrencyOptions currencyOptions(final float value, final @NonNull Project project,
final boolean preferUSD) {
final Config config = currentConfig.getConfig();
final Float staticUsdRate = project.staticUsdRate();
if (preferUSD && config.countryCode().equals("US") && staticUsdRate != null) {
return CurrencyOptions.builder()
.country("US")
.currencySymbol("$")
.currencyCode("")
.value(value * staticUsdRate)
.build();
} else {
return CurrencyOptions.builder()
.country(project.country())
.currencyCode(project.currency())
.currencySymbol(project.currencySymbol())
.value(value)
.build();
}
}
/**
* Determines whether the currency code should be shown. If the currency is ambiguous (e.g. CAD and USD both use `$`),
* we show the currency code if the user is not in the US, or the project is not in the US.
*/
private boolean showCurrencyCode(final @NonNull CurrencyOptions currencyOptions, final boolean excludeCurrencyCode) {
if (excludeCurrencyCode) {
return false;
}
final Config config = currentConfig.getConfig();
final boolean currencyIsDupe = config.currencyNeedsCode(currencyOptions.currencySymbol());
final boolean userIsUS = config.countryCode().equals("US");
final boolean projectIsUS = currencyOptions.country().equals("US");
return (currencyIsDupe && !userIsUS) || (currencyIsDupe && !projectIsUS);
}
@AutoParcel
public abstract static class CurrencyOptions implements Parcelable {
public abstract String country();
public abstract String currencyCode();
public abstract String currencySymbol();
public abstract float value();
@AutoParcel.Builder
public abstract static class Builder {
public abstract Builder country(String __);
public abstract Builder currencyCode(String __);
public abstract Builder currencySymbol(String __);
public abstract Builder value(float __);
public abstract CurrencyOptions build();
}
public static Builder builder() {
return new AutoParcel_KSCurrency_CurrencyOptions.Builder();
}
public abstract Builder toBuilder();
}
}