/**
 * <p>
 * UnsignedInt is a datatype for unsigned integers in Java since they are
 * conspicuously missing. It is important to note this datatype does not
 * actually create an unsigned integer instead it enforces rules on the
 * integer type that force it to always be positive. So the purpose of this
 * class is more about data integrity than actually solving the issue of an
 * unsigned integer. This version allows you to set a max value.
 * </p>
 *
 * <p>
 * +++ License +++ <br />
 * Do whatever you want with this code. Use it for business or
 * personal applications. However, I make no guarantee that this code is in
 * anyway correct. <br />
 * Just know that by using this code you have agreed that I am not liable
 * for any damages incurred while using or as a result of using this code.
 * <br />
 * Including my name in the code if you decide to copy it exactly would be
 * great, but this isn't required because realistically anyone
 * can write this. If you want you can write your own version and just
 * say you got the idea from my code if that's where you actually got your
 * idea from.
 * </p>
 *
 * <p>
 * +++ Coder Information +++           <br />
 * Hard tabs are used for indentation. <br />
 * Tab stop: 4 spaces or less          <br />
 * </p>
 *
 * <p>
 * +++ "Table of Contents" for various operations +++ <br />
 * <table>
 * <tr> <td> Operation </td> <td> Method Implemented By </td> </tr>
 * <tr> <td> = </td>         <td> setValue(...) </td> </tr>
 * <tr> <td> == </td>        <td> equals(...) </td> </tr>
 * <tr> <td> &gt; </td>      <td> greaterThan(...) </td> </tr>
 * <tr> <td> &lt; </td>      <td> lesserThan(...) </td> </tr>
 * <tr> <td> ++ </td>        <td> increment(...) </td> </tr>
 * <tr> <td> -- </td>        <td> decrement(...) </td> </tr>
 * <tr> <td> += </td>        <td> addBy(...) </td> </tr>
 * <tr> <td> +  </td>        <td> add(...) </td> </tr>
 * <tr> <td> -= </td>        <td> subtractBy(...) </td> </tr>
 * <tr> <td> -  </td>        <td> subtract(...) </td> </tr>
 * <tr> <td> *= </td>        <td> multiplyBy(...) </td> </tr>
 * <tr> <td> *  </td>        <td> multiply(...) </td> </tr>
 * <tr> <td> /= </td>        <td> divideBy(...) </td> </tr>
 * <tr> <td> / </td>         <td> divide(...) </td> </tr>
 * </table>
 * </p>
 *
 * @author Urban
 * @version 1.0 11/22/2008
 */
public class UnsignedInt implements Comparable
{
	/** The value of the UnsignedInt (can be only positive) */
	private int value;
	/**
	 * The maximum value that value can attain (can only be positive)
	 * If unused maxVal is set to -1 and ignored.
	 */
	private int maxVal;

	/**
	 * Constructs a new UnsignedInt with the specified value and a max
	 * value of -1 meaning no maximum value. <br />
	 * <b> Exceptions thrown: </b><br />
	 * IllegalArgumentException: The value is negative
	 * @param value The value to create the UnsignedInt with.
	 */
	public UnsignedInt(int value)
	{
		maxVal = -1;
		if(value < 0)
		{
			throw new IllegalArgumentException("Cannot pass a"
				+ " negative value to UnsignedInt.");
		}
		else
		{
			this.value = value;
		}
	}

	/**
	 * Constructs a new UnsignedInt with the specified value and specified
	 * max value that limits the maximum value of the UnsignedInt. <br />
	 * <b> Exceptions thrown: </b><br />
	 * IllegalArgumentException: The value is negative <br />
	 * IllegalArgumentException: The value exceeds the max value
	 * @param value The value to create the UnsignedInt with.
	 * @param maxVal The hard limit of value.
	 */
	public UnsignedInt(int value, int maxVal)
	{
		if(value > maxVal)
		{
			throw new IllegalArgumentException("Cannot have a"
				+ " value greater than the set max value.");
		}
		else if(value < 0 || maxVal < 0)
		{
			throw new IllegalArgumentException("Cannot pass a"
				+ " negative value to UnsignedInt.");
		}
		else
		{
			this.value = value;
			this.maxVal = maxVal;
		}
	}

