/*
* Copyright (C) 2014 SCVNGR, Inc. d/b/a LevelUp
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
package com.scvngr.levelup.core.model;
import android.content.Context;
import android.os.Parcel;
import android.os.Parcelable;
import android.support.annotation.NonNull;
import com.scvngr.levelup.core.R;
import com.scvngr.levelup.core.annotation.LevelUpApi;
import com.scvngr.levelup.core.annotation.LevelUpApi.Contract;
import com.scvngr.levelup.core.annotation.VisibleForTesting;
import com.scvngr.levelup.core.annotation.VisibleForTesting.Visibility;
import com.scvngr.levelup.core.annotation.model.NonWrappable;
import com.scvngr.levelup.core.annotation.model.RequiredField;
import com.scvngr.levelup.core.util.NullUtils;
import net.jcip.annotations.Immutable;
import lombok.AllArgsConstructor;
import lombok.Value;
// The code below will be machine-processed.
// CHECKSTYLE:OFF
/**
* Represents some amount of money on the server.
*/
/*
* The first rule of acquisition: "Once you have their money, you never give it back."
*/
@Immutable
@AllArgsConstructor(suppressConstructorProperties = true)
@Value
@NonWrappable
@LevelUpApi(contract = Contract.DRAFT)
public final class MonetaryValue implements Parcelable {
/**
* Implements the {@code Parcelable} interface.
*/
@NonNull
public static final Creator<MonetaryValue> CREATOR = new MonetaryValueCreator();
/**
* The currency code for USD.
*/
@VisibleForTesting(visibility = Visibility.PRIVATE)
@NonNull
protected static final String USD_CODE = "usd";
/**
* The symbol for USD.
*/
@VisibleForTesting(visibility = Visibility.PRIVATE)
@NonNull
protected static final String USD_SYMBOL = "$";
/**
* The amount (in cents) for this {@link MonetaryValue}.
*/
private final long amount;
/**
* The raw currency code, such as "USD" or "EUR".
*/
@NonNull
@RequiredField
private final String currencyCode;
/**
* The currency symbol (i.e.: "$" or "€").
*/
@NonNull
@RequiredField
private final String currencySymbol;
/**
* Constructor. Assumes USD.
*
* @param amount the amount (in cents) for this {@link MonetaryValue}.
*/
public MonetaryValue(final long amount) {
this.amount = amount;
this.currencyCode = USD_CODE;
this.currencySymbol = USD_SYMBOL;
}
/**
* Get the formatted currency amount with symbol, assuming standard US/European "symbol+amount"
* formatting.
*
* @param context the Application context.
* @return the amount formatted with the currency symbol and amount (e.g. "$20" or "$23.05")
*/
@NonNull
public String getFormattedAmountWithCurrencySymbol(@NonNull final Context context) {
return getFormattedMoney(context, currencySymbol, amount);
}
/**
* Get the formatted currency amount with symbol, assuming standard US/European "symbol+amount"
* formatting; drop the last digits and decimal/comma if they're all 0s.
*
* @param context the Application context.
* @return the amount formatted with the currency symbol and amount (e.g. "$20" or "$23.05")
*/
@NonNull
public String getFormattedCentStrippedAmountWithCurrencySymbol(@NonNull final Context context) {
return getFormattedMoneyNoDecimal(context, currencySymbol, amount);
}
@Override
public void writeToParcel(final Parcel dest, final int flags) {
((MonetaryValueCreator) CREATOR)
.writeToParcel(NullUtils.nonNullContract(dest), flags, this);
}
@Override
public int describeContents() {
return 0;
}
/**
* Helper to format a long monetary value to a string. NOTE: this is not internationalized. It
* assumes that the value is in "cents".
*
* @param context the Application context.
* @param currencySymbol the symbol for the currency of the money.
* @param amount the amount of money.
* @return {@link String} with the formatted amount.
*/
@NonNull
public static String getFormattedMoney(@NonNull final Context context,
@NonNull final String currencySymbol, final long amount) {
return NullUtils.nonNullContract(context.getString(R.string.levelup_monetary_value_format,
currencySymbol, amount / 100f));
}
/**
* Helper to format a monetary value to a string, but truncate the decimals. NOTE: this is not
* internationalized. It assumes that the value is in "cents".
*
* @param context the Application context.
* @param currencySymbol the symbol for the currency of the money.
* @param amount the amount of money.
* @return {@link String} with the formatted amount (with no decimal).
*/
@NonNull
public static String getFormattedMoneyNoDecimal(@NonNull final Context context,
@NonNull final String currencySymbol, final long amount) {
return NullUtils.nonNullContract(context.getString(
R.string.levelup_monetary_value_no_decimal_format, currencySymbol,
Math.round(amount / 100f)));
}
/**
* Class to parcel/unparcel {@link MonetaryValue} objects.
*/
@Immutable
private static class MonetaryValueCreator implements Creator<MonetaryValue> {
@Override
public MonetaryValue createFromParcel(final Parcel in) {
final long amount = in.readLong();
final String currencyCode = NullUtils.nonNullContract(in.readString());
final String currencySymbol = NullUtils.nonNullContract(in.readString());
return new MonetaryValue(amount, currencyCode, currencySymbol);
}
@Override
public MonetaryValue[] newArray(final int size) {
return new MonetaryValue[size];
}
/**
* Write the {@link MonetaryValue} to a parcel.
*
* @param dest the {@link Parcel} to write to.
* @param flag the flags to use to write with.
* @param money the object to write to the parcel.
*/
private void writeToParcel(@NonNull final Parcel dest, final int flag,
@NonNull final MonetaryValue money) {
dest.writeLong(money.getAmount());
dest.writeString(money.getCurrencyCode());
dest.writeString(money.getCurrencySymbol());
}
}
}