/* KC NAMESPACE */
var KC = {
	// UTILITY FUNCTIONS
	_$: function (e) {
		if ( typeof e == 'string' )
			e = document.getElementById (e);
		return e;
	},
	$: function (e) {
		e = this._$ (e);
		KC.Object.extend (e, this.Element);
		return e;
	},
	$A: function (e) {
		e = this._$ (e);
		KC.Object.extend (e, this.Enumerable);
		return e;
	},
	$F: function (e) {
		e = this.$(e);

		if ( e.getAttribute ('type') == 'checkbox' || e.getAttribute ('type') == 'radio' )
			e = this.$(e).checked;
		else
			e = this.$(e).value;

		return e;
	},
	$$: function (s) {
		var aFound = [];
		var oCond = new RegExp ('\\b' + s + '\\b');
		KC.$A(document.getElementsByTagName ('*')).each (function (e) {
			if ( oCond.test (e.className) )
				aFound.push (e);
		});

		return aFound;
	},
	SelectOption: function (sSelected, eList) {
		eList = this.$(eList);

		for (var i = 0; i < eList.options.length; i++)
		{
			if (eList.options[i].value == sSelected)
			{
				eList.selectedIndex = i;
				break;
			}
		}
	},
	Go:  function (sUrl) {
		setTimeout (function () {
			window.location = sUrl;
		}, 0);
	}
};

// ELEMENT
KC.Element = {
	show: function () {
		this.style.display = 'block';
	},
	hide: function () {
		this.style.display = 'none';
	},
	toggle: function () {
		if ( this.style.display == 'none' )
			this.show ();
		else
			this.hide ();
	},
	update: function (sContents) {
		this.innerHTML = sContents;
	},
	observe: function (sEvent, funcRun) {
		KC.Event.observe (this, sEvent, funcRun);
	},
	enable: function () {
		this.disabled = false;
	},
	disable: function () {
		this.disabled = true;
	}
};

// ENUMERABLE
KC.Enumerable = {
	each: function (funcRun) {
		for (var i = 0; i < this.length; i++)
			funcRun (this[i], i);
	},
	find: function (sSearch) {
		for (var i = 0; i < this.length; i++)
		{
			var v = this[i];
			if ( v == sSearch )
				return i;
		}

		return false;
	}
};

// OBJECT
KC.Object = {
	extend: function (oDes, oSource) {
		for (var sName in oSource)
			oDes[sName] = oSource[sName];
	}
};

// AJAX
KC.Ajax = {
	_X: function () {
		try {
			return new ActiveXObject ('Msxml2.XMLHTTP');
		}
		catch (e) {
			try {
				return new ActiveXObject ('Microsoft.XMLHTTP');
			}
			catch (e) {
				try {
					return new XMLHttpRequest ();
				}
				catch (e) {
					alert ('Your web browser is too old to support features of this web site.\n\nPlease upgrade your web browser.');
					return null;
				}
			}
		}
	},
	Request: function(sUrl, aParams) {
		var x = this._X();

		if ( x )
		{
			x.open ('POST', sUrl, true);
			x.onreadystatechange = function () {
				if ( x.readyState == 1 ) {
					if ( typeof aParams.onLoading == 'function' )
						aParams.onLoading ();
				} else if ( x.readyState == 4 ) {
					var t = x.responseText;
					var ct = x.getResponseHeader ('Content-Type');

					if ( ct == 'application/json' )
						t = eval ('(' + t + ')');
					else if ( ct == 'text/javascript' )
						eval (t);

					if ( typeof aParams.onComplete == 'function' )
						aParams.onComplete (t);
				}
			};
			x.setRequestHeader ('Content-Type', 'application/x-www-form-urlencoded');
			x.setRequestHeader( 'X-Requested-With', 'KC-Ajax');
			if ( typeof aParams.parameters == 'object' )
			{
				aParams.parameters = KC.SerializeJSON (aParams.parameters);
			}
			x.send (aParams.parameters);
		}
	}
};

