package org.jcon.df.column;

import org.jcon.param.Param;

/**
 * The Money type is a double of minimum and maximum value.
 * The defaults are:
 * - defaultValue = 0, just as in Java
 * - minValue = 0
 * - maxValue = 999999
 * - dollarsOnly = true
 *
 * @author Jack Harich and Tom Rouse
 */
public class MoneyColumn extends ColumnDef {

//---------- Protected Fields ----------------------------
protected boolean dollarsOnly = true;
protected double  minValue     = 0;
protected double  maxValue     = 999999;

//---------- Initialization ------------------------------
/**
 * No-arg to allow serialization.
 */
public MoneyColumn() {
    super();
    setDefaultValue("0");
    type = "Money";
}
/**
 * A convience constructor.
 */
public MoneyColumn(String name) {
    this();
    setName(name);
}
/**
 * Another convience constructor.
 */
public MoneyColumn(String name, int minValue, int maxValue) {
    this(name);
    this.minValue = minValue;
    this.maxValue = maxValue;
}
public static void main(String args[]) {
    MoneyColumn test = new MoneyColumn();
    test.runUnitTest();
}
//---------- Abstract Implementation ---------------------
public void initFromParam(Param param) {
    checkStandardProperties(param); // superclass
    if (param.hasProperty("MinValue")) {
        setMinValue(param.getInt("MinValue"));
    }
    if (param.hasProperty("MaxValue")) {
        setMaxValue(param.getInt("MaxValue"));
    }
}
/**
 * Checks for required, must be an Money, minValue and
 * maxValue.
 */
public String validateString(String text) {

    // Money check
    String message = validateMoney(text);
    if (message != null) return message;

    // Range check
    double value = Double.valueOf(text).doubleValue();
    if (! (minValue <= value && value <= maxValue)) {
        return displayName + " must be between " +
            minValue + " and " + maxValue;
    }
    // Passed all checks
    return null;
}
public String getMyPropertySummary() {
    String summary = "";
    summary += "Min=" + minValue + ",";
    summary += "Max=" + maxValue + ",";
    return summary;
}
//---------- Superclass Overrides ------------------------
public int getPreferredLength() {
    return String.valueOf(maxValue).length() + 2;
}
protected String getAutomaticDescription() {
    String text = "This must be a monetary value between "
        + minValue + " and " + maxValue + ".";
    if (dollarsOnly) {
        text += " Cents are not allowed.";
    }
    return text;
}
//---------- Public Methods ------------------------------
//--- Pair
public boolean isDollarsOnly() {
    return dollarsOnly;
}
public void setDollarsOnly(boolean dollarsOnly) {
    this.dollarsOnly = dollarsOnly;
}
//--- Pair
public double getMinValue() {
    return minValue;
}
public void setMinValue(double minValue) {
    this.minValue = minValue;
}
//--- Pair
public double getMaxValue() {
    return maxValue;
}
public void setMaxValue(double maxValue) {
    this.maxValue = maxValue;
}
//---------- Private Methods -----------------------------
private String validateMoney(String text) {
    // Must be numeric. REUSABLE
    double value;
    try {
        value = Double.valueOf(text).doubleValue();
        // Only 2 digits allowed to right of decimal
        if ((value * 100) % 1 != 0) {
            return displayName + " cannot have more than 2 digits to the right of the decimal.";
        }
    } catch(Exception ex) {
        return displayName + " is not numeric.";
    }
    // Check dollarsOnly
    if (dollarsOnly) {
        // No decimal digits allowed, must be integer
        try {
            int irrelevant = Integer.parseInt(text);
        } catch(Exception ex) {
            return displayName + " must be dollars only.";
        }
    }
    return null;
}
//----- Testing
private void runUnitTest() {
    MoneyColumn col = new MoneyColumn("ProposedAmount");
    col.setDisplayName("Proposed Amount");
    col.setDollarsOnly(true);
    col.setMinValue(0);
    col.setMaxValue(999999);

    test(col, "99999.99");
    test(col, "99999.995");
    test(col, "9999999");
    test(col, "999");
    test(col, "-999");
    test(col, "999-");
    test(col, "123xx");
    test(col, "");
    test(col, "B");
    test(col, "0");

    print("Range is " + col.getMinValue() + " to "
        + col.getMaxValue() );
}
private void test(MoneyColumn moneyColumn, String text) {
    String message = moneyColumn.validate(text);
    if (message == null) {
        print("'" + text + "' okay");
    } else {
        print("'" + text + "' invalid because: " + message);
    }
}
//--- Std
private void print(String text) {
    System.out.println(text);
}

} // End class
