
// still need to implement format(long)
// still need to add support for group seperators

public class NumFmt extends Object {
	private static int 	DEFAULTPLACES = 6;

	private		int		minLen 			= 0; //no max, string grows as needed
	private		int		decPlaces		= DEFAULTPLACES; //only used for reals

	private		boolean	padIt 			= true;
	private		char	padCharLeading	= ' ';
	private		char	padCharTrailing	= ' ';

	private		boolean	roundIt			= true; //only used for real nums
	private		boolean	alignRight		= true;

	private		boolean	useThouSep		= false;
	private		char	thousandCharSep	= ',';


	public NumFmt() {
		// need no-op constructor with all default values
	}

	public NumFmt(int minLen) {
		this();
		setMinLen(minLen);
	}

	public NumFmt(int minLen, int decPlaces) {
		this(minLen);
		setDecPlaces(decPlaces);
	}

	public NumFmt(int minLen, int decPlaces, char padCharLeading) {
		this(minLen, decPlaces);
		setPadIt(true);
		setPadCharLeading(padCharLeading);
	}

	public NumFmt(int minLen, char padCharLeading) {
		// for use with integer types, so decimal places value does not matter
		this(minLen, DEFAULTPLACES, padCharLeading); 
	}

	public void setMinLen(int minLen) {
		// make sure that vals are valid, else use curr val (initally default)
		this.minLen = ( minLen >= 0 ? minLen : this.minLen );
	}

	public void setDecPlaces(int decPlaces) {
		// make sure that vals are valid, else use curr val (initally default)
		this.decPlaces = ( decPlaces >= 0 ? decPlaces : this.decPlaces );
	}

	public void setPadIt(boolean padIt) {
		this.padIt = padIt;
	}

	public void setPadCharLeading(char padCharLeading) {
		this.padCharLeading = padCharLeading;
	}

	public void setPadCharTrailing(char padCharTrailing) {
		this.padCharTrailing = padCharTrailing;
	}

	public void setRoundIt(boolean roundIt) {
		this.roundIt = roundIt;
	}

	/**
	  * If true, number is attempted to be aligned with the right side
	  * of the field.  If false, the left side.
	  */
	public void setAlignRight(boolean alignRight) {
		this.alignRight = alignRight;
	}

	public String format(double num) {
		long   digits;
		int    digitLen;
		String digitStr, wholeStr, fractStr;

		char rangeFlag;
		if ( 0.0 <= num && num < 1.0 ) {
			rangeFlag = 'P';
		} else if ( -1.0 < num && num < 0.0 ) {
			rangeFlag = 'N';
		} else {
			rangeFlag = 'O';
		}

		switch ( rangeFlag ) {
			case 'P':
				num += 1.0;
				break;
			case 'N':
				num -= 1.0;
				break;
			// only care about those two cases
		}

		digits = Math.round(num * Math.pow(10.0, decPlaces));
		digitStr = String.valueOf(digits);

		digitLen = (int)digitStr.length();
		wholeStr = digitStr.substring(0, digitLen - decPlaces);
		fractStr = digitStr.substring(digitLen - decPlaces, digitLen);

		switch ( rangeFlag ) {
			case 'P':
				wholeStr = "0";
				break;
			case 'N':
				wholeStr = "-0";
				break;
			// only care about those two cases
		}

		return formatCombine(wholeStr, fractStr);
	}

	private String formatCombine(String wholeStr, String fractStr) {
		String numStr;
		int    numStrLen;

		if ( fractStr.length() > 0 ) {
			numStr = wholeStr + "." + fractStr;
		}
		else {
			numStr = wholeStr;
		}

		numStrLen = (int)numStr.length();

		if ( padIt && ( numStrLen < minLen ) ) {
			// we need to do some padding 
			StringBuffer padBuff = new StringBuffer(minLen + 10);

			if ( alignRight ) {
				for ( int i = numStrLen; i < minLen; i++ ) {
					padBuff.append(padCharLeading);
				}

				padBuff.append(numStr);
			}
			else {
				padBuff.append(numStr);
				for ( int i = numStrLen; i < minLen; i++ ) {
					padBuff.append(padCharTrailing);
				}
			}

			numStr = padBuff.toString();
		}

		return numStr;
	}

