function propertyTax() {
	xmlObject.call(this);
	
	this.actualValue="";
	this.estimatedValue="";
	this.fairMarketValue="";
	this.liensAndEncumberances="";
	this.netTax="";
	this.taxDue="";
	this.exemptCode="N";		//Default to "N"
	this.errors = new Array();	
	this.warnings = new Array();
	this.iHaveShownWarnings = 0; //incrementing count to the number of times it has been called

	this.isValid = function(bShow) {
		if (bShow==undefined)
			bShow = true;

		this.errors = new Array();
		var myDataError;

		if (bShow) {
			if (this.trimString(document.getElementById("actualValue").value).length > 0 && this.trimString(document.getElementById("estimatedValue").value).length > 0) {
				myDataError = new dataError();
				myDataError.description = 'You should fill in 1 or 1A but not both';
				myDataError.element = 'actualValue';
				this.errors.push(myDataError);
			}
		}

		if (this.trimString(this.actualValue).length == 0 && this.trimString(this.estimatedValue).length == 0) {
			myDataError = new dataError();
			myDataError.description = 'Block 1 or 1A must be completed';
			myDataError.element = 'actualValue';
			this.errors.push(myDataError);
		} else {
			if (this.trimString(this.actualValue).length > 0) {
				if (isNaN(this.trimString(this.actualValue))) {
					myDataError = new dataError();
					myDataError.description = 'Enter only numbers in Block 1';
					myDataError.element = 'actualValue';
					this.errors.push(myDataError);
				}
			}

			if (this.trimString(this.estimatedValue).length > 0) {
				if (isNaN(this.trimString(this.estimatedValue))) {
					myDataError = new dataError();
					myDataError.description = 'Enter only numbers in Block 1A';
					myDataError.element = 'estimatedValue';
					this.errors.push(myDataError);
				}
			}
		}

		if (this.exemptCode == 'N') {
			if (this.trimString(this.fairMarketValue).length == 0) {
				myDataError = new dataError();
				myDataError.description = 'Block 2 must be completed';
				myDataError.element = 'fairMarketValue';
				this.errors.push(myDataError);
			} else {
				if (isNaN(this.trimString(this.fairMarketValue))) {
					myDataError = new dataError();
					myDataError.description = 'Enter only numbers in Block 2';
					myDataError.element = 'fairMarketValue';
					this.errors.push(myDataError);
				}
			}

			if (this.trimString(this.liensAndEncumberances).length == 0) {
				myDataError = new dataError();
				myDataError.description = 'Block 3 must be completed';
				myDataError.element = 'liensAndEncumberances';
				this.errors.push(myDataError);
			} else {
				if (isNaN(this.trimString(this.liensAndEncumberances))) {
					myDataError = new dataError();
					myDataError.description = 'Enter only numbers in Block 3';
					myDataError.element = 'liensAndEncumberances';
					this.errors.push(myDataError);
				}
			}
			
			if (!isNaN(this.trimString(this.netTax))) {
				if ((Number(this.trimString(this.netTax)) < 0) && this.iHaveShownWarnings == 0) {
					myDataError = new dataError();
					myDataError.description = 'The values you have entered result in a \nnegative value for Net Taxable amount.  Please \nbe sure you entered the correct information.';
					myDataError.element = 'actualValue';
					this.warnings.push(myDataError);
				}
			}
		}		

		return this.errors.length == 0;
	}


	/* Trim String
	*
	* Does a VB Trim on a String
	*/
	this.trimString = function(str) {
	   return str.replace(/^\s+/g, '').replace(/\s+$/g, '');
	}
}


