
if (!console) var console = { log: function() {} };

dojo.require('dojo._base.html');
dojo.require('dojo.cookie');
dojo.require('dojo.date');
dojo.require('dojo.io.script');
dojo.require('dojo.number');

var hcsc = {
	Months: ['Month', 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'June', 'July', 'Aug', 'Sept', 'Oct', 'Nov', 'Dec' ],
	MIN_YEAR: (function() { var today = new Date(); return today.getFullYear() - 65; })(),
	MAX_DATE: (function() { var today = new Date(); today.setDate(today.getDate() + 90); return today; })(),
	MAX_YEAR: (function() { var today = new Date(); today.setDate(today.getDate() + 90); return today.getFullYear(); })(),
	MIN_DATE: new Date(),
	
	childTobaccoEl: [],
	
	calcMinEffectiveDate: function() { 
		if (dojo.byId('minEffDate') && dojo.byId('minEffDate').value) {
			var minDate = dojo.byId('minEffDate').value;
			var minDateArr = minDate.split(/\//);
			if (minDateArr.length == 3) {
				var d = new Date();
				d.setFullYear(minDateArr[0]);
				d.setMonth(dojo.number.parse(minDateArr[1]) - 1);
				d.setDate(minDateArr[2]);
				
				if (dojo.date.compare(d, new Date(), 'date') > 0) {
					hcsc.MIN_DATE = d;
				}
			}
		}
	},
	
	getScenarioValue: function() {
		var scenarioVal = 'Integrated Quote;Shop'; // default value
		var scenarioValEl = dojo.query('meta[name="WT.si_n"]');

		if (scenarioValEl && scenarioValEl.length > 0) {
			scenarioVal = scenarioValEl[0].content;
		}
		
		return scenarioVal;
	},
	
	captureQuote: function() {
		if (MultiTrackCall && dojo.isFunction(MultiTrackCall)) {
			MultiTrackCall(this.getScenarioValue(), '2;2', '0;0');
		}
	},
	
	captureApply: function() {
		if (MultiTrackCall && dojo.isFunction(MultiTrackCall)) {
			MultiTrackCall(this.getScenarioValue(), '3;3', '1;0');
		}
	},
	
	showQuote: function() {
		dojo.query('div.quote_step_two').style('display', 'block');
		dojo.query('div.tabberlive').style('display', 'block');
		dojo.query('div.quote_step_two').style('display', 'block');
		dojo.query('div.plan_details_glance').style('display', 'block');
		dojo.query('div.plan_details_glance_top').style('display', 'block');
		dojo.query('div.plan_details_glance_btm').style('display', 'block');
		dojo.style('quote_error', 'display', 'none');
	},
	
	hideQuote: function() {
		dojo.query('div.quote_step_two').style('display', 'none');
		dojo.query('div.tabberlive').style('display', 'none');
		dojo.query('div.quote_step_two').style('display', 'none');
		dojo.query('div.plan_details_glance').style('display', 'none');
		dojo.query('div.plan_details_glance_top').style('display', 'none');
		dojo.query('div.plan_details_glance_btm').style('display', 'none');
		dojo.style('quote_error', 'display', 'none');
	},

	createCheckboxDisplay: function(source, targetDiv) {
		var updated = function(event) {
			if (dojo.byId(source).checked) {
				dojo.style(targetDiv, 'display', 'block');
			} else {
				dojo.style(targetDiv, 'display', 'none');
			}		
		}
		
		updated();
		return dojo.connect(dojo.byId(source), 'onclick', updated);
	},
	
	childDiv: function(idx) {
		var childHtml = [
			'<div class="child_info">',			 
			'<select name="gender_', idx, '" class="gender">',
				'<option value="" selected="selected">Select Gender</option>',
				'<option value="M">Male</option>',
				'<option value="F">Female</option>',
			'</select>',
			'<select name="dobMonth_', idx, '" class="month"></select>',
			'<select name="dobDay_', idx, '" class="day"></select>',
			'<select name="dobYear_', idx, '" class="year dob"></select>',
			'<input type="text" id="heightFeet_', idx, '" name="heightFeet_', idx, '" class="ft" size="1" value="" /> <label for="heightFeet_', idx, '">ft. </label>',
			'<input type="text" id="heightInches_', idx, '" name="heightInches_', idx, '" class="in" size="2" value="" /> <label for="heightInches_', idx, '">in. </label>',
			'<input type="text" name="weight_', idx, '" id="weight_', idx, '" class="weight" size="6" value="" /> <label for="weight_', idx, '">lbs.</label>',
			'</div>',
			''
		];
		
		/* Uncomment to add UI for tobacco use for dependents in TX */
		if (this.getCorp() == 'tx' || this.getCorp() == 'nm') {
			childHtml.push('<div class="smokes" id="smokes_' + idx + '">');
			childHtml.push('<input id="smokes_' + idx + '_yes" type="radio" name="smokes_' + idx + '" class="smokes" value="True"/> <label for="smokes_' + idx + '_yes">Yes </label>');
			childHtml.push('<input id="smokes_' + idx + '_no" type="radio" name="smokes_' + idx + '" class="smokes" value="False"/> <label for="smokes_' + idx + '_no">No </label>');
			childHtml.push('</div>');
		}
		
		return childHtml.join('');
	},
	
	getCorp: function() {
		var corpEl = dojo.byId('corp');	
		return (corpEl && corpEl.value) ? corpEl.value : '';
	},
	
	fillYears: function(n) {
			if (n.options && n.options.length > 0) return;
			dojo.create('option', { innerHTML: 'Year', value: '', selected: 'selected' }, n, 'last');
	
			if (dojo.hasClass(n, 'dob')) {
				for (var y = (new Date()).getFullYear(); y >= hcsc.MIN_YEAR; y--) {
					dojo.create('option', { innerHTML: y, value: y }, n, 'last');	
				}
			} else {
				for (var y = (hcsc.MIN_DATE).getFullYear(); y <= hcsc.MAX_YEAR; y++) {
					dojo.create('option', { innerHTML: y, value: y }, n, 'last');	
				}		
			}
	},
	
	fillDays: function(n) {
			if (n.options && n.options.length > 0) return;
			dojo.create('option', { innerHTML: 'Day', value: '', selected: 'selected' }, n, 'last');
			for (var d = 0; d < 31; d++) {
				dojo.create('option', { innerHTML: d+1, value: d+1 }, n, 'last');	
			}		
	},
	
	fillMonths: function(n) {
		if (n.options && n.options.length > 0) return;
		dojo.create('option', { innerHTML: 'Month', value: '', selected: 'selected' }, n, 'last');
		for (var m = 1; m < hcsc.Months.length; m++) {
			dojo.create('option', { innerHTML: hcsc.Months[m], value: m }, n, 'last');	
		}		
	},
	
	getDateFromSelect: function(vals, name, suffix) {
		suffix = suffix || '';

		var month = dojo.number.parse(vals[name + 'Month' + suffix]);
		var day = dojo.number.parse(vals[name + 'Day' + suffix]);
		var year = dojo.number.parse(vals[name + 'Year' + suffix]);

		return new Date(year, month - 1, day);
	},
	
	getYearsOld: function(dob, at) {
		at = at || new Date();
		var yearsOld = at.getFullYear() - dob.getFullYear();
		if (dob.getMonth() > at.getMonth() || (dob.getMonth() == at.getMonth() && dob.getDate() > at.getDate())) {
			yearsOld--;
		}
		return yearsOld;
	},
	
	validateDate: function(vals, name, suffix) {
		var valid = true;
		suffix = suffix || '';
		
		var month = vals[name + 'Month' + suffix];
		var day = vals[name + 'Day' + suffix];
		var year = vals[name + 'Year' + suffix];
		
		valid &= month && dojo.string.trim(month).length > 0 && dojo.number.parse(month) > 0;
		valid &= day && dojo.string.trim(day).length > 0 && dojo.number.parse(day) > 0;
		valid &= year && dojo.string.trim(year).length > 0 && dojo.number.parse(year) > 0;
		
		return valid;
	},
	
	getDateStringFromSelect: function(vals, name, suffix) {
		var valid = true;
		suffix = suffix || '';
		
		var month = vals[name + 'Month' + suffix];
		var day = vals[name + 'Day' + suffix];
		var year = vals[name + 'Year' + suffix];
		
		return month + '/' + day + '/' + year;
	},
	
	checkZipCode: function(zipCode) {
		if (!zipCode) return "Zip code is required";
		
		zipCode = dojo.string.trim(zipCode)
		
		// required
		if (zipCode.length == 0) 
			return "Zip code is required";

		// length 5
		if (zipCode.length != 5)
			return "Zip code is not valid";

		// all digits
		if ((!/^\d+$/.test(zipCode))) 
			return "Zip code is not valid";
		
		return false;
	},
	
	validateOptionalNumber: function(val) {
		// it's optional, so if it's falsy, we're ok
		if (!val) return true;
	
		// if a value exists, then trim it
		val = dojo.string.trim(val);
	
		// if after trimming we have something, then test if its a number
		if (val.length > 0)
			return /^\d+$/.test(val);
		else
			return true;
	},
	
	normalizeHeight: function(vals, idx) {
		var feet = vals['heightFeet_' + idx];
		var inches = vals['heightInches_' + idx];
		
		if (!feet && !inches) return;
		
		if (feet && dojo.string.trim(feet).length > 0 && /^\d+$/.test(feet)) {
			if (!inches || dojo.string.trim(inches).length == 0) {
				dojo.query('input[name="heightInches_' + idx + '"]').forEach(function(el) { el.value = '0'; });
			}
		} 
		else if (inches && dojo.string.trim(inches).length > 0 && /^\d+$/.test(inches)) {
			if (!feet || dojo.string.trim(feet).length == 0) {
				dojo.query('input[name="heightFeet_' + idx + '"]').forEach(function(el) { el.value = '0'; });
			}
		}
	},
	
	validateApplicant: function(vals, idx) {
		// gender required
		if (!vals['gender_' + idx] || dojo.string.trim(vals['gender_' + idx]).length == 0) 
			return "Gender is required";

		// dob required
		if (!this.validateDate(vals, 'dob', '_' + idx))
			return "Date of birth is required";

		// weight
		if (!this.validateOptionalNumber(vals['weight_' + idx]))
			return "Weight is not valid";

		// height
		if (!this.validateOptionalNumber(vals['heightInches_' + idx]) || !this.validateOptionalNumber(vals['heightFeet_' + idx]))
			return "Height is not valid";
		
		// primary/spouse only checks
		if (idx == 'p' || idx == 's') {
			// check tobacco use for primary/spouse only (may have to change this later to support different state requirements)
			if (!vals['smokes_' + idx]) 
				return 'Please check Yes or No for Tobacco Use';			
		} else {
			var age = this.getAgeAtEffective(vals, idx);

			// check smoking on dependents in tx and nm over 17
			if (vals['corp'] == 'tx' || (vals['corp'] == 'nm' && age > 17)) {
				if (!vals['smokes_' + idx])
					return 'Please check Yes or No for Tobacco Use';
			}

			// in OK/TX, dependents have max age of 24
			if ((vals['corp'] == 'nm' || vals['corp'] == 'ok' || vals['corp'] == 'tx') && age >= 25) {
				return "The maximum age for dependent applicants is 24 year(s).";
			}
			
			// in IL, dependents have max age of 25
			if (vals['corp'] == 'il' && age >= 26) {
				return "The maximum age for dependent applicants is 25 year(s). If military retired please contact customer service toll free at 1-800-477-2000.";
			}
		}

		this.normalizeHeight(vals, idx);
	},
	
	getAgeAtEffective: function(vals, idx) {
		var birthdate = this.getDateFromSelect(vals, 'dob', '_' + idx);
		var effectiveDate = this.getDateFromSelect(vals, 'effectiveDate');
		return this.getYearsOld(birthdate, effectiveDate);
	},
	
	validateUnder65: function(vals, idx) {
		// check for over 65 for primary/spouse only
		if (this.getAgeAtEffective(vals, idx) >= 65) {
			return "We're sorry, we can only offer major medical or temporary insurance to individuals under age 65. For applicants aged 65 or older, we offer Medicare Supplement plans and Medicare Part D prescription drug plans. Please return to the home page to obtain details for Medicare Supplement Plans."
		}

		return "";
	},

	validatePlanFilter: function(vals) {
		var zipCodeErrors = this.checkZipCode(vals['zipCode']);
		if (zipCodeErrors) return zipCodeErrors;
			
		// required
		if (!this.validateDate(vals, 'effectiveDate'))
			return "Effective Date is required";
		
		// after today
		if (dojo.date.compare(this.getDateFromSelect(vals, 'effectiveDate'), new Date(), 'date') <= 0) 
			return "Effective Date must be after today";
		
		// greater than minimum date
		if (dojo.date.compare(this.getDateFromSelect(vals, 'effectiveDate'), hcsc.MIN_DATE, 'date') < 0) 
			return "Effective Date must be on or after " + (hcsc.MIN_DATE.toLocaleDateString ? hcsc.MIN_DATE.toLocaleDateString() : hcsc.MIN_DATE);

		// must be before 45 days in the future
		if (dojo.date.compare(this.getDateFromSelect(vals, 'effectiveDate'), hcsc.MAX_DATE, 'date') > 0) 
			return "Effective Date must be less than 45 days in the future";

		// check if it's at the end of the month
		var tempPlanEl = dojo.byId('plans_temp');
		if (!(tempPlanEl && tempPlanEl.value == 'true') &&  dojo.number.parse(vals['effectiveDateDay']) >= 29)
			return "Selecting the 29th, 30th, or 31st of the month as your effective date is only available for Temporary plans.";

		// check primary applicant
		var primaryError = this.validateApplicant(vals, 'p');
		if (primaryError) return primaryError + ' for Primary Insured (' + this.getDateStringFromSelect(vals, 'dob', '_p') + ')';
		
		// check primary is under 65
		var primaryUnder65 = this.validateUnder65(vals, 'p');
		if (primaryUnder65) return primaryUnder65;
		
		// check spouse if exists
		if (vals['has_spouse'] && vals['has_spouse'] == 'true') {
			var spouseError = this.validateApplicant(vals, 's');
			if (spouseError) return spouseError + ' for Spouse (' + this.getDateStringFromSelect(vals, 'dob', '_s') + ')';
			
			var spouseUnder65 = this.validateUnder65(vals, 's');
			if (spouseUnder65) return spouseUnder65;

			// check gender is different than primary
			if (vals['gender_p'] == vals['gender_s']) 
				return "Spouse's gender must be different than primary applicant's gender";
		}
		
		// check dependents
		var dependentCount = dojo.number.parse(vals['dependentCount'])
		
		if (vals['has_dependents'] == 'true' && dependentCount == 0) {
			return "Please specify number of children";
		}

		for (var i = 1; i <= dependentCount; i++) {
			var childError = this.validateApplicant(vals, i);
			if (childError) return childError + ' for Dependent ' + i + ' (' + this.getDateStringFromSelect(vals, 'dob', '_' + i) + ')';
		}

		return false;
	},
	
	isMaternityVisible: function(vals) {
		if (vals['corp'] == 'ok') {
			var hasSpouse = vals && vals['has_spouse'] && vals['has_spouse'] == 'true';
					
			// primary is female and 19 and over
			if (vals['gender_p'] == 'F' && this.getAgeAtEffective(vals, 'p') >= 19) {
				return true;
			}
			
			if (hasSpouse && vals['gender_s'] == 'F' && this.getAgeAtEffective(vals, 's') >= 19) {
				return true;
			}

			// neither 
			return false;
		}

		return true;
	},
	
	groupByPlanCode: function(data) {
		var ratesByPlanCode = {};
		
		dojo.forEach(data.plans, function(p) {
			dojo.forEach(p.rates, function(r) {
				var ratesForPlanCode = ratesByPlanCode[r.plan_code] || [];
				
				// calc the dental premium
				var premium = dojo.number.parse(r.premium);
				var dentalPremium = (r.dental) ? dojo.number.parse(r.dental_premium) : 0;
				r.premiumWithDental = dojo.number.round(premium + dentalPremium, 2);

				// filter out rates that are 999,999 or greater
				if (premium < 999999) {
					ratesForPlanCode.push(r);
				}
				
				// store it back
				ratesByPlanCode[r.plan_code] = ratesForPlanCode;
			});
		});
		
		return ratesByPlanCode;
	},
	
	formatDollar: function(d, whole) {
		return dojo.number.format(d, { currency: 'USD', symbol: '$', places: whole ? 0 : 2, type: 'currency' });
	},
	
	filterUniq: function(field, rates) {
		var used = {};
		var unique = [];
		
		var ratesToSearch = rates || [];
		
		dojo.forEach(ratesToSearch, function(rate, i) { 
			var val = rate[field]+'';
			if (val && !used.hasOwnProperty(val)) { 
				unique.push(val); 
				used[val] = true; 
			}
		});
		
		return unique;
	},
	
	sortCoverages: function(rates) {
		var coverages = this.filterUniq('coverage', rates);
		
		if (coverages.length > 1) {
			var coveragesVal = dojo.map(coverages, function(c) { 
				var n = (c.indexOf('%') > -1) ? c.substring(0, c.length - 1) : c; 
				return dojo.number.parse(n); 
			});
			coveragesVal.sort(function(a, b) { return a - b; });
			coverages = dojo.map(coveragesVal, function(c) { return c + '%'; });
		}
		
		return coverages;
	},
	
	sortDeductiblesWithCo: function(rates) {
		var deductibles = this.sortDeductibles(rates);
		var both = [];
		
		dojo.forEach(deductibles, function(d) {
			var coinsurances = this.filterUniq('coinsurance', rates);
			dojo.forEach(coinsurances, function(c) {
				both.push({deductible: d, coinsurance: c});
			});
		}, this);
		
		return both;
	},
	
	sortDeductibles: function(rates) {
		var deductibles = this.filterUniq('deductible', rates);
		deductibles.sort(function(a, b) { return a - b; });
		return deductibles;
	},
	
	applyCoinsurance: function(rates, coinsurances) {
		var idx = 0;
		
		if (!coinsurances) return;
				
		// here we sort the premiums descending, because the first (highest) premium should
		// be associated with the lowest co-insurance.
		var sortedByPremium = rates.sort(function(a, b) { 
			return b.premium - a.premium; 
		});

		dojo.forEach(sortedByPremium, function(r) {
			r['coinsurance'] = dojo.number.parse(coinsurances[idx++]);

			// make sure we don't go over the array size if they don't match
			if (idx >= coinsurances.length) {
				idx = (coinsurances.length - 1);
			}
		});
	},
	
	createChildTobaccoDisplay: function(childEl, idx) {
		var tobaccoUseEl = hcsc.single('div.smokes', childEl);
		
		if (tobaccoUseEl) {	
			var updateFunc = function(evt) {
				var vals = dojo.formToObject('planfilter_form');
				
				// check if dob and effective date is valid
				if (hcsc.validateDate(vals, 'dob', '_' + idx) && hcsc.validateDate(vals, 'effectiveDate')) {
					if (hcsc.getAgeAtEffective(vals, idx) > 17) {
						dojo.style(tobaccoUseEl, 'display', 'inline');
					} else {
						dojo.style(tobaccoUseEl, 'display', 'none');
					}
				} else {
					dojo.style(tobaccoUseEl, 'display', 'none');
				}
			};
			
			dojo.query('select', childEl).connect('onchange', updateFunc);
			updateFunc();
			
			hcsc.childTobaccoEl.push({el: tobaccoUseEl, update: updateFunc});
		}		
	},
	
	updateChildTobaccoDisplay: function() {
		dojo.forEach(hcsc.childTobaccoEl, function(el) {
			if (el.update && dojo.isFunction(el.update)) el.update();
		});
	},
	
	updateDependents: function() {
		var count = dojo.byId('dependentCount').selectedIndex;
		var childrenDiv = dojo.byId('children');

		for (var i = 1; i < 16; i++) {
			var childId = 'child_' + i;
			var childEl = dojo.byId(childId);
			
			if (i > count) {
				if (childEl) dojo.style(childEl, 'display', 'none');
			} else {
				// the child row isn't created, so create it now and populate
				if (!childEl) {
					var opts = { innerHTML: hcsc.childDiv(i), id: 'child_' + i, style: { display: 'none'} };
					childEl = dojo.create('div', opts, childrenDiv, 'last');
					dojo.create('div', { "class": 'float_fix' }, childrenDiv, 'last');

					dojo.query('select.year', childEl).forEach(hcsc.fillYears);
					dojo.query('select.month', childEl).forEach(hcsc.fillMonths);
					dojo.query('select.day', childEl).forEach(hcsc.fillDays);
					
					//var tobaccoUseEl = hcsc.single('div.smokes', childEl);
					
					// attach handlers only in NM
					if (hcsc.getCorp() == 'nm') {
						hcsc.createChildTobaccoDisplay(childEl, i);
					}
				}

				dojo.style(childEl, 'display', 'block');
			}
		}
	},
	
	reloadPlanFilterForm: function() {
		var planFilter = dojo.cookie('planfilter');
		var planFilterObj = (planFilter) ? dojo.fromJson(planFilter) : null;

		if (planFilterObj) {
			// update dependent views before setting from cookie
			if (planFilterObj.dependentCount) {
				dojo.byId('dependentCount').selectedIndex = planFilterObj.dependentCount;
				this.updateDependents();
			}

			for (f in planFilterObj) {
				if (planFilterObj.hasOwnProperty(f) && f != 'plans') {
					var val = planFilterObj[f];
					dojo.query('input[name="' + f +'"][type="text"]').forEach(function(n) { n.value = val; });
					dojo.query('input[name="' + f +'"][type="checkbox"]').forEach(function(n) { n.checked = (n.value == val) ? 'checked' : ''; });
					dojo.query('input[name="' + f +'"][type="radio"]').forEach(function(n) { n.checked = (n.value == val) ? 'checked' : ''; });					
					dojo.query('select[name="' + f + '"]').forEach(function(f) { 
						for (var i = 0; i < f.options.length; i++) {
							if (f.options[i].value == val) {
								f.selectedIndex = i;
								if (dojo.isIE) f.options[i].setAttribute('selected', true);
							}
						}
					});
				}
			}
		}
	},
	
	initPlanColumns: function() {
		var idx = 1;
		var planCodeEl = undefined;
		var columns = [];

		// get the list of default deductibles
		var defaultDeductibleEl = dojo.byId('defaultDeductible');
		var deductibles = (defaultDeductibleEl && defaultDeductibleEl.value) ? defaultDeductibleEl.value.split(/\|/) : [];
		deductibles = dojo.map(deductibles, dojo.number.parse);	

		while (planCodeEl = dojo.byId('planCodes-' + idx)) {
			var defaultDeductible = (idx <= deductibles.length) ? deductibles[idx-1] : null;
			var planCodes = planCodeEl.value.split(/,/);
			columns.push(new hcsc.PlanColumn(idx, defaultDeductible, planCodes));
			idx++;
		}
		
		return columns;
	},
	
	initPlanTables: function() {
		return dojo.query('.plan_details_glance').map(function(el) {
			return new hcsc.PlanTable(el);
		});		
	},
	
	filterRates: function(dataObj, planCodes) {
		var rates = [];
		dojo.forEach(planCodes, function(planCode) {
			if (dataObj[planCode]) rates = rates.concat(dataObj[planCode]); 
		});
		return rates;
	},
	
	single: function(query, root) {
		var list = [];
		if (dojo.isArrayLike(query) && dojo.isFunction(root)) {
			list = dojo.filter(query, root);
			
		} else {
			list = dojo.query(query, root);
		}
		
		return (list && list.length) ? list[0] : undefined;
	}

};

hcsc.PlanColumn = function(argIdx, argDeductible, argCodes, ratesObj) {
	var idx = argIdx;
	var defaultDeductible = argDeductible ? argDeductible : 0;
	var planCodes = argCodes;

	var allRates = [];
	var validRates = [];
	var deductibleEl = dojo.byId('deductible-' + idx);
	
	var _hasCoinsurance = false;
	
	var showNotAvailable = function(name) {
		var lastEl = undefined;
		var labelId = 'na-' + name + '-' + idx;
		var naLabelEl = dojo.byId(labelId);

		// hide the other elements
		dojo.query('input[name="' + name + '-' + idx + '"]').forEach(function(n) { 
			var lblEl = n.parentNode; 
			dojo.style(lblEl, 'display', 'none'); 
			lastEl = lblEl; 
		});

		// show or create the not available label			
		if (naLabelEl) {
			dojo.style(naLabelEl, 'display', 'inline');
		} else if (lastEl) { 
			dojo.create('label', { id: labelId, innerHTML: 'Option not available', 'class': 'not-available' }, lastEl, 'after'); 
		}
	}

	var selectRadioValue = function(name, value) {
		var radioToCheck = dojo
			.query('input[name="' + name + '-' + idx + '"]')
			.filter(function(o) { return o.value == (value + '') });
			
		if (radioToCheck.length > 0) dojo.attr(radioToCheck[0], "checked", true);	
	}
	
	var updateRadio = function(name) {
		var unique = hcsc.filterUniq(name, validRates);

		if (unique.length == 1) {
			selectRadioValue(name, unique[0]);
		//	showNotAvailable(name);
		} else {
			dojo.query('input[name="' + name + '-' + idx + '"]').forEach(function(o) { o.removeAttribute('disabled'); });
		}
	}

	var updateDentalRadio = function() {
		var unique = hcsc.filterUniq('dental', validRates);

		// if the only valid value is that it's not an option, then we hide
		if (unique.length == 1 && !unique[0]) {
		//	showNotAvailable('dental');
		} else {
			dojo.query('input[name="dental-' + idx + '"]').forEach(function(o) { o.removeAttribute('disabled'); });
		}
	}

	
	var updateDeductible = function() {
		var form = dojo.formToObject('planoptions_form');
		var deductible = form['deductible-' + idx];
		var selectedDeductible = deductible;
		
		if (_hasCoinsurance || (deductible && deductible.length > 0 && deductible.indexOf('|') >= 0)) {
			var deductibleVals = deductible.split(/\|/);
			if (deductibleVals && deductibleVals.length == 2) {
				selectedDeductible = { deductible: deductibleVals[0], coinsurance: deductibleVals[1] };
			}
		}

		// get valid rates for that deductible
		validRates = getValidRates(selectedDeductible);	

		updateRadio('coverage');
		updateRadio('maternity');
		updateDentalRadio();
		updatePremium();
	}

	var updatePremium = function(event) {
		var form = dojo.formToObject('planoptions_form');

		var selected = {
			coverage: form['coverage-' + idx],
			dental: form['dental-' + idx],
			maternity: form['maternity-' + idx]
		};
		
		var ratesForCoverage = dojo.filter(validRates, function(e) {
			var keep = true;
			if (selected.coverage && e.coverage != 'none') keep &= (e.coverage == selected.coverage);
			if (selected.maternity) keep &= ((e.maternity + '') == selected.maternity);
			return keep;
		});

		var selectedRate = ratesForCoverage[0];
		
		if (selectedRate) {
			var premium = (selected.dental == 'true') ? selectedRate.premiumWithDental : selectedRate.premium;

			dojo.byId('premium-' + idx).value = premium;
			dojo.byId('planCode-' + idx).value = selectedRate.plan_code;
			dojo.byId('deductibleVal-' + idx).value = selectedRate.deductible;
			dojo.byId('maternityVal-' + idx).value = selectedRate.maternity;
			dojo.byId('dentalVal-' + idx).value = (selectedRate.dental) ? selected.dental : 'false';
			dojo.byId('quote-' + idx).innerHTML = hcsc.formatDollar(premium);
		} else {
			dojo.byId('quote-' + idx).innerHTML = "Not Available";
		}		
	}
	
	var applyCoinsurance = function(rates) {
		var coinsuranceEl = dojo.byId('coinsurance-' + idx);
		var coinsuranceVal = (coinsuranceEl && coinsuranceEl.value) ? coinsuranceEl.value : '';
		var coinsurances = coinsuranceVal && coinsuranceVal.length > 0 ? coinsuranceVal.split(/,/) : [];
		
		if (coinsurances && coinsurances.length) {
			_hasCoinsurance = true;
			hcsc.applyCoinsurance(rates, coinsurances);
		}	
	}

	var init = function() {
		// sort through deductibles
		var deductibles = _hasCoinsurance ?
				hcsc.sortDeductiblesWithCo(allRates):
				hcsc.sortDeductibles(allRates);

		createDeductibleSelect(deductibles);

		// select the first premium
		var coverages = hcsc.sortCoverages(validRates);
		selectRadioValue('coverage', coverages[0]);
		selectRadioValue('dental', 'false');
		selectRadioValue('maternity', 'false');
		updatePremium();
	}

	var createDeductibleSelect = function(deductibles) {
		var selectedDeductible = false;
		
		dojo.empty(deductibleEl);
		dojo.forEach(deductibles, function(e, i) {
			var deductibleNumber = (_hasCoinsurance && e.deductible) ? e.deductible : e;
			var deductibleLabel = (_hasCoinsurance && e.deductible && e.coinsurance) ? 
				hcsc.formatDollar(e.deductible, true) + ', (' + hcsc.formatDollar(e.coinsurance, true) + ')': 
				hcsc.formatDollar(e, true);
			var deductibleVal = (_hasCoinsurance && e.deductible && e.coinsurance) ? e.deductible + '|' + e.coinsurance : e;
		
			var opts = { 
				innerHTML: deductibleLabel, 
				value: deductibleVal
			};
			
			// either the current is greater than the default or we're at the 
			// last deductible and haven't selected one
			if (!selectedDeductible && (deductibleNumber >= defaultDeductible || (i == deductibles.length - 1))) {
				opts.selected = 'selected';
				selectedDeductible = e;
			}
			
			dojo.create('option', opts, deductibleEl, 'last');
		}, this);
		
		validRates = getValidRates(selectedDeductible);	
	}
	
	var getValidRates = function(deductible) {
		var deductibleFilter = _hasCoinsurance ? 
			function(rate) { return rate.deductible == deductible.deductible && rate.coinsurance == deductible.coinsurance; } :
			function(rate) { return rate.deductible == deductible; };
		
		return dojo.filter(allRates, deductibleFilter);
	}
	
	var submitApplication = function(event) {
		dojo.stopEvent(event);		
		hcsc.captureApply();

		setTimeout(dojo.hitch(this, function() { 
			var applicationForm = dojo.byId('application_form-' + idx); 
			applicationForm.submit(); 
		}), 500);
	}
	
	// attach all of our handlers (only once)
	dojo.connect(deductibleEl, 'onchange', updateDeductible);
	dojo.connect(dojo.byId('apply-' + idx), 'onclick', submitApplication);	
	dojo.forEach(['coverage', 'maternity', 'dental'], function(name) {
		dojo.query('input[name="' + name + '-' + idx + '"]').connect('onclick', updatePremium);
	});
	
	// check if rates were passed in as arguments	
	if (ratesObj) updateRates(ratesObj);

	return {
		updateRates: function(d) {
			allRates = hcsc.filterRates(d, planCodes);
			applyCoinsurance(allRates);
			init();
		}
	};	
}

hcsc.PlanTable = function(argTabelEl) {
	var tableDiv = argTabelEl;

	var planCodesEl = hcsc.single('input[name="planCodeFilter"]', tableDiv);
	var planCodes = (planCodesEl && planCodesEl.value) ? planCodesEl.value.split(/,/) : [];

	var _tableForm = hcsc.single('form', tableDiv);
	var deductibleEl = hcsc.single('input[name="deductible"]', _tableForm);
	var planCodeEl = hcsc.single('input[name="planCode"]', _tableForm);

	var allRates = [];
	var rateCells = [];
	
	var _hasCoinsurance = false;
	
	var submitApplication = function(evt) {
		dojo.stopEvent(evt);

		// validate
		var formObject = dojo.formToObject(_tableForm);
		if (formObject['planCode'] == '') {
			alert('Select a deductible to apply');
			return false;
		}

		// call webtrends
		hcsc.captureApply();
		setTimeout(dojo.hitch(this, function() {
			_tableForm.submit();
		}), 500);
	}
	
	var updateCells = function(evt) {
		var f = dojo.formToObject(_tableForm);
		
		dojo.forEach(rateCells, function(cell, i) {
			cell.updatePremium((f['dental'] == 'true'), (f['maternity'] == 'true'));
		});

		return true;
	};
	
	var getRatePremium = function(rates, dental, maternity) {
		// use the rate for maternity if it exists, otherwise, just take the first			
		var rate = hcsc.single(rates, function(r) { return r.maternity == maternity; })
		var premium = 0;
		
		if (rate) {
			premium = dental ? rate.premiumWithDental : rate.premium;
		}
		else {
			premium = 'N/A';
		}

		return premium;
	}
	
	var createCell = function(rates) {
		var cell = dojo.create('td', { align: 'center' });		
		var premium = getRatePremium(rates, false, false);
		var rate = (rates.length) ? rates[0] : undefined;
		var rateId = 'premium-' + rate.plan_code + '-' + rate.deductible + '-' + rate.coverage;

		dojo.place('<input type="radio" name="premium" value="' + premium + '" id="' + rateId + '"/>', cell);
		var radioList = dojo.query('input[name="premium"]', cell);
		var premiumRadio = radioList[0];
		var premiumLabel = dojo.create('label', { 'for': rateId, 'innerHTML': hcsc.formatDollar(premium) }, cell);

		var clickBind = dojo.connect(premiumRadio, 'onclick', function(evt) {
			var formObject = dojo.formToObject(_tableForm);
			var rate = hcsc.single(rates, function(r) { return r.maternity == (formObject['maternity'] == 'true'); });
			planCodeEl.value = rate.plan_code;
			deductibleEl.value = rate.deductible;
		});
		
		return {
			node: cell,
			updatePremium: function(dental, maternity) {
				var premium = getRatePremium(rates, dental, maternity);
				premiumRadio.value = premium;
				premiumLabel.innerHTML = hcsc.formatDollar(premium);
			},
			disconnect: function() {
				if (clickBind) dojo.disconnect(clickBind);
			}
		};
	}
	
	var createRow = function(deductible) {
		var formObject = dojo.formToObject(_tableForm);
		var deductibleFilter = _hasCoinsurance ? 
			function(rate) { return rate.deductible == deductible.deductible && rate.coinsurance == deductible.coinsurance; } :
			function(rate) { return rate.deductible == deductible; };
		var ratesForDeductible = dojo.filter(allRates, deductibleFilter);

		// create row
		var rateRow = dojo.create('tr', { 'class': 'planContent' });

		// create the header cell
		var deductibleVal = _hasCoinsurance && deductible.deductible ? deductible.deductible : deductible;
		dojo.create('td', { innerHTML: hcsc.formatDollar(deductibleVal, true) }, rateRow);

		// create text description cell
		var prescriptionVal = hcsc.filterUniq('prescription', ratesForDeductible); // should only be one
		var drugCoverage = (prescriptionVal.length == 1 && prescriptionVal[0]) ? formObject['drugCoverageRx'] : formObject['drugCoverage'];
		dojo.create('td', { innerHTML: drugCoverage }, rateRow);

		// add optional cell for co-insurance max
		if (_hasCoinsurance && deductible.coinsurance) {
			var coinsuranceVal = deductible.coinsurance;
			dojo.create('td', { innerHTML: hcsc.formatDollar(coinsuranceVal, true) }, rateRow);
		}

		// for each of the coverages, create a cell
		dojo.forEach(hcsc.sortCoverages(ratesForDeductible), function(coverage) {
			var ratesForCoverage = dojo.filter(ratesForDeductible, function(rate) { 
				return rate.coverage == coverage; 
			});
			
			if (ratesForCoverage.length) {
				var cell = createCell(ratesForCoverage);
				rateCells.push(cell);
				dojo.place(cell.node, rateRow);
			}
		});

		return rateRow;
	}
	
	var applyCoinsurance = function(rates) {
		var formObject = dojo.formToObject(_tableForm);
		var coinsurances = formObject['coinsurance'] ? formObject['coinsurance'].split(/,/) : [];
		
		if (coinsurances && coinsurances.length) {
			_hasCoinsurance = true;
			hcsc.applyCoinsurance(rates, coinsurances);
		}
	}

	var init = function() {
		// set dental/maternity opts
		dojo.query('input[name="dental"][value="false"]', tableDiv).forEach(function(el) {el.checked = true;});
		dojo.query('input[name="maternity"][value="false"]', tableDiv).forEach(function(el) {el.checked = true;});
		
		// reset hidden fields
		planCodeEl.value = '';
		deductibleEl.value = '';

		// clear existing cells
		dojo.forEach(rateCells, function(cell, i) { if (cell) cell.disconnect(); });		
		rateCells = [];
		
		var tbody = hcsc.single('table.table_deductible_details tbody', tableDiv);		
		if (tbody) {
			var deductibles = _hasCoinsurance ?
				hcsc.sortDeductiblesWithCo(allRates):
				hcsc.sortDeductibles(allRates);

			dojo.empty(tbody);
			dojo.forEach(deductibles, function(deductible) { 
				var row = createRow(deductible);
				dojo.place(row, tbody);
			});
		}
	}
	
	// connect all of our handlers 
	dojo.query('input[name="dental"]', tableDiv).connect('onclick', updateCells);
	dojo.query('input[name="maternity"]', tableDiv).connect('onclick', updateCells);
	dojo.query('a.apply span', tableDiv).connect('onclick', submitApplication);	

	return {
		updateRates: function(d) {
			allRates = hcsc.filterRates(d, planCodes);
			applyCoinsurance(allRates);
			init();
		}		
	};
}

dojo.addOnLoad(function() {
	hcsc.calcMinEffectiveDate();

	var planColumns = hcsc.initPlanColumns();
	var planTables = hcsc.initPlanTables();

	// hide all the quote elements	
	hcsc.hideQuote();

	// populate selects with values	
	dojo.query('select.year').forEach(hcsc.fillYears);
	dojo.query('select.day').forEach(hcsc.fillDays);	
	dojo.query('select.month').forEach(hcsc.fillMonths);	

	// reload form data from cookie
	hcsc.reloadPlanFilterForm();
	
	// setup event handlers and update display after we've updated form values
	hcsc.createCheckboxDisplay('has_spouse', 'spouse');
	hcsc.createCheckboxDisplay('has_dependents', 'dependents_section');
	dojo.connect(dojo.byId('dependentCount'), 'onchange', hcsc.updateDependents);
	
	// update dependent display
	hcsc.updateDependents();
	
	if (hcsc.getCorp() == 'nm') {
		hcsc.updateChildTobaccoDisplay();
		dojo.connect(dojo.byId('effectiveDateMonth'), 'onchange', hcsc.updateChildTobaccoDisplay);
		dojo.connect(dojo.byId('effectiveDateDay'), 'onchange', hcsc.updateChildTobaccoDisplay);
		dojo.connect(dojo.byId('effectiveDateYear'), 'onchange', hcsc.updateChildTobaccoDisplay);
	}
	
	dojo.connect(dojo.byId('show_quote'), 'onclick', function(event) {
		dojo.stopEvent(event);
		
		// set the child count to 0 if its hidden
		if (!dojo.byId('has_dependents').checked) {
			dojo.byId('dependentCount').selectedIndex = 0;
		}
		
		// do some kind of validation here
		var demoForm = dojo.formToObject('planfilter_form');
		var errors = hcsc.validatePlanFilter(demoForm);
		
		// show the first error and return
		if (errors) {
			alert(errors);
			return;
		}

		// prep the ui to wait for the async return
		dojo.style('quote_loader', 'display', 'block');
		hcsc.hideQuote();
		
		var hasSpouse = demoForm && demoForm['has_spouse'] && demoForm['has_spouse'] == 'true';
		var hasChildren = demoForm && demoForm['has_dependents'] && demoForm['has_dependents'] == 'true';
		
		// show the out-of-pocket fields based on demo form submitted
		if (hasSpouse || hasChildren) {
			dojo.query('span.oop-indiv').style('display', 'none');
			dojo.query('span.oop-family').style('display', 'inline');
		} else {
			dojo.query('span.oop-indiv').style('display', 'inline');
			dojo.query('span.oop-family').style('display', 'none');
		}
		
		// hide maternity rows/divs if individual male
		
		if (hcsc.isMaternityVisible(demoForm)) {
			dojo.query('tr.maternity_coverage').style('display', '');
			dojo.query('div.maternity_coverage').style('display', 'block');
		} else {
			dojo.query('tr.maternity_coverage').style('display', 'none');
			dojo.query('div.maternity_coverage').style('display', 'none');
		}
		
		
		// save the demographic data into a cookie
		var demoData = dojo.formToJson('planfilter_form');
		dojo.cookie('planfilter', demoData);
		
		// save the applicant data to the plans
		dojo.query('input[name="applicants"]').forEach(function(el) {
			el.value = demoData;
		});
		
		var ajaxConfig = {
			form: 'planfilter_form',
			callbackParamName: 'jsonpcallback',
			handleAs: 'json',
			load: function(data) {
				if (data.errors) {
					for (var e in data.errors) {
						alert(data.errors[e][0]);
						dojo.style('quote_loader', 'display', 'none');
						return;
					}
				} 
				else if (!data.plans || data.plans.length == 0) {
					dojo.style('quote_error', 'display', 'block');
				}
				else {
					// regroup the rates by plan code
					var ratesByPlanCode = hcsc.groupByPlanCode(data);
					
					// load the objects with the latest data
					dojo.forEach(planColumns, function(p) { p.updateRates(ratesByPlanCode); });
					dojo.forEach(planTables, function(p) { p.updateRates(ratesByPlanCode); });
					
					// show the quote info
					hcsc.showQuote();

					// submit webtrends
					hcsc.captureQuote();
				}
				
				// hide the loader
				dojo.style('quote_loader', 'display', 'none');
			},
			error: function(e) {
				console.log('ERROR', e);
				dojo.style('quote_loader', 'display', 'none');
				dojo.style('quote_error', 'display', 'block');
			}
		};

		dojo.xhrPost(ajaxConfig);
	});

	// finally hide the loader and show the form
	dojo.style('quote_loader', 'display', 'none');
	dojo.style('planfilter_form', 'display', 'block');
	
});