	/**
	 * Sets an UnsignedInt to a given value, but enforces that
	 * the new value is positive and if a max value is set that
	 * the new value is less than the max value. <br />
	 * Equivalent to an '<b> = </b>' operation.
	 * <b> Exceptions thrown: </b><br />
	 * IllegalArgumentException: The value is negative <br />
	 * IllegalArgumentException: The value exceeds a set max value <br />
	 * @param value The value to set the UnsignedInt to.
	 */
	public void setValue(int value)
	{
		if(value < 0)
		{
			throw new IllegalArgumentException("Cannot pass a"
				+ " negative value to UnsignedInt.");
		}
		else if(maxVal > -1 && value > maxVal)
		{
			throw new IllegalArgumentException("Cannot have a"
				+ " value greater than the set max value.");
		}
		else
		{
			this.value = value;
		}
	}

	/**
	 * Returns the value of an UnsignedInt as an integer.
	 * @return The value of an UnsignedInt as an integer
	 */
	public int getValue()
	{
		return value;
	}

	/**
	 * Returns the max value of an UnsignedInt as an integer.
	 * @return -1 if no max value set and actual max value otherwise
	 */
	public int getMax()
	{
		return maxVal;
	}

	/**
	 * Returns the String representation of the value of an
	 * UnsignedInt disregarding any max value.
	 * @return String representation of an UnsignedInt's value.
	 */
	public String toString()
	{
		return(((Integer)value).toString());
	}

	/**
	 * The standard compareTo method for use with Integers.
	 * @param toCompare The integer to compare to this UnsignedInt.
	 * @return -1 if this is less, 1 if this is greater, or 0 if equal.
	 */
	public int compareTo(int toCompare)
	{
		if(value > toCompare)
		{
			return 1;
		}
		else if(value < toCompare)
		{
			return -1;
		}
		else
		{
			return 0;
		}
	}

	/**
	 * The standard compareTo method for use with UnsignedInts.
	 * @param toCompare The UnsignedInt to compare to this UnsignedInt.
	 * @return -1 if this is less, 1 if this is greater, or 0 if equal.
	 */
	public int compareTo(UnsignedInt toCompare)
	{
		return(this.compareTo(toCompare.value));
	}

	/**
	 * The standard compareTo method for use with objects. <br />
	 * The object must be an instance of UnsignedInt. <br />
	 * <b> Exceptions thrown: </b> <br />
	 * ClassCastException: The object is not an instance of UnsignedInt
	 * @param toCompare The Object to compare to this UnsignedInt.
	 * @return -1 if this is less, 1 if this is greater, or 0 if equal.
	 */
	public int compareTo(Object toCompare)
	{
		if(toCompare instanceof UnsignedInt)
		{
			return this.compareTo(((UnsignedInt)toCompare).value);
		}
		else
		{
			throw new ClassCastException("The compareTo method"
				+ " requires a variable of type UnsignedInt.");
		}
	}

	/**
	 * The standard equals method for use with Integers. <br />
	 * Equivalent to an '<b> == </b>' operation.
	 * @param equalTo The integer value to test equality with.
	 * @return True if the value of the UnsignedInt and equalTo are
	 * the same else false.
	 */
	public boolean equals(int equalTo)
	{
		return value == equalTo;
	}

	/**
	 * The standard equals method for use with UnsignedInts. <br />
	 * Equivalent to an '<b> == </b>' operation.
	 * @param equalTo The UnsignedInt to test equality with.
	 * @return True if the value of the UnsignedInt and equalTo are
	 * the same else false.
	 */
	public boolean equals(UnsignedInt equalTo)
	{
		return this.equals(equalTo.value);
	}

	/**
	 * The standard equals method for use with Objects. <br />
	 * The object must be an instance of UnsignedInt. <br />
	 * Equivalent to an '<b> == </b>' operation. <br />
	 * <b> Exceptions thrown: </b><br />
	 * ClassCastException: The object is not an instance of UnsignedInt
	 * @param equalTo The Object to test equality with.
	 * @return True if the value of the UnsignedInt and equalTo are
	 * the same else false.
	 */
	public boolean equals(Object equalTo)
	{
		if(equalTo instanceof UnsignedInt)
		{
			return this.equals(((UnsignedInt)equalTo).value);
		}
		else
		{
			throw new ClassCastException("The equals method "
				+ "requires a variable of type UnsignedInt.");
		}
	}