// EVENTS
KC.Event = {
	observe: function (eEl, sEvent, funcRun) {
		if (eEl.addEventListener)
			eEl.addEventListener (sEvent, funcRun, false);
		else
			eEl.attachEvent ('on' + sEvent, funcRun);
	},
	onReady: function (funcRun) {
		this.observe (window, 'load', funcRun);
	},
	NumbersOnly: function (eEvent) {
		eEvent = (eEvent) ? eEvent : ((window.event) ? event : null);
	    if ( eEvent ) {
	       var eEl = (eEvent.target) ? eEvent.target : ((eEvent.srcElement) ? eEvent.srcElement : null);

	       if (eEl)
	       {
	           var iCharCode = (eEvent.charCode) ? eEvent.charCode :
	               ((eEvent.which) ? eEvent.which : eEvent.keyCode);

	           if ((iCharCode < 32 ) ||
	               (iCharCode > 44 && iCharCode < 47) ||
	               (iCharCode == 37 || iCharCode == 39) ||
	               (iCharCode > 47 && iCharCode < 58)) {
	               return true;
	           } else
	               return false;
	       }
	    }
	},
	pointerX: function (evt) {
		if (evt.pageX)
			return evt.pageX;
		else if (evt.clientX)
			return evt.clientX + (document.documentElement.scrollLeft ?
					document.documentElement.scrollLeft :
					document.body.scrollLeft);
		else
			return null;
	},
	pointerY: function (evt) {
		if (evt.pageY)
			return evt.pageY;
		else if (evt.clientY)
			return evt.clientY + (document.documentElement.scrollTop ?
					document.documentElement.scrollTop :
					document.body.scrollTop);
		else
			return null;
	}
};

// FUNCTION BINDING
if ( typeof Function.prototype.bind == 'undefined' )
{
	Function.prototype.bind = function (x) {
		var __method = this;
		return function () {
			return __method.apply (x);
		};
	};
}

// PERIODICALEXECUTER
KC.PeriodicalExecuter = function (callback, frequency) {
	this.callback = callback;
	this.frequency = frequency;
	this.currentlyExecuting = false;

	this.registerCallback ();
};
KC.PeriodicalExecuter.prototype.registerCallback = function () {
	this.timer = setInterval (this.onTimerEvent.bind (this), this.frequency * 1000);
};

KC.PeriodicalExecuter.prototype.execute = function () {
	this.callback(this);
};

KC.PeriodicalExecuter.prototype.stop = function () {
	if ( ! this.timer)
		return;
	clearInterval (this.timer);
	this.timer = null;
};

KC.PeriodicalExecuter.prototype.onTimerEvent = function () {
	if ( ! this.currentlyExecuting) {
		try {
			this.currentlyExecuting = true;
			this.execute ();
		} finally {
			this.currentlyExecuting = false;
		}
	}
};

// JSON
KC.SerializeJSON = function (oObj) {
	var sStr = '';

	for (var sKey in oObj)
	{
		var eProp = oObj[sKey];

		if ( typeof eProp != 'function' )
		{
			if (sStr.length > 0)
				sStr += '&';

			var sValue = String (oObj[sKey]);
			sStr += sKey + '=' + escape (sValue);
		}
	}

	return sStr;
};

// INVENTORY
KC.Inv = {
	PopulateModels: function (oVehs, sMake, sModels) {
		var e = KC.$(sModels);

		e.options.length = 0;
		e.options[e.options.length] = new Option ('Any Model', '');

		for (i in oVehs.Makes)
		{
			if ( oVehs.Makes[i].Name == KC.$F(sMake) )
			{
				for (j in oVehs.Makes[i].Models)
				{
					v = oVehs.Makes[i].Models[j];
					if ( typeof v == 'object' )
						e.options[e.options.length] = new Option (v.Name + ' (' + v.Count + ')', v.Name);
				}
			}
		}
	},
	SetCompare: function (sUrl, iVehicle, eEl) {
		KC.Ajax.Request (sUrl, {
			parameters: {
				Action: 'compare',
				Vehicle: iVehicle,
				Status: eEl.checked
			},
			onComplete: function (t) {
				if (t.Status == false)
				{
					alert (t.Message);
					eEl.checked = false;
				}
			}
		});
	},
	ShowCapDesc: function () {
		KC.$('KC_cap_why').hide ();
		KC.$('KC_cap_desc').show ();
	}
};