function PropertyTaxCalculation() {
	Panel.call(this);
	
	myTax = new propertyTax();
	
	// This is totally a hack function because I don't feel like doing round 4 with menu colors again
	// This allows me to figure out how many times it has been called
	this.warningCount = function () {
		myTax.iHaveShownWarnings += 1;
		return myTax.iHaveShownWarnings;
	}

	this.display = function() {					// override form.display
		this.getContainer().innerHTML=this.getForm();
		document.getElementById("dvTitle").innerHTML = this.getTitle();
		this.displayValues();
		this.focusFirstElement();
	}
	
	this.toXml = function() {
		return myTax.toXml();
	}
	
	this.trigger = function(aControl, anEvent) {
		if (anEvent == 'change') {
			/* 
			 * This may seem stupid, why not create another event and call
			 * it in the onChange right?  Well for some dumb ass reason
			 * two or more calls to theMediator object in the onChange event does
			 * not like to work.  I really don't care enough to figure out
			 * why or fix.  This works, if you want to fix it then be my guest
			 */
			this.round(aControl);

			if (this.checkActualEstimated(aControl) == false)
				return false;

			return this.calc(aControl);
		} else if (anEvent == 'exemptchange') {
			myTax.exemptCode = aControl.value;

			if (aControl.value == 'N')
				this.disableTaxControls(false);
			else
				this.disableTaxControls(true);
				
			this.loadEventDescriptions(aControl);
		} else if (anEvent == 'key')	{
			if (this.checkActualEstimated(aControl) == false)
				return false;
		}
	}
	
	
	/*
	 * Depending if they are exempt or not disable or enable the tax controls based on value
	 *
	 * value: true to disable controls; false to enable controls
	 * in the display function is actually disables the fields
	 */
	this.disableTaxControls = function(value) {
		with (myTax) {
			if (value) {
				fairMarketValue = "";
				liensAndEncumberances = "";
			}				
		}
		
		document.getElementById("actualValue").className='textFieldNormal';
		document.getElementById("estimatedValue").className='textFieldNormal';
		document.getElementById("fairMarketValue").className='textFieldNormal';
		document.getElementById("liensAndEncumberances").className='textFieldNormal';

		this.calcTaxDue();
		return true;
	}
	
	/*
	 * Load Event Descriptions
	 */
	this.loadEventDescriptions = function(aControl) {
		var sDesc;
		var sLabel = 'Description:';
		
		switch(aControl.value) {
			case 'ATP':
				sDesc = 'Consideration must be that of Principal; not Nominee.';
				break;
			case 'CD':
				sDesc = '"Deeds" to cemetery plots.';
				break;
			case 'CTIT':
				sDesc = 'Any deed, instrument, or other writing through which real property is transferred from a corporation, partnership, or other entity to one or more individuals if the individual or individuals to whom the property is transferred also have a majority ownership interest in the corporation, partnership, or other entity by which the property is transferred.';
				break;
			case 'CM':
				sDesc = 'Deeds transferring title from the old Corporation to the new Corporation as part of a merger.';
				break;
			case 'CTC':
				sDesc = 'Deeds conveying interest only when there is a Corporate Dissolution.';
				break;
			case 'DCTV':
				sDesc = 'Deeds filed to clear flaw or cloud in title when no consideration paid.';
				break;
			case 'DLF':
				sDesc = 'Any deed issued in lieu of foreclosure if the deed issued in lieu of foreclosure is for a purchase money deed to secure debt that has been in existence and properly executed and recorded for a period of 12 months prior to the recording of the deed in lieu of foreclosure.';
				break;
			case 'DOC':
				sDesc = 'Deeds correcting any error on a previous filing when there is no consideration.';
				break;
			case 'DOG':
				sDesc = 'Any deed or instrument which voluntarily transfers legal title to property for no consideration, that is for which no value is received in return.';
				break;
			case 'DBT':
				sDesc = 'Any transfer of real estate between a husband and wife in connection with a divorce case.';
				break;
			case 'ESTD':
				sDesc = 'Any deed of assent or distribution by an executor, administrator, guardian, trustee, or custodian; any deed or other instrument carrying out the exercise of a power of appointment; and any other instrument transferring real estate to or from a fiduciary; provided, however, that the exemption provided under this paragraph shall apply only if the transfer is without valuable consideration.';
				break;
			case 'FIFA':
				sDesc = 'Any deed that seeks to return any property sold at a tax sale back to the defendant in a FiFa.';
				break;
			case 'FTF':
				sDesc = 'The deed from the debtor to the first transferee at a foreclosure sale.';
				break;
			case 'GOV':
				sDesc = 'Any deed, instrument, or other writing to which any of the following is a party: the United States; this state; any agency, board, commission, department, or political subdivision of either the United States or this state; any public authority; or any nonprofit public corporation.';
				break;
			case 'ITCT':
				sDesc = 'Any deed, instrument, or other writing through which real property is transferred from one or more individual owners to a corporation, partnership, or other entity if the individual owner or owners of the real property also have a majority ownership interest in the corporation, partnership, or other entity to which the property is transferred.';
				break;
			case 'JTD':
				sDesc = 'Any deed, instrument, or other writing which effects a division of real property among joint tenants or tenants in common if the transaction does not involve any consideration other than the division of the property.';
				break;
			case 'PD':
				sDesc = 'Deeds which only change type method of ownership from undivided interest to divided interest with no change in portion.';
				break;
			case 'PRA':
				sDesc = 'Transfer of property which is acquired as provided in Code Sections 32-3-2 and 32-3-3.';
				break;
			case 'SDOR':
				sDesc = 'Deeds of Redemption from Sheriff’s Tax Sale.';
				break;
			case 'YSO':
				sDesc = 'Any order for year\'s support awarding an interest in real property as provided in Code Section 53-5-11 of the "Pre-1998 Probate Code," if applicable, or Code Section 53-3-11 of the "Revised Probate Code of 1998".';
				break;
			default:
				sDesc = '';
				sLabel = '';
				break;		
		}

		//this hides or shows the required field indicator so as not to cause confusion
		if (aControl.value == 'N') {
			document.getElementById("Number2Star").innerHTML = '*';
			document.getElementById("Number3Star").innerHTML = '*';

			document.getElementById("fairMarketValue").disabled = false;
			document.getElementById("liensAndEncumberances").disabled = false;
		} else {
			document.getElementById("Number2Star").innerHTML = '';		
			document.getElementById("Number3Star").innerHTML = '';		

			document.getElementById("fairMarketValue").disabled = true;
			document.getElementById("liensAndEncumberances").disabled = true;
		}
		
		document.getElementById("dvExemptLabel").innerHTML = sLabel;
		document.getElementById("dvExemptText").innerHTML = sDesc;
	}
	
	this.displayValues = function() {
		for(var i in myTax) {		
			if(typeof myTax[i] == "string"){
				document.getElementById(i).value = myTax[i];
				}
		}

		if (myTax.exemptCode != 'N') 
			var value = true;
		else
			var value = false;

		document.getElementById("fairMarketValue").disabled = value;
		document.getElementById("liensAndEncumberances").disabled = value;
		
		this.loadEventDescriptions(document.getElementById("exemptCode"));
	}

		
	this.setData = function() {
		for(var i in myTax) {		
			if(typeof myTax[i] != "object" && typeof myTax[i] != "function"  ){
				if (i != "iHaveShownWarnings")
					myTax[i] = document.getElementById(i).value;
				}
		}
	}

	
	this.hide = function() {
		this.setData();
				
		this.getContainer().innerHTML="";
	}

	
	this.focusFirstElement = function() {
		if ( myTax.errors.length == 0) {
			document.getElementById("actualValue").select();
		}
	}
	
	this.round = function(aControl) {
		if (isNaN(this.trimString(aControl.value))) {
			alert('Please enter only numbers in the ' + aControl.id + ' field');
			aControl.value = '';
			this.setData();
			this.displayValues();
		} else {
			if (aControl.id == 'actualValue') {
				if (this.trimString(document.getElementById("actualValue").value).length > 0)
					aControl.value = Math.round(aControl.value);
			} else if (aControl.id == 'estimatedValue') {
				if (this.trimString(document.getElementById("estimatedValue").value).length > 0)
					aControl.value = Math.round(aControl.value);
			} else {
				aControl.value = Math.round(aControl.value);
			}
		}
	}	
	
	this.checkActualEstimated = function(aControl) {
		if (this.trimString(document.getElementById("actualValue").value).length > 0 && this.trimString(document.getElementById("estimatedValue").value).length > 0) {
			this.setData();
			alert ("You should fill in 1 or 1A but not both.");
			with (myTax) {
				if (aControl.id == 'actualValue') {
					actualValue = "";
				} else {
					estimatedValue = "";
				}

				this.displayValues();
				return false;
			}
		}
		return true;
	}
	
	this.calc = function(aControl) {
		myTax[aControl.id]=aControl.value;
		with (myTax) {	
			if (aControl.id == "actualValue" || aControl.id == "estimatedValue") {
				if (this.trimString(aControl.value).length > 0)
					document.getElementById("fairMarketValue").select();
			}
			if ((actualValue || estimatedValue) && fairMarketValue && liensAndEncumberances) {
				this.calcTaxDue(false);
				return;
			} else if ((actualValue || estimatedValue) && myTax.exemptCode != 'N') {
				this.calcTaxDue(false);
				return;
			} else {
				myTax.netTax = '';
				myTax.taxDue = '';
				this.displayValues();
			}
		
		}
	}
	
	
	/*
	 * calcTaxDue
	 *
	 * Calculates the Tax due and displays the value
	 *
	 * bExempt: pass true if exempt and pass false if not
	 */
	this.calcTaxDue = function() {
		if (myTax.exemptCode != 'N') {
			with (myTax) {
				if (actualValue || estimatedValue) {
					netTax = "0";
					taxDue = "$0.00"
					this.displayValues();
					return true;
				} else {
					return true;
				}
			}
		} else {
			with (myTax) {
				netTax = ((Number(actualValue) + Number(estimatedValue)) - (Number(fairMarketValue) + Number(liensAndEncumberances))).toString();
						
				/*
				 * The dollar and cents method below may seem stupid but if you do
				 * alert(6 * .1); or alert(6 /10); you get .6000000000001 which messes up everything
				 * 
				 * However, if you round using a rounding trick to you get 0.6.  Below is the trick
				 * Math.round((6*.1)*10) / 10
				 *
				 * It is done below just make formatting easier and to avoid the stupid trick
				 */
				var taxDollars;
				var taxCents;
						
				if (Number(netTax) < 100) {
						taxDollars = 0
						taxCents = 0				
				} else {
					if (Number(netTax) <= 1000) {
						taxDollars = 1
						taxCents = 0				
					} else {
						taxDollars = Math.floor( Number(netTax) / 1000) < 1 ? 1 : Math.floor( Number(netTax) / 1000) * 1 ;
							
						taxCents = Number(netTax) % 1000.0;
						taxCents = Math.ceil(taxCents / 100.0);
						if (taxCents >= 10) {
							taxCents -= 10;
							taxDollars += 1;
						}
					}
				}

				taxDue = '$' + taxDollars.toString() + '.' + taxCents.toString() + '0';
				this.displayValues();
				return true;
			}
		}
	}

	
	this.isValid = function(bShow) {
		if (bShow==undefined)
			bShow = true;

		if (!myTax.isValid(bShow)) {
			if (bShow) 
				this.displayErrors();

			return false;
		} else {
			if (myTax.warnings.length > 0)  {
				this.displayWarnings();
				myTax.iHaveShownWarnings += 1;
				myTax.warnings = new Array();
			}
			
			return true;
		}
	}
	

	this.displayErrors = function() {
		var msgPop;

		msgPop = 'The following information is missing or incorrect:\n\n';
		for (var i in myTax.errors) {
			msgPop += '\t' + myTax.errors[i].description + '\n';
		}

		msgPop += '\nand will be highlighted on the form.';
		alert(msgPop);

		for (var i in myTax.errors) {
			document.getElementById(myTax.errors[i].element).className = 'textFieldError';
		}

		document.getElementById(myTax.errors[0].element).select();
	}
	
	
	this.displayWarnings = function() {
		var msgPop;

		msgPop = 'Important Notice:\n\n';
		for (var i in myTax.warnings) {
			msgPop += myTax.warnings[i].description + '\n';
		}

		alert(msgPop);
	}
	
	

	/* Trim String
	*
	* Does a VB Trim on a String
	*/
	this.trimString = function(str) {
	   return str.replace(/^\s+/g, '').replace(/\s+$/g, '');
	}
	
	
	/* 
	 * loadTax
	 *
	 * Inializes the Property Object
	 */
	this.loadTax = function(actualValue, estimatedValue, fairMarketValue, liensAndEncumberances, netTax, taxDue, exemptCode) {
		if (this.trimString(actualValue).length > 0)
			myTax.actualValue = actualValue;

		if (this.trimString(estimatedValue).length > 0)
			myTax.estimatedValue = estimatedValue;

		if (this.trimString(fairMarketValue).length > 0)
			myTax.fairMarketValue = fairMarketValue;

		if (this.trimString(liensAndEncumberances).length > 0)
			myTax.liensAndEncumberances = liensAndEncumberances;

		if (this.trimString(netTax).length > 0)
			myTax.netTax = netTax;

		if (this.trimString(taxDue).length > 0)
			myTax.taxDue = taxDue;

		if (this.trimString(exemptCode).length > 0)
			myTax.exemptCode = exemptCode;		
		else
			myTax.exemptCode = 'N';
	}	
}