	/**
	 * Determines if this UnsignedInt's value is greater than the
	 * parameter, lesser. <br />
	 * Equivalent to a '<b> &gt; </b>' operation.
	 * @return True if UnsignedInt's value &gt; the parameter else false.
	 */
	public boolean greaterThan(int lesser)
	{
		return value > lesser;
	}

	/**
	 * Determines if this UnsignedInt's value is greater than the
	 * parameter, lesser. <br />
	 * Equivalent to a '<b> &gt; </b>' operation.
	 * @return True if UnsignedInt's value &gt; the parameter else false.
	 */
	public boolean greaterThan(UnsignedInt lesser)
	{
		return(this.greaterThan(lesser.value));
	}

	/**
	 * Determines if this UnsignedInt's value is lesser than the
	 * parameter, greater. <br />
	 * Equivalent to a '<b> &lt; </b>' operation.
	 * @return True if UnsignedInt's value &lt; the parameter else false.
	 */
	public boolean lesserThan(int greater)
	{
		return value < greater;
	}

	/**
	 * Determines if this UnsignedInt's value is lesser than the
	 * parameter, greater. <br />
	 * Equivalent to a '<b> &lt; </b>' operation.
	 * @return True if UnsignedInt's value &lt; the parameter else false.
	 */
	public boolean lesserThan(UnsignedInt greater)
	{
		return(this.lesserThan(greater.value));
	}

	/**
	 * Increase the value of an UnsignedInt by one. <br />
	 * Equivalent to a '<b> ++ </b>' operation. <br />
	 * <b> Exceptions thrown: </b><br />
	 * ArithmeticException: Increment value past max value. <br />
	 * ArithmeticException: Increment value past max integer.
	 */
	public void increment()
	{
		if(maxVal > -1 && (value + 1) > maxVal)
		{
			throw new ArithmeticException("Cannot increment"
				+ " passed the max value.");
		}
		else if(value+1 < 0)
		{
			throw new ArithmeticException("Cannot increment."
				+ "Integer overflow.");
		}
		else
		{
			value++;
		}
	}

	/**
	 * Decrese the value of an UnsignedInt by one. <br />
	 * Equivalent to a '<b> -- </b>' operation. <br />
	 * <b> Exceptions thrown: </b><br />
	 * ArithmeticException: Decrement value below zero
	 */
	public void decrement()
	{
		if(value - 1 < 0)
		{
			throw new ArithmeticException("Cannot decrement"
				+ " passed the minimum value of zero.");
		}
		else
		{
			value--;
		}
	}

	/**
	 * Adds the parameter, toAdd, to this UnsignedInt's value. <br />
	 * Equivalent to a '<b> += </b>' operation. <br />
	 * <b> Exceptions thrown: </b><br />
	 * ArithmeticException: value + toAdd is less than zero <br />
	 * ArithmeticException: value + toAdd is greater than max value
	 * @param toAdd The value to add to this UnsignedInt.
	 */
	public void addBy(int toAdd)
	{
		if(value + toAdd < 0)
		{
			throw new ArithmeticException("Result is"
				+ " less than zero.");
		}
		else if(maxVal > -1 && (value + toAdd) > maxVal)
		{
			throw new ArithmeticException("Result is"
				+ " greater than the max value.");
		}
		else
		{
			value += toAdd;
		}
	}

	/**
	 * Adds the parameter, toAdd, to this UnsignedInt's value. <br />
	 * Equivalent to a '<b> += </b>' operation. <br />
	 * <b> Exceptions thrown: </b><br />
	 * ArithmeticException: value + toAdd is less than zero <br />
	 * ArithmeticException: value + toAdd is greater than max value
	 * @param toAdd The value to add to this UnsignedInt.
	 */
	public void addBy(UnsignedInt toAdd)
	{
		this.addBy(toAdd.value);
	}

