/*
 * ZCPP for GMDS
 * Version: 2.1.4.2
 * Package: mrm.cmp.zc
 * Requires: jQuery 1.4.1+, GMDS/Mootools Cookie support , mrm.util package
 * Author(s): Andrew Zammit (DET-MRM), David Gramlich (DET-MRM)
 * Notes: no cross-domain (JSONP) support, UTF-8
 */

(function($){
	mrm.cmp = mrm.cmp || {};
	$.extend(mrm.cmp,{
		zc: {
			/* country code profiles */
			cc:{
				enus:{
					lang:'en-US',
					msg:{
						close:'Close',
						submit:'Go',
						title:'Please enter your ZIP code',
						titlestate:'Please select your state',
						par:'In order to provide you with the best vehicle price and relevant results we will need to know your location.',
						input:'Enter Zip',
						stateLoad:'' // Loading...
					},
					rules:{
						regex:/^[0-9]{5}$/,
						restrict:['00000'],
						sliceEnd:5,
						maxlength:5
					},
					config:{
						dataType:'json',
						urlSchema:'/zipdata/##LANG##/##LOC_REQUEST##.json',
						urlState:'/zipdata/##LANG##/region_state.json',
						handler:'enusvalidate',
						locFetch:'enusloc',
						regFetch:'enusreg'
					},
					errors:{
						locNull:'No location specified.',
						locRegexInvalid:'Please enter a valid zip code.',
						locRestrictInvalid:'Please enter a valid zip code.',
						locAjaxInvalid:'Please enter a valid zip code.',
						locAjaxError:'There was an error processing your request.',
						noAjaxHandler:'There was an error processing your request.'
					},
					auxLinks:[
						{
							name:'lad-advanced',
							match:[/\/tools\/dealerlocator\/.*/,/locatedealer\(/],
							url:'/tools/dealerlocator/search.do',
							title:'Advanced Search'
						}
					]
				},
				ptbr:{
					lang:'pt-BR',
					msg:{
						close:'Fechar',
						submit:'Continuar',
						title:'Insira seu CEP',
						titlestate:'Selecione seu estado',
						par:'Para apresentar um preço adequado e resultados relevantes precisamos saber a sua localização.',
						input:'Insira um CEP',
						stateLoad:'' // Carregando...
					},
					rules:{
						regex:/^[0-9]{5}(\-?[0-9]{3})?$/,
						restrict:['00000'],
						sliceEnd:5,
						maxlength:9
					},
					config:{
						dataType:'json',
						urlSchema:'/zipdata/##LANG##/##LOC_REQUEST##.json',
						urlState:'/zipdata/##LANG##/region_state.json',
						handler:'ptbrvalidate',
						locFetch:'ptbrloc',
						regFetch:'ptbrreg'
					},
					errors:{
						locNull:'Nenhuma localização especificada.',
						locRegexInvalid:'Insira um CEP válido.',
						locRestrictInvalid:'Insira um CEP válido.',
						locAjaxInvalid:'Insira um CEP válido.',
						locAjaxError:'Um erro foi encontrado.',
						noAjaxHandler:'Um erro foi encontrado.'
					},
					auxLinks:[]
				}
			},
			/* custom config */
			config:{
				MASK_ID:'zc-winmask',
				APPEND_SELECTOR:'body',
				FX_FADE_TIME:500,
				FX_MASK_OPACITY:0.25,
				COOKIE_NAME:'cookie_customer_location',
				COOKIE_VALIDITY:2592000000, // 1000*60*60*24*30
				COOKIE_EXPIRES:1,
				COOKIE_PATH:'/',
				BASE_CONTEXT:''
			},
			/* internal global inits */
			lang:{},
			cookie:{},
			uxStore:{loc:null,action:null,isUrl:true,type:null,region:null,container:null},
			activeForm:null,
			isInit:false,
			/* internal init */
			init:function(c) {
				if ( !this.isInit ) {
					this.enableLocalization();
					if ( typeof gmds == 'object' ) {
						this.cookie.set = (function(c){return function(value){gmds.setCookie(c.config.COOKIE_NAME,value,c.config.COOKIE_VALIDITY,c.config.COOKIE_PATH);};}(this));
						this.cookie.get = (function(c){return function(){return gmds.getCookie(c.config.COOKIE_NAME);};}(this));
						this.cookie.del = (function(c){return function(){gmds.deleteCookie(c.config.COOKIE_NAME);};}(this));
					} else if ( typeof Cookie == 'function' ) {
						this.cookie.set = (function(c){return function(value){Cookie.write(c.config.COOKIE_NAME,value,{duration:c.config.COOKIE_EXPIRES,path:c.config.COOKIE_PATH});};}(this));
						this.cookie.get = (function(c){return function(){return Cookie.read(c.config.COOKIE_NAME);};}(this));
						this.cookie.del = (function(c){return function(){Cookie.dispose(c.config.COOKIE_NAME);};}(this));
					}
				}
				this.isInit = true;
			},
			/* core methods (incl lang/county specific) */
			validate:function(loc, action, isUrl, type) {
				if ( !this.ca(loc) )
					throw new this.exception('loc is undefined or null',this.lang.errors.locNull,this);
				if ( !this.ca(action) ) action = this.uxStore.action;
				if ( !this.ca(isUrl) ) isUrl = this.uxStore.isUrl;
				if ( !this.ca(type) ) type = this.uxStore.type;
				if ( typeof this[this.lang.config.handler] != 'function' )
					throw new this.exception('ajax handler required for active check',this.lang.errors.noAjaxHandler,this);
				if ( loc == this.lang.msg.input )
					throw new this.exception('loc is undefined or null',this.lang.errors.locNull,this);
				loc = $.trim(loc);
				if ( loc.length > this.lang.rules.sliceEnd )
					loc = loc.slice(0,this.lang.rules.sliceEnd);
				var matches = String(loc).match(this.lang.rules.regex);
				if ( matches == null )
					throw new this.exception('loc passive check returned invalid',this.lang.errors.locRegexInvalid,this);
				if ( matches.length < 1 )
					throw new this.exception('loc passive check returned invalid',this.lang.errors.locRegexInvalid,this);
				if ( $.inArray(loc,this.lang.rules.restrict) >= 0 )
					throw new this.exception('loc passive check returned restricted',this.lang.errors.locRestrictInvalid,this);
				var url = this.lang.config.urlSchema;
				var arr = [
							{key:'##LOC_REQUEST##',val:loc},
							{key:'##LANG##',val:this.lang.lang.toLowerCase()}
						];
				for ( var i = 0; i<arr.length; i++) url = url.replace(arr[i].key,arr[i].val);
				this.uxStore = {loc:loc,action:action,isUrl:isUrl,type:type};
				try {
					var xhr = $.ajax({
						url:url,
						dataType:this.lang.config.dataType,
						context:this,
						async:false,
						success:this[this.lang.config.handler]
					});
					try {
						this.checkForError(xhr.statusText);
					} catch (e) {
						throw e;
					}
				} catch (e) {
					throw e;
				}
			},
			getLocation:function(){
				this.init();
				return $.parseJSON(this.cookie.get());
			},
			loadLocalization:function(ccLoad, force){
				force = this.ca(force,true);
				for ( var i in ccLoad ) {
					if ( ccLoad[i].lang ) {
						for ( var j in this.cc ) {
							if ( this.cc[j].lang == ccLoad[i].lang ) return false;
						}
						$.extend(this.cc,ccLoad);
						if ( force ) this.enableLocalization(ccLoad[i].lang);
						return true;
					}
				}
				return false;
			},
			enableLocalization:function(override){
				var htmlLang = $('html').attr('lang');
				if ( !this.ca(override) ) override = htmlLang;
				else htmlLang = override;
				if ( typeof htmlLang != undefined ) {
					for ( var i in this.cc ) {
						if ( this.cc[i].lang == htmlLang ) this.lang = this.cc[i]; 
					}
				}
				if ( typeof this.lang.lang == 'undefined' || this.lang.lang == null ) this.lang = this.cc.enus;
			},
			initStates:function(container, action, isUrl, type) {
				if ( this.ca(container) ) this.uxStore.container = container;
				if ( this.ca(action) ) this.uxStore.action = action;
				if ( this.ca(isUrl) ) this.uxStore.isUrl = isUrl;
				if ( this.ca(type) ) this.uxStore.type = type;
				var url = this.lang.config.urlState;
				var arr = [
					{key:'##LANG##',val:this.lang.lang.toLowerCase()}
				];
				for ( var i = 0; i<arr.length; i++) url = url.replace(arr[i].key,arr[i].val);
				try {
					var xhr = $.ajax({
						url:url,
						dataType:this.lang.config.dataType,
						context:this,
						async:false,
						success:this.drawStates
					});
					try {
						this.checkForError(xhr.statusText);
					} catch (e) {
						throw e;
					}
				} catch (e) {
					throw e;
				}
			},
			isStateMode:function(type){
				if ( !this.ca(type,true) ) type = this.uxStore.type;
				return type?(type.indexOf('-state')>=0):false;
			},
			/* lang code specific funcs w/ customization code */
			enusvalidate:function(data, textStatus, jqXHR) {
				if ( data.zipcode === this.uxStore.loc ) {
					this.cookie.del();
					this.cookie.set($.trim(jqXHR.responseText));
					if ( this.uxStore.isUrl ) {
						var url = new this.urlp(this.uxStore.action),
							cqs = url.getQuerystring();
						cqs = cqs==''?'':'&'+cqs;
						if ( $.inArray(this.uxStore.type,['btl','byo16','dlc']) >= 0 ) {
							url.setQuerystring('x-zipcode='+this.uxStore.loc+cqs);
						} else if ( $.inArray(this.uxStore.type,['dl']) >= 0 ) {
							url.setQuerystring('searchType=ByPostalCode&searchByPostalCodePostalCode='+this.uxStore.loc+cqs);
						} else if ( $.inArray(this.uxStore.type,['co']) >= 0 ) {
							url.setQuerystring('zipCode='+this.uxStore.loc+cqs);
						}
						this.uxStore.action = url.getURL();
					}
					this.executeAction();
				}
				this.uxStore = {loc:null,action:null,isUrl:true,type:null,region:null,container:null};
			},
			enusloc:function(){
				var loc = this.getLocation();
				if ( loc ) return loc.zipcode;
				return null;
			},
			enusreg:function(){
				var region = this.getLocation();
				if ( region ) return region.region;
				return null;
			},
			ptbrvalidate:function(data, textStatus, jqXHR) {
				var context = this.activeForm || $('body');
				var state = context.find('.zc-select option:selected').val();
				if ( this.ca(state) ) {
					state = decodeURIComponent(state);
					var sdata = $.parseJSON(state);
					if ( this.ca(sdata) ) { 
						this.cookie.set(state);
						this.uxStore.region	= sdata.region;
					}
				} else if ( this.ca(data) && data.zipcode === this.uxStore.loc ) {
					this.cookie.del();
					this.cookie.set($.trim(jqXHR.responseText));
				}
				var json = $.parseJSON(this.cookie.get());
				if ( json ) {
					this.uxStore.state = json.state; 
					this.uxStore.region = json.region; 
					if ( this.uxStore.isUrl ) {
						var url = new this.urlp(this.uxStore.action),
							cqs = url.getQuerystring(),
							reg = this.uxStore.region?'x-regionid='+this.uxStore.region:'',
							sta = this.uxStore.state?'x-state='+this.uxStore.state:'',
							zip = this.uxStore.loc?'x-zipcode='+this.uxStore.loc:'';
						cqs = cqs==''?'':'&'+cqs;
						if ( $.inArray(this.uxStore.type,['btl','byo16','dlc']) >= 0 && zip.length ) {
							url.setQuerystring(zip + (reg.length>0?'&'+reg:'') + cqs);
						} else if ( $.inArray(this.uxStore.type,['byo16-state']) >= 0 && reg.length ) {
							url.setQuerystring((zip.length>0?zip+'&':'') + (sta.length>0?sta+'&':'') + reg + cqs);
						}
						this.uxStore.action = url.getURL();
					}
					this.executeAction();
				}
				this.uxStore = {loc:null,action:null,isUrl:true,type:null,region:null,container:null};
			},
			ptbrloc:function(){
				var loc = this.getLocation();
				if ( loc ) return loc.zipcode;
				return null;
			},
			ptbrreg:function(){
				var loc = this.getLocation();
				if ( loc ) return loc.region;
				return null;
			},
			/* ui methods */
			open:function(action, isUrl, type, loc, force, region) {
				this.init();
				if ( !this.ca(action) ) {
					action = 'window.reload(true)';
					isUrl = false;
				}
				if ( !this.ca(isUrl) ) isUrl = true;
				loc = this.ca(loc)?String(loc):this[this.lang.config.locFetch]();
				region = this.ca(region)?String(region):this[this.lang.config.regFetch]();
				force = this.ca(force,true);
				this.uxStore = {action:action,isUrl:isUrl,type:type,loc:loc,region:region};
				var storedLoc = this.getLocation();
				if ( !force && this.isStateMode() && this.ca(region) ) this[this.lang.config.handler]();
				else if ( !force && storedLoc && loc ) this.validate(loc);
				else this.createLayer();
			},
			createLayer:function() {
				if ( !$('#'+this.config.MASK_ID).length ) {
					var s = '#'+this.config.MASK_ID+' > form',
						inputMsg = this.uxStore.loc?this.uxStore.loc:this.lang.msg.input,
						langClass = this.lang.lang.replace(/[^a-zA-Z0-9]/ig,'').toLowerCase();
					var isState = this.isStateMode();
					$(this.config.APPEND_SELECTOR).append('<div id="'+this.config.MASK_ID+'" class="'+langClass+'"><form/><div class="zc-mask"/></div>');
					$('<p/>').addClass('zc-close').append('<a href="#">'+this.lang.msg.close+'</a>').click({namespace:this},function(e){
						var ns = e.data.namespace;
						e.preventDefault();
						ns.removeLayer();
						return false;
					}).appendTo(s);
					$('<p/>').addClass('zc-title').appendTo(s).text(this.lang.msg[(isState?'titlestate':'title')]);
					$('<p/>').addClass('zc-par').appendTo(s).text(this.lang.msg.par);
					if ( isState ) $('<p/>').addClass('zc-selectpar').appendTo(s)
							.append('<p class="zc-load">' + this.lang.msg.stateLoad + '</p>');
					else $('<p/>').addClass('zc-inputpar').appendTo(s)
							.append('<input type="text" name="zc-input" class="zc-input" maxlength="'+this.lang.rules.maxlength+'" value="'+inputMsg+'"/>');
					$('.zc-par').next().append('<input type="submit" value="'+this.lang.msg.submit+'" class="zc-go"/>');
					$('<p/>').addClass('zc-error').appendTo(s);
					if ( this.lang.auxLinks && this.uxStore.action ) {
						for ( var i = 0; i<this.lang.auxLinks.length; i++ ) {
							var hasMatch = false;
							for ( var j = 0; j<this.lang.auxLinks[i].match.length; j++ ) {
								if ( String(this.uxStore.action).match(this.lang.auxLinks[i].match[j]) ) {
									hasMatch = true;
									break;
								}
							}
							if ( hasMatch ) $('<p/>').addClass('zc-link').appendTo(s)
									.html('<a href="'+this.lang.auxLinks[i].url+'" class="'+this.lang.auxLinks[i].name+'">'+this.lang.auxLinks[i].title+'</a>');
						}
					}
					$('<div><div /></div>').addClass('zc-loading').appendTo(s).hide();
					if ( isState ) {
						$('.zc-go').hide();
						try {
							this.initStates();
						} catch (e) {
							this.updateErrorUI(e.messageUI);
						}
					}
					if ( $.browser.msie ) $('#'+this.config.MASK_ID).hide().addClass('zc-wrapper')
							.children('.zc-mask').fadeTo(this.config.FX_FADE_TIME,this.config.FX_MASK_OPACITY)
							.parent().show();
					else $('#'+this.config.MASK_ID).hide().addClass('zc-wrapper')
							.children('.zc-mask').fadeTo(this.config.FX_FADE_TIME,this.config.FX_MASK_OPACITY)
							.parent().children('form').fadeTo(this.config.FX_FADE_TIME,1)
							.parent().show();
					mrm.util.clearInput(s+' .zc-input',this.lang.msg.input);
					$(s).submit({namespace:this},function(e){
						var ns = e.data.namespace;
						e.preventDefault();
						ns.disableLayer();
						ns.activeForm = $(e.target);
						$('.zc-error').fadeOut();
						ns.submit($('.zc-input').val());
						return false;
					});
				} 
			},
			drawStates:function(data, textStatus, jqXHR) {
				var $s, container = this.uxStore.container, loc = this.getLocation(), curState = null;
				if ( this.ca(loc) && this.ca(loc.state) ) curState = loc.state;
				if ( this.ca(container) ) {
					$s = $(container).html('<form />');
					$s.children('form').addClass(this.lang.lang.replace(/[^a-zA-Z0-9]/ig,'').toLowerCase())
						.append('<select class="zc-select" />').append('<input type="submit" value="'+this.lang.msg.submit+'" class="zc-go"/>')
						.submit({namespace:this}, function(e) {
							var ns = e.data.namespace;
							e.preventDefault();
							ns.activeForm = $(e.target);
							try { ns[ns.lang.config.handler](); }
							catch (e) { ns.updateErrorUI(e.messageUI); }
						});
				} else {
					$('.zc-load').remove();
					$('.zc-go').show();
					$s = $('.zc-selectpar').prepend('<select class="zc-select"/>');
				}
				for ( var i = 0; i < data.length; i++ ) {
					if ( data[i].region && data[i].state && data[i].statelong )
						$s.find('.zc-select').append('<option value="'
								+encodeURIComponent('{'+'"region":"'+data[i].region+'","state":"'+data[i].state+'","statelong":"'+data[i].statelong+'"}')
								+'"'+(curState==data[i].state?' selected="selected"':'')+'>'
								+data[i].statelong+' ('+data[i].state+')'+'</option>');
				}
			},
			removeLayer:function() {
				$('#'+this.config.MASK_ID).fadeOut(this.config.FX_FADE_TIME,function(){$(this).detach();});
			},
			enableLayer:function() {
				$('#'+this.config.MASK_ID+' input').removeAttr('disabled');
				$('#'+this.config.MASK_ID+' .zc-loading').fadeOut(this.config.FX_FADE_TIME,0);
			},
			disableLayer:function() {
				$('#'+this.config.MASK_ID+' input').attr('disabled','disabled');
				$('#'+this.config.MASK_ID+' .zc-loading').fadeTo(this.config.FX_FADE_TIME,this.config.FX_MASK_OPACITY);
			},
			uiValidate:function(selector, type, loc, action, isUrl, doFx) {
				this.init();
				if ( !this.ca(action) ) {
					action = 'null';
					isUrl = false;
				}
				if ( !this.ca(doFx) ) doFx = true;
				isUrl	= this.ca(isUrl,true);
				loc		= this.ca(loc)?String(loc):this[this.lang.config.locFetch]();
				this.uxStore = {action:action,isUrl:isUrl,type:type,loc:loc};
				try {
					this.validate(loc);
					if ( doFx ) $(selector).hide();
					return true;
				} catch (e) {
					this.updateErrorUI(e.messageUI, selector, doFx);
					return false;
				}
			},
			submit:function(loc) {
				if ( this.isStateMode() ) {
					this.log('submit state validation');
					try {this[this.lang.config.handler]();}	
						catch (e) {this.updateErrorUI(e.messageUI);}
				} else {
					this.log('submit zip validation');
					try {this.validate(loc);}
						catch (e) {this.updateErrorUI(e.messageUI);}
				}
			},
			updateErrorUI:function(msg, selector, doFx) {
				if ( !this.ca(selector) ) selector = '#'+this.config.MASK_ID+' .zc-error';
				if ( !this.ca(doFx) ) doFx = true;
				this.enableLayer();
				var j = $(selector);
				if ( j.length ) {
					if ( doFx ) j.hide().fadeIn(this.config.FX_FADE_TIME).html(msg);
					else j.html(msg);
				} else {
					this.log('no zc-error object to dump friendly msg for UI');
				}
			},
			/* util support methods */
			executeAction:function(){
				if ( !this.uxStore ) window.reload(true);
				else if ( !this.uxStore.action ) window.reload(true);
				else if ( !this.uxStore.isUrl && typeof this.uxStore.action == 'string' ) eval(this.uxStore.action);
				else if ( !this.uxStore.isUrl && typeof this.uxStore.action != 'string' ) this.uxStore.action();
				else window.location = this.uxStore.action;
			},
			checkForError:function(textStatus) {
				if ( $.inArray(textStatus,['error','parsererror','Not Found']) >= 0 )
					throw new this.exception('loc active check returned invalid',this.lang.errors.locAjaxInvalid,this);
				else if ( $.inArray(textStatus,['timeout','abort']) >= 0 )
					throw new this.exception('loc active check returned abnormal',this.lang.errors.locAjaxError,this);
			},
			exception:function(msg, ui, c) { // usage: throw new this.exception(...)
				if ( typeof c == 'undefined' ) c = this;
				if ( typeof ui == 'undefined' || ui == null ) ui = msg;
				this.name		= 'cmp.zc';
				this.message	= msg;
				this.messageUI	= String(ui);
				if ( c && c.log ) c.log(this.message, true);
			},
			log:function(msg, thrown) {
				if ( typeof thrown == 'undefined' ) thrown = false;
				mrm.util.log('[cmp.zc log'+(thrown?': error thrown':'')+']',msg);
			},
			ca:function(o,useBoolean){ // check arg/param/var
				if ( typeof useBoolean == 'undefined' || useBoolean == null ) useBoolean = false;
				if ( typeof o == 'undefined' ) return false;
				if ( o == null ) return false;
				if ( useBoolean ) return o?true:false;
				return true;
			},
			/**
			 * @projectDescription	Poly9's polyvalent URLParser class
			 * Modified to URL reconstruction by Mikko Ohtamaa.
			 * @authorDenis	Laprise <denis@poly9.com>, Mikko Ohtamaa <mikko.ohtamaa@twinapex.com>
			 * @version	0.2
			 * @namespace	zc
			 * URLParser is freely distributable under the terms of an MIT-style license.
			 * The orignal code: https://code.poly9.com/trac/browser/urlparser/urlparser.js
			 * http://poly9.com
			 * http://www.twinapex.com
			 */
			urlp:(function(){var URLParser=function(url){this._fields={'Username':4,'Password':5,'Port':8,'Protocol':2,'Host':6,'Pathname':9,'URL':0,'Querystring':10,'Fragment':11};this._values={};this._regex=null;this.version=0.2;this._regex=/^((\w+):\/\/)?((\w+):?(\w+)?@)?(([^\/\?:]+):?)?(\d+)?(\/?[^\?#]+)?\??([^#]+)?#?([^#]*)/;for(var f in this._fields){this['get'+f]=this._makeGetter(f);this['set'+f]=this._makeSetter(f);}
			this.getURL=this._getURL;if(typeof url!='undefined')this._parse(url);}
			URLParser.prototype.setURL=function(url){this._parse(url);}
			URLParser.prototype._getURL=function(){var s="";if(this.getProtocol()!=''){s+=this.getProtocol()+"://"}
			if(this.getUsername()!=''){s+=this.getUsername();}
			if(this.getPassword()!=''){s+=":";s+=this.getPassword();}
			if(this.getUsername()!=''){s+="@";}
			s+=this.getHost();if(this.getPort()!=''){s+=":"+this.getPort();}
			s+=this.getPathname();if(this.getQuerystring()!=''){s+="?"+this.getQuerystring();}
			if(this.getFragment()!=''){s+="#"+this.getFragment();}
			return s;}
			URLParser.prototype._initValues=function(){for(var f in this._fields)
			this._values[f]='';}
			URLParser.prototype._parse=function(url){this._initValues();var r=this._regex.exec(url);if(!r)throw"DPURLParser::_parse -> Invalid URL"
			for(var f in this._fields)if(typeof r[this._fields[f]]!='undefined')this._values[f]=r[this._fields[f]];}
			URLParser.prototype._makeGetter=function(field){return function(){return this._values[field];}}
			URLParser.prototype._makeSetter=function(field){return function(value){this._values[field]=value;}}
			return URLParser;}())
		}
	});
}(mrm.$));

// backwards compatibility support
function validateCookie(src, response, type, isURL, zip, force) {
	mrm.cmp.zc.open(response, isURL, type, zip, force);
	return false;
}