// POPUP
KC.Popup = function (sUrl, iWidth, iHeight) {
	var p;

	if ( iWidth == undefined )
		iWidth = 600;
	if ( iHeight == undefined )
		iHeight = 500;

	var iCenterWidth = (window.screen.width - iWidth) / 2;
    var iCenterHeight = (window.screen.height - iHeight) / 2;

	try {
		p = window.open (sUrl, null, 'status=0,toolbar=0,width=' + iWidth + ',height=' + iHeight + ',scrollbars=1,top=' + iCenterWidth + ',left=' + iCenterHeight);
		p.focus ();
	}
	catch (e) {
		alert ('Your popup blocker prevented the window from opening. Please disable your popup blocker.');
	}

	return false;
};
KC.PopupLink = function (eEl, iWidth, iHeight) {
	return KC.Popup (eEl.href, iWidth, iHeight);
};

KC.RolloverSetup = function () {
	KC.$A(KC.$$('KC_rollover')).each (function (e) {
		var sOvr = e.getAttribute ('longdesc');
		if ( ! sOvr)
			return;
		e.oversrc_img = new Image ();
		e.oversrc_img.src = sOvr;
		KC.Event.observe (e, 'mouseover', function () {
			e.src = e.getAttribute ('longdesc');
		});
		KC.Event.observe (e, 'mouseout', function () {
			e.src = e.getAttribute ('origsrc');
		});
		e.setAttribute ('origsrc', e.src);
	});
};
KC.Event.onReady (KC.RolloverSetup);


// VEHICLES
KC.Veh = {
	ChangePhoto: function (iPhoto) {
		KC.$('KC_photo_' + KC_photo + '_wrap').hide ();
		KC_photo = iPhoto;
		KC.$('KC_photo_' + iPhoto + '_wrap').show ();
	},
	StartPhotoRotator: function (iDelay) {
		var i = 0;
		var oRotate;

		if ( KC_photos_array.length > 0 )
		{
			if ( j = KC.$A(KC_photos_array).find (KC_photo) )
				i = j;

			oRotate = new KC.PeriodicalExecuter (function () {
				var iPhoto = KC_photos_array[i];

				this.ChangePhoto (iPhoto);

				i++;

				if ( i >=  KC_photos_array.length )
					i = 0;
			}.bind (this), iDelay);
		}

		return oRotate;
	},
	PaymentCalc: function (fHidden, fTaxes, fPrincipal, fCashDown, fInterest, iTerm, sFreq, fRebate) {
		if ( isNaN (fHidden) )
			fHidden = 0;
		if ( isNaN (fTaxes) )
			fTaxes = 0;
		if ( isNaN (fPrincipal) )
			fPrincipal = 0;
		if ( isNaN (fCashDown) )
			fCashDown = 0;
		if ( isNaN (fInterest) )
			fInterest = 0;
		if ( isNaN (iTerm) )
			iTerm = 0;
		if ( isNaN (fRebate) )
			fRebate = 0;

		fPrincipal = ((fPrincipal - fCashDown - fRebate) + fHidden) * (1 + (fTaxes / 100));

		fInterest /= 100;

		if ( sFreq == 'b' )
		{
			iTerm = (iTerm / 12) * 26;
			fInterest /= 26;
		}
		else
		{
			fInterest /= 12;
		}

		if (fInterest == 0)
			return Math.round (fPrincipal / iTerm);

		var fPow = 1;

		for (var j = 0; j < iTerm; j++)
		{
			fPow *= 1 + fInterest;
		}

		var fAmount = Math.round (0.01 * Math.round (100 * (fPrincipal * fPow * fInterest) / (fPow - 1)));

		if ( fAmount < 0 )
			return 0;

		return fAmount;
	},
	OpenHistoryReport: function (sUrl) {
		return KC.Popup (sUrl, 840, 650);
	}
};