	public void printAllValues() {
		System.err.println("minLen = " + minLen);
		System.err.println("decPlaces = " + decPlaces);
		System.err.println("padIt = " + padIt);
		System.err.println("padCharLeading = " + padCharLeading);
		System.err.println("padCharTrailing = " + padCharTrailing);
		System.err.println("roundIt = " + roundIt);
		System.err.println("alignRight = " + alignRight);
	}
	
	public static void main(String[] args) {
		NumFmt nf1 = new NumFmt();
		NumFmt nf2 = new NumFmt(13);
		NumFmt nf3 = new NumFmt(13, 4);
		NumFmt nf4 = new NumFmt(-3);
		NumFmt nf5 = new NumFmt(-2, -1);
		NumFmt nf6 = new NumFmt(2, -1);
		NumFmt nf7 = new NumFmt(-22, 3);

		/*
		nf1.printAllValues();
		nf2.printAllValues();
		nf3.printAllValues();
		nf4.printAllValues();
		nf5.printAllValues();
		nf6.printAllValues();
		nf7.printAllValues();
		*/

		NumFmt nf;
		String str;
		nf = new NumFmt();
		str = nf.format(3.4F); 
		System.out.println(">" + str + "<");
		System.out.println(">" + nf.format(3.123456789F) + "<"); 

		nf = new NumFmt(12, 0);
		System.out.println(">" + nf.format(3.123456789F) + "<"); 

		nf = new NumFmt(14, 3, '0');
		System.out.println(">" + nf.format(3.123456789F) + "<"); 
		System.out.println(">" + nf.format(3.5555555) + "<"); 

		nf = new NumFmt(14, '0');
		System.out.println(">" + nf.format(3.123456789F) + "<"); 
		System.out.println(">" + nf.format(3.5555555) + "<"); 

		nf = new NumFmt(12, 4);
		System.out.println(">" + nf.format(1234567890.1234) + "<"); 
		System.out.println(">" + nf.format(.1234) + "<"); 
		System.out.println(">" + nf.format(123.0) + "<"); 
		System.out.println(">" + nf.format(4444.44444) + "<"); 

		nf = new NumFmt(12, 4);
		nf.setAlignRight(false);
		System.out.println(">" + nf.format(1234567890.1234) + "<"); 
		System.out.println(">" + nf.format(.1234) + "<"); 
		System.out.println(">" + nf.format(123.0) + "<"); 
		System.out.println(">" + nf.format(4444.44444) + "<"); 

		nf = new NumFmt(12, 4);
		nf.setAlignRight(false);
		nf.setPadIt(false);
		System.out.println(">" + nf.format(1234567890.1234) + "<"); 
		System.out.println(">" + nf.format(.1234) + "<"); 
		System.out.println(">" + nf.format(123.0) + "<"); 
		System.out.println(">" + nf.format(4444.44444) + "<"); 

		nf = new NumFmt(12, 4);
		nf.setAlignRight(false);
		nf.setPadCharTrailing('-');
		System.out.println(">" + nf.format(1234567890.1234) + "<"); 
		System.out.println(">" + nf.format(123.0) + "<"); 
		System.out.println(">" + nf.format(4444.44444) + "<"); 

		nf = new NumFmt(12, 4);
		System.out.println(">" + nf.format( 1.50008) + "<"); 
		System.out.println(">" + nf.format(-1.50008) + "<"); 
		System.out.println(">" + nf.format( 1.5    ) + "<"); 
		System.out.println(">" + nf.format(-1.5    ) + "<"); 
		System.out.println(">" + nf.format( 0.12348) + "<"); 
		System.out.println(">" + nf.format(-0.12348) + "<"); 
		System.out.println(">" + nf.format( 0.01208) + "<"); 
		System.out.println(">" + nf.format(-0.01208) + "<"); 
		System.out.println(">" + nf.format( 0.1234) + "<"); 
		System.out.println(">" + nf.format(-0.1234) + "<"); 
		System.out.println(">" + nf.format( 0.012 ) + "<"); 
		System.out.println(">" + nf.format(-0.012 ) + "<"); 
		System.out.println(">" + nf.format( 0.0   ) + "<"); 
		System.out.println(">" + nf.format( 1.0   ) + "<"); 
		System.out.println(">" + nf.format(-1.0   ) + "<"); 
	}
}