	/**
	 * Creates a new UnsignedInt from adding this UnsignedInt
	 * to the parameter, toAdd. <br />
	 * Equivalent to a '<b> + </b>' operation. <br />
	 * <b> Exceptions thrown: </b><br />
	 * ArithmeticException: value + toAdd is less than zero <br />
	 * ArithmeticException: value + toAdd is greater than max value
	 * @param toAdd The value to add.
	 * @return The new UnsignedInt created from adding.
	 */
	public UnsignedInt add(int toAdd)
	{
		UnsignedInt toRet = new UnsignedInt(value);
		toRet.maxVal = maxVal;
		toRet.addBy(toAdd);
		return(toRet);
	}

	/**
	 * Creates a new UnsignedInt from adding this UnsignedInt
	 * to the parameter, toAdd. <br />
	 * Equivalent to a '<b> + </b>' operation. <br />
	 * <b> Exceptions thrown: </b><br />
	 * ArithmeticException: value + toAdd is less than zero<br />
	 * ArithmeticException: value + toAdd is greater than max value
	 * @param toAdd The value to add.
	 * @return The new UnsignedInt created from adding.
	 */
	public UnsignedInt add(UnsignedInt toAdd)
	{
		return(this.add(toAdd.value));
	}

	/**
	 * Subtracts the parameter, toSub, from this UnsignedInt's
	 * value. <br />
	 * Equivalent to a '<b> -= </b>' operation. <br />
	 * <b> Exceptions thrown: </b><br />
	 * ArithmeticException: value - toSub is less than zero<br />
	 * ArithmeticException: value - toSub is greater than max value
	 * @param toSub The value to subtract from this UnsignedInt.
	 */
	public void subtractBy(int toSub)
	{
		if(value - toSub < 0)
		{
			throw new ArithmeticException("Result is"
				+ " less than zero.");
		}
		else if(maxVal > -1 && (value - toSub) > maxVal)
		{
			throw new ArithmeticException("Result is"
				+ " greater than the max value.");
		}
		else
		{
			value -= toSub;
		}
	}

	/**
	 * Subtracts the parameter, toSub, from this UnsignedInt's
	 * value. <br />
	 * Equivalent to a '<b> -= </b>' operation. <br />
	 * <b> Exceptions thrown: </b><br />
	 * ArithmeticException: value - toSub is less than zero<br />
	 * ArithmeticException: value - toSub is greater than max value
	 * @param toSub The value to subtract from this UnsignedInt.
	 */
	public void subtractBy(UnsignedInt toSub)
	{
		this.subtractBy(toSub.value);
	}

	/**
	 * Creates a new UnsignedInt from subtracting the parameter,
	 * toSub, from this UnsignedInt. <br />
	 * Equivalent to a '<b> - </b>' operation. <br />
	 * <b> Exceptions thrown: </b><br />
	 * ArithmeticException: value - toSub is less than zero<br />
	 * ArithmeticException: value - toSub is greater than max value
	 * @param toSub The value to subtract.
	 * @return The new UnsignedInt created from subtracting.
	 */
	public UnsignedInt subtract(int toSub)
	{
		UnsignedInt toRet = new UnsignedInt(value);
		toRet.maxVal = maxVal;
		toRet.subtractBy(toSub);
		return(toRet);
	}

	/**
	 * Creates a new UnsignedInt from subtracting the parameter,
	 * toSub, from this UnsignedInt. <br />
	 * Equivalent to a '<b> - </b>' operation. <br />
	 * <b> Exceptions thrown: </b><br />
	 * ArithmeticException: value - toSub is less than zero<br />
	 * ArithmeticException: value - toSub is greater than max value
	 * @param toSub The value to subtract.
	 * @return The new UngsignedInt created from subtracting.
	 */
	public UnsignedInt subtract(UnsignedInt toSub)
	{
		return(this.subtract(toSub.value));
	}

	/**
	 * Multiplies this UnsignedInt's value by the parameter,
	 * toMult. <br  />
	 * Equivalent to a '<b> *= </b>' operation. <br />
	 * <b> Exceptions thrown: </b><br />
	 * ArithmeticException: value * toMult is negative <br />
	 * ArithmeticException: value * toMult is greater than max value
	 * @param toMult The value to multiply this UnsignedInt by.
	 */
	public void multiplyBy(int toMult)
	{
		if(maxVal > -1 && (toMult * value) > maxVal)
		{
			throw new ArithmeticException("Result is"
				+ " greater than the max value.");
		}
		else if(toMult * value < 0)
		{
			throw new ArithmeticException("Result is"
				+ " less than zero.");
		}
		else
		{
			value *= toMult;
		}
	}

