/**
 * simple class to convert resistor codes
 * (only partially implemented, feel free to extend it :)
 *
 * @author Peter Sch&uuml;ller <mailto:e0125596@student.tuwien.ac.at>
 */
public class ResistorCodes extends Object {
	/**
	 * exception class to report errors from ResistorCodes - conversions
	 */
	public static class ResistorCodesException extends Exception {
	}
	
	/**
	 * strings used to represent color rings on resistors and their corresponding values
	 */
	public final static String[] asColorStrings = {
		"si","go","sw","br","rt","or","ge","gn","bl","vi","gr","ws"
	};
	public final static double[] aiColorValues = {
	      -2,  -1,   0,   1,   2,   3,   4,   5,   6,   7,   8,   9
	};

	/**
	 * characters used to represent commas in electrotechnical resistor specifications
	 * and their corresponding muliplication factors
	 */
	public final static char[] acCommaChars = {
		'.', 'R', 'K', 'M'
	};
	public final static double[] adCommaMultipliers = {
		1.0, 1.0, 1e3, 1e6
	};
	
	/**
	 * decodes normal numbers or resistor specifications with special comma
	 * characters which specify multiplication factors
	 */
	public static double decodeString( String s ) throws ResistorCodesException {
			//string validity check
			//and get comma character index and position too
		int i, j;
		int iCountCommaChars = 0;
		int iCountNonDigits = 0;
		int iCommaCharIndex = -1;
		int iCommaCharPosition = -1;

			//safety check
		if( s.length() == 0 )
			throw new ResistorCodesException();
		
			//loop through input characters
		for( i = 0; i < s.length(); i++ ) {
			
				//is true if character at (i) is no digit
			if( "0123456789".indexOf(s.charAt(i)) == -1 )
				iCountNonDigits ++;

				//loop through comma characters
			for( j = 0; j < acCommaChars.length; j++ ) {
				if( s.charAt(i) == acCommaChars[j] ) {
						//remember this for later (to get value)
					iCommaCharIndex = j;
						//remember this for later (to replace character with ".")
					iCommaCharPosition = i;
						//count comma characters
					iCountCommaChars ++;
				}
			}
		}
		
			//too many comma characters
		if( iCountCommaChars > 1 )
			throw new ResistorCodesException();

			//other characters which are neither digits nor comma characters
		if( iCountNonDigits != iCountCommaChars )
			throw new ResistorCodesException();

		double dMultiplier;
		
			//no comma character -> add ".0" to string to enable safe (and easy) conversion in the next step
		if( iCountCommaChars == 0 ) {
			dMultiplier = 1.0;			
			s += ".0";
			iCommaCharPosition = s.length() - 2;
		}
		else {
			//there was a comma character -> calculate multiplier
			dMultiplier = adCommaMultipliers[ iCommaCharIndex ];			
		}

			//replace comma digit with "." and parse double like an ordinary number
		s = s.substring( 0, iCommaCharPosition ) + "." + s.substring( iCommaCharPosition + 1, s.length() );

		return dMultiplier * Double.parseDouble( s );
	}
	
	/**
	 * not implemented
	 * should decode a resistor color string
	 * (such a string is produced by the codeColorString(...) - function)
	 */
	public static double decodeColorString( String s ) throws ResistorCodesException {
		//not implemented
		throw new ResistorCodesException();
	}
	
	/**
	 * not implemented
	 * should produce an electrottechnical resistor specification
	 * (such a specification is decoded by the decodeString(...) - function
	 */
	public static String codeString( double d ) throws ResistorCodesException {
		//not implemented
		throw new ResistorCodesException();
	}

	/**
	 * produces a color code for a given resistor value
	 * color codes can be produced for resistors from 1 ohm to 999e9 ohms
	 */
	public static String codeColorString( double d ) throws ResistorCodesException {
		if( d < 1 || d > 999e9 )
			throw new ResistorCodesException();

		//only first digits count, make enough zeroes for indexing
		String sNumber = Double.toString( d*1000.0 );
		String sResult = "[";

		int j;
		for( j = 0; j < 3; j++ ) {
			sResult += asColorStrings[ sNumber.charAt( j ) - (int)'0' + 2 ];
			sResult += " ";
		}
		
		int iPower;
		//this formula produces an error for an exact value of 1000.0 (this value does not work
		//correctly, however this is the only value which does not work and the formula is ok)
		//beware of this java bug, it also does NOT work with floor(), StrictMath and other tricks
		//perhaps with StrictMath.IEEERemainder, but i was too busy to work this out
		iPower = (int)( Math.log(d) / Math.log(10.0) );

		//fix bug (weird solution but it works)
		if( d == 1000.0 )
			iPower = 3;

		sResult += asColorStrings[ iPower ] + "]";
		return sResult;
	}
}