public class Witch {

	// Static Fields
	private static int totalWitches = 0;

	// Non-Static Fields
	private String name;
	private String school;
	private int magicPower;

	// Static Constants
	static final int MAX_LEVEL = 100;
	static final int MIN_LEVEL = 0;

	// Constructors
	/**
	 * This is the default constructor
	 * 
	 * @category constructor
	 * @param None This constructor takes no parameter
	 */
	public Witch() {
		this.name = "no one";
		this.school = "unknown school";
		this.magicPower = 10;
		Witch.totalWitches++;
	}

	/**
	 * Initialize this witch object with data from parameter
	 * 
	 * @category constructor
	 * @param name       The name of the witch
	 * @param school     The school that the witch belong to
	 * @param magicPower The magicPower of the witch
	 */
	public Witch(String name, String school, int magicPower) {
		this.name = name;
		this.school = school;
		this.magicPower = magicPower;
		Witch.totalWitches++;
	}

	/**
	 * Initialize this witch object with data from w
	 * 
	 * @category constructor
	 * @param w Witch to clone from
	 */
	public Witch(Witch w) {
		this.magicPower = w.getMagicPower();
		this.name = w.getName();
		this.school = w.getSchool();
		Witch.totalWitches++;
	}

	// Getters
	/**
	 * Get the number of witch created
	 * 
	 * @category getter
	 * @return totalWitches The total number of witch created
	 */
	public static int getTotalWitches() {
		return Witch.totalWitches;
	}

	/**
	 * Get the name of the witch
	 * 
	 * @category getter
	 * @return name name of the witch
	 */
	public String getName() {
		return this.name;
	}

	/**
	 * Get the magic power of the witch
	 * 
	 * @category getter
	 * @return magicPower The magic power of the witch
	 */
	public int getMagicPower() {
		return this.magicPower;
	}

	/**
	 * Get the school of the witch
	 * 
	 * @category getter
	 * @return school The school of the witch
	 */
	public String getSchool() {
		return this.school;
	}

	// Setters
	/**
	 * Set the totalWitches field
	 * 
	 * @category setter
	 * @param totalWitches The value of totalWitches to set
	 */
	public static void setTotalWitches(int totalWitches) {
		Witch.totalWitches = totalWitches;
	}

	/**
	 * Set the name of the witch
	 * 
	 * @category setter
	 * @param name The name of the witch to set
	 */
	public void setName(String name) {
		this.name = name;
	}

	/**
	 * Set the magic power of the witch
	 * 
	 * @category setter
	 * @param magicPower the magic power to set (0<=magicPower<=100), numbers out of
	 *                   range will be rounded up/down to MAX_LEVEL and MIN_LEVEL
	 */
	public void setMagicPower(int magicPower) {
		if (magicPower < MIN_LEVEL)
			magicPower = MIN_LEVEL;
		if (magicPower > MAX_LEVEL)
			magicPower = MAX_LEVEL;
		this.magicPower = magicPower;
	}

	/**
	 * Set the school of the witch
	 * 
	 * @category setter
	 * @param school The school that the witch belong to.
	 */
	public void setSchool(String school) {
		this.school = school;
	}

	// Utilities
	/**
	 * Return the object as a formatted string
	 * 
	 * @category utility
	 * @Override java.lang.Object.toString()
	 * @return WitchString The formatted string containing all field of Object Witch
	 */
	@Override
	public String toString() {
		return String.format("Witchname: %s, School: %s, Magic Power: %s", this.name, this.school, this.magicPower);
	}

	/**
	 * Compare the power level of this witch to witch w
	 * 
	 * @category utility
	 * @param w The second witch object
	 * @return intPowerCompare 1 if this>w, 2 if this==w, 3 if this<w
	 */
	public int compareTo(Witch w) {
		if (this.magicPower > w.magicPower)
			return 1;
		else if (this.magicPower == w.magicPower)
			return 0;
		else if (this.magicPower < w.magicPower)
			return -1;
		return 9999; // This statement should not be called
	}

	/**
	 * Increase the witch's magicPower
	 * 
	 * @category utility
	 * @param increase a positive integer to increase the level of the witch by
	 *                 (this.magicPower+increase must be less than MAX_LEVEL)
	 */
	public void levelUp(int increase) {
		if (increase < 0)
			return;
		if (this.magicPower + increase > MAX_LEVEL)
			this.magicPower = MAX_LEVEL;
		else
			this.magicPower += increase;
	}
}