	/**
	 * Multiplies this UnsignedInt's value by the parameter,
	 * toMult. <br />
	 * Equivalent to a '*=' operation. <br />
	 * <b> Exceptions thrown: </b><br />
	 * ArithmeticException: value * toMult is negative <br />
	 * ArithmeticException: value * toMult is greater than max value
	 * @param toMult The value to multiply this UnsignedInt by.
	 */
	public void multiplyBy(UnsignedInt toMult)
	{
		this.multiplyBy(toMult.value);
	}

	/**
	 * Creates a new UnsignedInt from multiplying the parameter,
	 * toMult, by this UnsignedInt's value. <br />
	 * Equivalent to a '*' operation. <br />
	 * <b> Exceptions thrown: </b><br />
	 * ArithmeticException: value * toMult is negative <br />
	 * ArithmeticException: value * toMult is greater than max value
	 * @param toMult The value to multiply by.
	 * @return The new UnsignedInt created by multiplying.
	 */
	public UnsignedInt multiply(int toMult)
	{
		UnsignedInt toRet = new UnsignedInt(value);
		toRet.maxVal = maxVal;
		toRet.multiplyBy(toMult);
		return(toRet);
	}

	/**
	 * Creates a new UnsignedInt from multiplying the parameter,
	 * toMult, by this UnsignedInt's value. <br />
	 * Equivalent to a '*' operation. <br />
	 * <b> Exceptions thrown: </b><br />
	 * ArithmeticException: value * toMult is negative <br />
	 * ArithmeticException: value * toMult is greater than max value
	 * @param toMult The value to multiply by.
	 * @return The new UnsignedInt created by multiplying
	 */
	public UnsignedInt multiply(UnsignedInt toMult)
	{
		return(this.multiply(toMult.value));
	}

	/**
	 * Divides this UnsignedInt's value by the parameter, toDiv. <br />
	 * Equivalent to a '<b> /= </b>' operation. <br />
	 * <b> Exceptions thrown: </b><br />
	 * ArithmeticException: Divide by zero. <br />
	 * ArithmeticException: Divide by a negative value. <br />
	 * @param toDiv The value to divide this UnsignedInt by.
	 */
	public void divideBy(int toDiv)
	{
		if(toDiv < 1)
		{
			throw new ArithmeticException("Cannot divide"
				+ " by a negative value or zero.");
		}
		else
		{
			value /= toDiv;
		}
	}

	/**
	 * Divides this UnsignedInt's value by the parameter, toDiv. <br />
	 * Equivalent to a '<b> /= </b>' operation. <br />
	 * <b> Exceptions thrown: </b><br />
	 * ArithmeticException: Divide by zero. <br />
	 * ArithmeticException: Divide by a negative value. <br />
	 * @param toDiv The value to divide this UnsignedInt by.
	 */
	public void divideBy(UnsignedInt toDiv)
	{
		this.divideBy(toDiv.value);
	}

	/**
	 * Creates a new UnsignedInt from divinding this UnsignedInt's
	 * value by the parameter, toDiv. <br />
	 * Equivalent to a '<b> / </b>' operation. <br />
	 * <b> Exceptions thrown: </b><br />
	 * ArithmeticException: Divide by zero. <br />
	 * ArithmeticException: Divide by a negative value. <br />
	 * @param toDiv The value to divide by.
	 * @return The new UnsignedInt created by dividing.
	 */
	public UnsignedInt divide(int toDiv)
	{
		UnsignedInt toRet = new UnsignedInt(value);
		toRet.maxVal = maxVal;
		toRet.divideBy(toDiv);
		return(toRet);
	}

	/**
	 * Creates a new UnsignedInt from dividing this UnsignedInt's
	 * value by the parameter, toDiv. <br />
	 * Equivalent to a '<b> / </b>' operation. <br />
	 * <b> Exceptions thrown: </b><br />
	 * ArithmeticException: Divide by zero. <br />
	 * ArithmeticException: Divide by a negative value. <br />
	 * @param toDiv The value to divide by.
	 * @return The new UnsignedInt created by dividing.
	 */
	public UnsignedInt divide(UnsignedInt toDiv)
	{
		return(this.divide(toDiv.value));
	}
}