// VALIDATION
KC.Validation = {
	_aFields: [],

	Require: 1,
	Acceptance: 2,
	Email: 3,
	Numeric: 4,

	Register: function (iType, mEl, sErrorMsg) {
		this._aFields.push ( [ iType, mEl, sErrorMsg] );
	},
	Unregister: function (iType, sEl) {
		for (var i = 0; i < this._aFields.length; i++)
		{
			var aF = this._aFields[i];
			if ( aF[0] == iType && aF[1] == sEl )
			{
				this._aFields.splice (i);
				break;
			}
		}
	},
	Check: function () {
		var bValid = true;
		for (var i = 0; i < this._aFields.length; i++)
		{
			var a = this._aFields[i];
			var v = KC.$F(a[1]);
			var e = KC.$(a[1]);

			if ( a[0] == this.Require ) // REQUIRED
			{
				if ( v.replace (/^\s+|\s+$/g, '') == '' ) bValid = false;
			}
			else if ( a[0] == this.Email ) // EMAIL
			{
				if ( ! v.match (/.+\@.+\..+/i) && v != '' ) bValid = false;
			}
			else if ( a[0] == this.Acceptance ) // ACCEPTANCE
			{
				if ( v == false ) bValid = false;
			}
			else if ( a[0] == this.Numeric ) // NUMERIC
			{
				if ( ! v.match (/^[0-9\.]+$/) && v != '' ) bValid = false;
			}

			if ( bValid == false )
			{
				alert (a[2]);
				e.focus ();
				if ( e.getAttribute ('type') == 'text' || e.getAttribute ('type') == 'password' )
					e.select ();
				break;
			}
		}

		return bValid;
	}
};

KC.Effects = {
	GrowTextarea: function (sEl) {
		KC.$(sEl).observe ('keyup', function () {
			var maxHeight = document.documentElement.clientHeight;
			var adjustedHeight = this.clientHeight;

			if ( ! maxHeight || maxHeight > adjustedHeight )
			{
				adjustedHeight = Math.max (this.scrollHeight, adjustedHeight);
				if ( maxHeight )
					adjustedHeight = Math.min (maxHeight, adjustedHeight);
				if ( adjustedHeight > this.clientHeight )
					this.style.height = adjustedHeight + "px";
			}
		});
	},

	SlideToggle: function (sEl)
	{
		var contentElement = KC.$(sEl);
		if (contentElement.style.display == 'none')
		{
			this.SlideDown (contentElement);
		}
		else if (contentElement.style.display == 'block'
			|| !contentElement.style.display)
		{
			this.SlideUp (contentElement);
		}
	},

	SlideUp: function (sEl) {
		this._SlideElement (KC.$(sEl).id, false);
	},

	SlideDown: function (sEl) {
		this._SlideElement (KC.$(sEl).id, true);
	},

	_SlideElement: function (elementId, show) {

		var slideSpeed = 10;
		var slideTimer = 10;

		var content = KC.$(elementId);
		var content_inner = KC.$(elementId + "_inner");
		var height = content.clientHeight;
		if (height == 0)
		{
			height = content.offsetHeight;
			content.style.display = 'block';
		}
		height = height + (show ? slideSpeed : -slideSpeed);

		var rerun = true;
		if (height >= content_inner.offsetHeight)
		{
			height = content_inner.offsetHeight;
			rerun = false;
		}
		else if (height <= 1)
		{
			height = 1;
			rerun = false;
		}

		content.style.height = height + 'px';
		var topPos = height - content_inner.offsetHeight;
		if (topPos > 0)
		{
			topPos = 0;
		}
		content_inner.style.top = topPos + 'px';

		if (rerun)
		{
			setTimeout("KC.Effects._SlideElement('"
				+ elementId + "', " + show + ");",
				slideTimer);
		}
		else
		{
			if (height <= 1)
			{
				content.style.display = 'none';
			}
		}
	}
};
