(function( $ ){
	
	$.fn.MortgagePreQualifier = function(method, options){
	
		var CANNOT_QUALIFY ="We can't pre-qualify you without more information";//L43
		var NA="NA";// no value
	//constant multiplier  value for calcuation
		var TYPE_OF_WORK_MULTIPLIER= 10;
		var CREDIT_MULTIPLIER=7;
		var DOWNPAYMENT_SOURCE_MULTIPLIER=10;
		var HOME_TYPE_MULTIPLIER=5;

	//mortgage constants
		var MONTHLY_DEBT_PAYMENT = 0.03;//average monthly debt payment (all kinds of debt)  --- I2
		var MINIMUM_DOWN_PAYMENT = 0.05;//Minimum downpayment required by law -- I3
		var AVERAGE_MORTGAGE_RATE = 0.06;//average mortgage interest rate -- I4
		var AVERAGE_MORTGAGE_AMMORTIZATION = 35;//average mortgage ammortization -- I5 , 35 years mortgage
		var MINIMUM_REQUIRED_GDS = 0.32;//Minumum required GDS  -- I6
		var MINIMUM_REQUIRED_TDS = 0.40;//Minumum required TDS  -- I7
		var HEAT = 85;//$85 -- I8
		
		var TOTAL_WEIGHT_AVERAGE = 320;// L39, TYPE_OF_WORK_MULTIPLIER , CREDIT_MULTIPLIER ,DOWNPAYMENT_SOURCE_MULTIPLIER ,HOME_TYPE_MULTIPLIER;
		var MINIMUM_REQUIRED_AVERAGE = 0.6;//L40
		var MINIMUM_LOAN_AMOUNT =150000;//L41

	//CMHC  - insurence for the morgage -- array
		var downpaymentRates = new Array(5,10,15,20); //downpayment percentage 
		var insuranceRates = new Array(2.75,2.00,1.75,0.00);//insurance percentage
		
	//varibles
		var annualIncome;
		//var monthlyIncome = annualIncome/12;
		var workType;
		var currentDebts;//current monthly debts
		var credit;
		var bankruptcy;
		var homeType;
		var downPayment;
		var downpaymentSource;
		var estimatedMonthlyCondoFee;
		var estimatedAnnualTax;
		
	//reprot part --- result
		var preQualifiedMortgage;
		var maxHousePrice;
		var monthlyPayment;

		var defaults = {
			'verified' : '0',
			'ajaxTarget' : 'listings'
		}
		var settings = null;
		
		var methods = {
			init : function(options){
				return this.each(function(){
					var $this = $(this);
					settings = {};
					
					$.extend(settings, defaults, options);
					$this.data('preQualSettings', settings);
					
					//option  1: client info verified, 0: not verified
					//only if client info is verified then we will calculate the prequalified mortgage
					if(settings.verified == "1"){
						helpers["mortPreQ_calculate"].call($this);
					}
				});
			},
			// event handler for cancel and submit button on the mortgage prequalifier form
			// goto server controller and send out email
			submitPreQForm : function(){
				return this.each(function(){
					var $this = $(this);
					settings = {};
					settings = $this.data("preQualSettings");
					
					var host = document.location.host; //important variable. Contains the calling domain.
					if(host.indexOf("www.") != -1) host = host.replace("www.", ""); //strip the "www." from the host url
					
					$.ajax({
						type : "GET",
						url : settings.ajaxTarget,
						data : "pathway=537&submitPreQualifier=true&"+$("#mortgagePreQInfoForm").serialize()+"&url="+host,
						dataType : "html",
						error : function(data,error){
							alert("submit mortgage preQualifier failed: " + data +" " + error);
						},
						success : function(data){
							$("#cs-prequalifier-container").html(data);
						},
						beforeSend : function(){
							//$('#cs-prequalifier-container').block({ message: 'Loading Qualifier, Please wait...'+' <img src="/t/resources/rpm3.0/images/activity/indicator_medium.gif" />' });
						},	
						complete : function (XMLHttpRequest, textStatus) {
							//$('#cs-prequalifier-container').unblock();
							$("label[for='bankruptcy']").parents("div.cs-input-small").removeClass("cs-input-small");
							$.clickSoldUtils('infoBoxResize');
						}
					}); 
				});	
			}
		};
		
		var helpers = {
			/**
			* get all form input value, and check if input should be number but not number then correct them
			*/
			getFormValue : function(){
				//get values from the form interface
				annualIncome = parseFloat($("#annualIncome").val());
				if(isNaN(annualIncome))
					$("#annualIncome").attr("value","0");
				currentDebts = parseFloat($("#currentDebts").val());
				if(isNaN(currentDebts))
					$("#currentDebts").attr("value","0");
				downPayment = parseFloat($("#downpayment").val());
				if(isNaN(downPayment))
					$("#downpayment").attr("value","0");
				estimatedMonthlyCondoFee = parseFloat($("#conFees").val());
				if(isNaN(estimatedMonthlyCondoFee))
					$("#condoFees").attr("value","0");
				estimatedAnnualTax = parseFloat($("#propTax").val());
				if(isNaN(estimatedAnnualTax))
					$("#annualTax").attr("value","0");
				
				// Each of these has a weight attached to it. We need to map the selected option to the weight, before the value of the
				// option was the weight but this confused the framework as there were duplicates.
				workType = parseInt($("#typeOfWork").val());//opiton  drop down
				if(isNaN(workType))
					workType = 0;
				switch (workType) {
					case 0: workType = 0;  break;
					case 1: workType = 10; break;
					case 2: workType = 9;  break;
					case 3: workType = 8;  break;
					case 4: workType = 7;  break;
					case 5: workType = 6;  break;
					case 6: workType = 6;  break;
					case 7: workType = 6;  break;
					case 8: workType = 5;  break;
					case 9: workType = 0;  break;
					default: workType = 0;
				}
						
				credit = parseInt($("#credit").val());
				if(isNaN(credit))
					credit = 0;
				switch (credit) {
					case 0: credit = 0;  break;
					case 1: credit = 0;  break;
					case 2: credit = 0;  break;
					case 3: credit = 5;  break;
					case 4: credit = 8;  break;
					case 5: credit = 10; break;
					default: credit = 0;
				}

				homeType = parseInt($("#homeType").val());
				if(isNaN(homeType))
					homeType = 0;
				switch (homeType) {
					case 0: homeType = 0;  break;
					case 1: homeType = 10; break;
					case 2: homeType = 9;  break;
					case 3: homeType = 0;  break;
					case 4: homeType = 7;  break;
					case 5: homeType = 6;  break;
					default: homeType = 0;
				}
				
				downpaymentSource = parseInt($("#downpaymentSource").val());
				if(isNaN(downpaymentSource))
					downpaymentSource = 0;
				switch (downpaymentSource) {
					case 0: downpaymentSource = 0;  break;
					case 1: downpaymentSource = 10; break;
					case 2: downpaymentSource = 10; break;
					case 3: downpaymentSource = 10; break;
					case 4: downpaymentSource = 10; break;
					case 5: downpaymentSource = 5;  break;
					case 6: downpaymentSource = 5;  break;
					default: downpaymentSource = 0;
				}
				
				bankruptcy = ($("#bankruptcy").attr("checked") == true)?1:0;
			},
			
			/**
			*
			*/
			mortPreQ_calculate : function(){
				return this.each(function(){
					var $this = $(this);
					var settings = $this.data("preQualSettings");
				
					//inter media variable
					var pre_qual_mortgage;//E6, result for showing
					var max_house_price;//E7, maximum house price 
					//var stopper;//E56,E57,E58
					var best_case_mortgage;//E41 best case mortgage amount
					var best_purchase_price;//E42 best case mortgage purchase price
					var best_case_mortgage_cal;//calculate principal outstanding before compare downpayment calculation
					var average;//G52
					//var total_weight_average;//L39
					var total_weight;//G51
					var max_monthly_payment;//E39
					var GDS;// Gross Debt Service, Total Allowable Monthly Mortgage Payment E32
					var TDS;//Total Debt Service, Total Allowable Monthly Mortgage Payment E35
					var lower_DS;//lower of the GDS or TDS  E39
					var mortgage_base_on_downpayment;//Total Allowable Mortgage based on downpayment E37
					var bankruptcyStopper;
					var averageStopper;
					var minimumStopper;
					
					var total_weight;//G51
					var mortgage_by_weight;//E54, Allowable mortgage by weighted average
					var price_by_weight;//E55, allowable price by weighted average
					var downPayment_rate;
					var insurance_rate;
					var CMHC_price;//E43 --todo
					var total_allowed_purchase_price;//E44 --- todo
					
					helpers["getFormValue"].call($this);
					
					GDS = MINIMUM_REQUIRED_GDS * (annualIncome/12) - (estimatedMonthlyCondoFee + estimatedAnnualTax/12 + HEAT);
					TDS = MINIMUM_REQUIRED_TDS * (annualIncome/12) - (estimatedMonthlyCondoFee + currentDebts + estimatedAnnualTax/12 + HEAT);
					lower_DS = (GDS > TDS)?TDS:GDS;
					
					mortgage_base_on_downpayment = helpers["toCurrency"].call($this, downPayment/MINIMUM_DOWN_PAYMENT);
					best_case_mortgage_cal = helpers["toCurrency"].call($this, lower_DS *(1-Math.pow(Math.pow((1+AVERAGE_MORTGAGE_RATE/2),(1/6)),(-12)*AVERAGE_MORTGAGE_AMMORTIZATION))/(Math.pow((1+AVERAGE_MORTGAGE_RATE/2),(1/6))-1));
					
					best_case_mortgage = (best_case_mortgage_cal < mortgage_base_on_downpayment)?best_case_mortgage_cal:mortgage_base_on_downpayment;
					
					best_purchase_price = best_case_mortgage/1 + downPayment/1;//no use  calculate here
					
					//alert("best_case_mortgage_cal: " + best_case_mortgage_cal + "   mortgage_base_on_downpayment: " +mortgage_base_on_downpayment + "  best_case_mortgage:"+best_case_mortgage);
					//alert("best_purchase_price: " +best_purchase_price+"  downpayment:"+ downPayment);
					//alert("GDS TDS: " + GDS + "  " + TDS);
					
					if(best_case_mortgage == 0){
						//alert("failed by best_case_mortgage =0");
						//pre_qual_mortgage = CANNOT_QUALIFY;
						//max_house_price = CANNOT_QUALIFY;
						$("#prequal_mortgage").html("NA");
						$("#max_house_Price").html(CANNOT_QUALIFY);
						$("#monthly_payments").html("NA");
					}
					else{
						//alert(workType +"--"+ TYPE_OF_WORK_MULTIPLIER +"--"+  credit+"--"+  CREDIT_MULTIPLIER +"--"+  downpaymentSource +"--"+ DOWNPAYMENT_SOURCE_MULTIPLIER +"--"+  homeType +"--"+ HOME_TYPE_MULTIPLIER);
						total_weight = workType * TYPE_OF_WORK_MULTIPLIER + credit * CREDIT_MULTIPLIER + downpaymentSource * DOWNPAYMENT_SOURCE_MULTIPLIER + homeType * HOME_TYPE_MULTIPLIER;
						if(workType*credit*downpaymentSource*homeType==0){
							total_weight =0;
						}
						average = total_weight/TOTAL_WEIGHT_AVERAGE;
						//alert("work credit downpayment hometype total_weight average: "+ workType +"  " +credit+"  "+ downpaymentSource+"  " + homeType+"  "+total_weight + "  " + average);
						
						//get the CMHC
						downPayment_rate = (downPayment/best_case_mortgage)*100;
						if(downPayment_rate>= downpaymentRates[3])
							insurance_rate = insuranceRates[3];
						else if(downPayment_rate>= downpaymentRates[2])
							insurance_rate = insuranceRates[2];
						else if(downPayment_rate>= downpaymentRates[1])
							insurance_rate = insuranceRates[1];	
						else if(downPayment_rate>= downpaymentRates[0])
							insurance_rate = insuranceRates[0];
						//else  won't get here because  because we tested this value by mortgage_base_on_downpayment
						
						CMHC_price=helpers["toCurrency"].call($this, best_case_mortgage * insurance_rate/100);			

						
						mortgage_by_weight = best_case_mortgage * average;
						price_by_weight = mortgage_by_weight/1 + downPayment/1 - CMHC_price;
						//alert("mortgage_by_weight: " + mortgage_by_weight/1 + "   CMHC_price"+ CMHC_price);
						//calculate 3 stopper 
						bankruptcyStopper = (bankruptcy == 0)?1:0;
						averageStopper = ((total_weight/TOTAL_WEIGHT_AVERAGE)>MINIMUM_REQUIRED_AVERAGE)?1:0;
						minimumStopper = (price_by_weight>MINIMUM_LOAN_AMOUNT)?1:0;
						//alert("price_by_weight  minimum_loan_amount stopper(bankruptcy average minimum): " + price_by_weight + " -- " + MINIMUM_LOAN_AMOUNT +" ("+bankruptcyStopper +","+ averageStopper +","+minimumStopper+")");
						
						pre_qual_mortgage = mortgage_by_weight * bankruptcyStopper * averageStopper * minimumStopper;
						max_house_price = price_by_weight *  bankruptcyStopper * averageStopper * minimumStopper;
						
						if(pre_qual_mortgage == 0){
							//alert("failed by the stopper");
							$("#prequal_mortgage").html("NA");
							$("#max_house_Price").html(CANNOT_QUALIFY);
							$("#monthly_payments").html("NA");
						}
						else{
							$("#prequal_mortgage").html("$" + helpers["toCurrency"].call($this, pre_qual_mortgage));
							$("#max_house_Price").html("$" + helpers["toCurrency"].call($this, max_house_price));
							$("#monthly_payments").html("$" + helpers["toCurrency"].call($this, lower_DS * average));
						}
					}
				});
			},			
			/*
			*The toFixed() method rounds the Number to the specified number of decimal places.
			*/
			toCurrency : function(value){
				if(typeof value == "number"){
					return new Number(value.toFixed(2));
				}else{
					return new Number(parseFloat(value).toFixed(2));
				}
			}
		};
			
		if( methods[method] ){  //Method call
			return methods[method].apply(this, Array.prototype.slice.call( arguments, 1 ));
		}else if(typeof method === "object"){  //Initialization call - must have arguments
			return methods.init.apply(this, arguments);
		}else{  //ERROR
			$.error("Method " + method + " does not exist on jQuery.MortgagePreQualifier");
		}
			
	};
	
})( jQuery );

