/*!
 * jQuery eControl plugin v0.9
 * Copyright (c) 2011 ...
 * licensed under ...
 */
 
(function($){

	/*
		----------------- hash-tag format
		
		http://www.mylink.com/myfile.ext?myquerystring#well1=state1&well2=state2-slidenumber*mypage
		
		----------------- wells and states
		
		<div class="well" id="mywell state_defaultstate" title="state1,state2"></div>
		symbols "-", "&", "|", "!" are not allowed in well and state names
		
		---------------- state triggers
		
		<a href="#" class="state_strigger" id="myid|well1=state1&well2=state2&...-1*mynewpage">Text</a>
		
		
		
		
	*/
	
	// Some JQuery settings
	$.ajaxSetup ({
		// Disable caching of AJAX responses
		cache: false
	});
	
	// URL object
	function myurl() 
	{	
		
		this.url='';
		this.base='';
		this.hash='';
		this.slide='';
		this.states='';
		this.page='',
		
		// change well/state pair in hash part "well1=state1&well2=state2"
		this.changestate = function(mywell,mystate) {
			var reg=new RegExp(mywell+'\=[^&\-\*]*','ig');				
			if (this.states.search(reg)!=-1) {					
				this.states=this.states.replace(reg,mywell+'='+mystate);				
			} else	{
				this.states+=(this.states=='' ? '' : '&')+mywell+'='+mystate;				
			}
		}
		
		// display URL and it parts		
		this.show = function (a) {
			if (a) {alert(this.base + "\r\n" + this.hash +"\r\n"+this.states+"\r\n"+this.slide +"\r\n"+this.page);}
			else {return this.base + "\r\n" + this.hash +"\r\n"+this.states+"\r\n"+this.slide +"\r\n"+this.page;}
		}
		
		
		// extract parts of URL
		this.parse=function (s) {
			// 
			this.hash='';
			this.states='';
			this.slide='';
			this.page='';
			//
			this.url=s;
			var arr=s.split('#');
			if (arr.length==1) {arr=s.split('|');} // trigger situation
			this.base=arr[0];
			if (arr.length==1) {return false;}
			
			// hash 			
			this.hash=arr[1];
			
			// page first.
			arr=this.hash.split('*');
			s=arr[0];
			if (arr.length==2) {this.page=arr[1];}
					
			arr=s.split('-');			
			this.states=s;
			if (arr.length==1) {return false;}			
			this.states=arr[0];
			
			this.slide=arr[1];
		};
			
		// Replace "well1=newstate1&well2=newstate2-newslide*newpage" from surl param in current url object
		this.statesreplace = function(surl) {
			var arr,mywell,mystate;
			
			// update states
			if (surl.states!='')	{
				
				arr=surl.states.split('&');			
				for (var i=0;i<arr.length;i++) {
					arrw=arr[i].split('=');
					if (arrw.length!=2) {$.fn.econtrol.myerror('','Invalid well=state format in trigger ID '+surl.url);return false;}
					mywell=arrw[0];
					mystate=arrw[1];			
					this.changestate(mywell,mystate);							
				}
			}
			// update slide and page
			if (surl.slide!='') {this.slide=surl.slide;}
			if (surl.page!='') {this.page=surl.page;}
			this.buildurl();
			
		}
		
		// build URL form object params
		this.buildurl = function() {
			this.hash=this.states+(this.slide!='' ? '-' : '') +this.slide + (this.page!='' ? '*' :'')+this.page;
			this.url=this.base+(this.hash!='' ? '#' : '')+this.hash;
		}
		
	}
	
	// default settings
	var defaults = {
		showcontrolbox: false, 	// Display the control box for switching the wells states
		callmode: 'ajax', 		// 'ajax','states'. Do ajax calls on state changed or display states
		calldelay: 0, 			// Delay before calling request on state change to show animation
		statesfromhash: false, 	// Initially to set states from hash or from html. When the page is loaded.
		refreshwells: false, 	// Force to refresh default html content of the well according to the state after page is loaded.
		callurl: '"file://localhost/C:/cadillac/prototype/calls/"+well+"/"+state+".html?hash="+hash',	// call address to be evaluated with parameters 
		displayerrors: false,	// Display errors with Alerts or put them in console
		autoHeight: true,
		firstPanelToLoad: 1,
		slideEaseDuration: 1000,
		slideEaseFunction: "easeInOutExpo"

	};
	
	
	var myoptions, 				// plugin properties
		well_url,				// well URL
		window_url,				// window URL
		prev_url,	// prev URL
		global_blockhash=false,	// Block hashchange event trigger 		
		slider_panelWidth;		// slider panel width
		
	
	// methods
	var methods = {
		
		// initialize everything
		init : function( options ) { 			
			
			// remember the URL hashtag	
			
			/* testing regexp
			var w='well1';
			var s='state3';
			var patt=w+'\=[^&]+';
			var reg=new RegExp(patt,'ig');
			var str='well1=state2&well2=state3';
			alert(str.replace(reg,'1'));
			*/
			
			//alert('init');
			// Get url
			well_url =new myurl();
			well_url.parse(window[ 'location' ][ 'href']);
			
			window_url = new myurl();
			window_url.parse(window[ 'location' ][ 'href']);
			
			prev_url=new myurl();
			
			// Clear hash tag directive			
			if ($('body').is('.clear') && window_url.hash!='') {
				window_url.page='0'; // to avoid emprty hash is better to set page 0.
				window_url.states='';
				window_url.slide='';
				window_url.buildurl();
				well_url.parse(window_url.url);
				if (location!=window_url.url) {global_blockhash=true;} // block change hash handler only if URL changed
				location=window_url.url;						
			}

			
			
			// initializing plugin only once
			myoptions = $.extend(defaults, options);
			// prepare control box					
			if (myoptions.showcontrolbox) {					
				$('#state-control').removeClass('hidden');				
				
			}
			else {			
				
				$('#state-control').addClass('hidden');	
			}
								
			
			// initialize slider 
			var slider = $('#slider');
			if (slider)
			{
				slider_panelWidth = slider.find(".panel").width();
				var panelCount = slider.find(".panel").size();
				var panelContainerWidth = slider_panelWidth*panelCount;
				var navClicks = 0; // Used if autoSlideStopWhenClicked = true
				
				// Surround the collection of panel divs with a container div (wide enough for all panels to be lined up end-to-end)
				//$('.panel', slider).wrapAll('<div class="panel-container"></div>');
				// Specify the width of the container div (wide enough for all panels to be lined up end-to-end)
				$(".panel-container", slider).css({ width: panelContainerWidth });
				
				// Specify the current panel.
					
				// If that's not the case, check to see if we're supposed to load a panel other than Panel 1 initially...
				if (myoptions.firstPanelToLoad != 1 && myoptions.firstPanelToLoad <= panelCount) { 
					
					var currentPanel = myoptions.firstPanelToLoad;
					var offset = - (slider_panelWidth*(currentPanel - 1));
					$('.panel-container', slider).css({ marginLeft: offset });
				// Otherwise, we'll just set the current panel to 1...
				} else { 
					
					var currentPanel = 1;
				};
		
				// Set the height of the first panel		
				panelHeight = $('.panel:eq(' + (currentPanel - 1) + ')', slider).height();
				slider.css({ height: panelHeight });
				
			}
			
			// initialiaze wells and states
			this.each(function(){				
				
				// get well name
				$.fn.econtrol.storedata($(this).attr('id'),'well',$(this).attr('id'));
								
				// previous state could be useful
				$.fn.econtrol.storedata($(this).attr('id'),'prevstate',null);
				
				// parsing states form title attribute
				states=$.fn.econtrol.storedata($(this).attr('id'),'states',String($(this).attr('title')).split(','));
			
				$(this).attr('title',''); // clear title
				
				// find default state in class attribute
				s=$(this).attr('class');				
				pat=/state\_[\w]+/gi; // class="myclass ... state_mydefault"
				state=String(pat.exec(s)); 
				
				if (state==null) {
					state='';
				}	else {
					state=state.substr(6,state.length);// cuting state_
				}
				
				// !!! check for state exists in states				
				if (state!='')
				{
					if (String(states).search(state)!=-1){	
						$.fn.econtrol.storedata($(this).attr('id'),'state',state);	
						$.fn.econtrol.storedata($(this).attr('id'),'defaultstate',state);
						$(this).econtrol('hash');						
						
					} else {
						$.fn.econtrol.myerror($(this).attr('id'),'Unknown state "'+state+'"');					
					}
				}					
			});
			
			
		
			// Add slide number to the hash
			if (well_url.slide!='') {
				slider.econtrol('slider_slide',well_url.slide);					
			}
			
			well_url.buildurl();
			
			// 	Refresh wells according to hash
			if (myoptions.statesfromhash) {
				if (window_url.states=='') {
					
					$.fn.econtrol.refreshwells(well_url.states);
				} else {
					$.fn.econtrol.refreshwells(window_url.states);
				}
			} else if (myoptions.refreshwells) {
				$.fn.econtrol.refreshwells(well_url.states);
			}
			
			$('#breadcrumbs').econtrol('crumbs',window_url);		
			
			
			return this.each(function(){});
		},
	
		// sliding
		slider_slide: function (targetPanel) {
						
			if (targetPanel=='') {targetPanel=1;}
			offset = - (slider_panelWidth*(targetPanel - 1));
			
			// hack to hide visible video divs
			$('.video_1').hide();
			$('.video_2').hide();

			
			// Slide
			$('#slider').animate({ marginLeft: offset }, myoptions.slideEaseDuration, myoptions.slideEaseFunction,function(){
				if (myoptions.callcount>=0) {
					myoptions.callback('slide',targetPanel);
				}		
				
				// hack to showe hidden video divs
				$('.video_1').show();
				$('.video_2').show();
				
			});
			well_url.slide=targetPanel;
			
			//$('#slider').econtrol('slider_updatetriggers'); // we will update slider triggers always in updatetriggers method
			
		},		
	
		// update state triggers usually after global hash tag is changed
		updatetriggers: function() {
			var action,well,href,hash,arr;
			
			// trigger href param
			var curl=new myurl();
			
			
			
			this.each(function(){
				curl.parse(window_url.url); // spent 4hrs on this line. stupid.
			
				// Parse well and states data from trigger id attribute	
				var url=new myurl(); 
				id=$(this).attr('id');
				url.parse(id);
			
				curl.statesreplace(url);
				curl.buildurl();				
				
				// different types of triggers
				switch ($(this).get(0).tagName)
				{
					case 'BUTTON': // buttons
						$(this).unbind('click');
						$(this).bind('click',function(e){$.fn.econtrol.triggerhash($(this).attr('id'));});
						break;
						
					default:	// links 
						if ($(this).is('.welltrigger_sp1a')) {
						}						
						$(this).attr('href','#'+curl.hash);
						break;
				}				
			});		
			//$('body').econtrol('slider_updatetriggers');
		},
	
		
		// redraw state control 
		refresh_state_control: function (nocrumbs){
			if (myoptions.showcontrolbox){	
				if ($('#state-control table').is('.hidden')) {hidden=' class="hidden"';} else {hidden='';}
				html='<h2><b>State control</b><a id="state-control-switch" href="#">'+(hidden!='' ? '+' : '-')+'</a></h2><div class="clear"></div>';
				var hidden;
				
				html+='<table cellspacing="0"'+hidden+'><th>Well</th><!--<th>Hash</td>--><th>State</th></tr>';
				this.each(function(){
					control=$('#state-contorl');
					well1=$.fn.econtrol.getdata($(this).attr('id'),'well');
					state=$.fn.econtrol.getdata($(this).attr('id'),'state');
					html=html+'<tr><td>'+well1+'</td><td>';
					
					states=String($.fn.econtrol.getdata($(this).attr('id'),'states')).split(','); // converting string of avaible states to array
					
					
					
					
					if (states!='')
					{
						for (var i=0;i<states.length;i++) {
							html=html+'<a '+ (state==states[i] ? ' class="state_trigger active welltrigger_'+well1+'"' : ' class="state_trigger welltrigger_'+well1+'"')+' id="box_trigger_'+i+'|'+well1+'='+states[i]+'" href="#">'+states[i]+'</a>';
							
						}
					}
					html=html+'</tr>';
					
				});
				
				// add bad state trigger for testing
				/*
				html=html+'<tr><th colspan="3">Exceptions</th></tr>';
				html=html+'<tr><td>Unknown well</td><td>&nbsp;</td><td><a class="state_trigger" id="xt1|mywell=state1" href="#">state_1</a></td></tr>';
				html=html+'<tr><td>fw3</td><td>&nbsp;</td><td><a class="state_trigger" id="xt2|fw1=unknown" href="#">unknown</a></td></tr>';
				*/
				// Slider
				html=html+'<tr><th colspan="3">Slider</th></tr>';
				html=html+'<tr><td colspan="3"><a href="#" id="slider2|-1"'+(window_url.slide=='1' ? ' class="state_trigger active"':' class="state_trigger"')+'>1</a><a id="slider2|-2" href="#" '+(window_url.slide=='2' ? ' class="state_trigger active"':' class="state_trigger"')+'>2</a>';
				// analytics
				html=html+'<tr><th colspan="3">Analytics</th></tr>';
				html=html+'<tr><td colspan="3"><div id="analytics"></div>';

				
				// global data
				html=html+'<tr><th colspan="3">Global vars</th></tr>';
				html=html+'<tr><td colspan="3">Wells state URL<br/><textarea rows="6" cols="37">'+well_url.show()+'</textarea></td></tr>';
				html=html+'<tr><td colspan="3">Window URL<br/><textarea rows="6" cols="37">'+window_url.show()+'</textarea></td></tr>';
								
				html=html+'</table>';
				$('#state-control div').html(html);							
				$('#state-control-switch').click(function(e) {

					if ($('#state-control table').is('.hidden')) {
						$('#state-control table').removeClass('hidden');
						$('#state-control-switch').html('-');
					} else {
						$('#state-control-switch').html('+');
						$('#state-control table').addClass('hidden');
					}
					
					return false;
				});
				
				// Bind click handler to trigger setstate 				
				/*$('a.state_trigger').bind('click',function(){				
					
					//$.fn.econtrol.setstates(this.id);
				});*/
			}
			if (!nocrumbs) {$('#breadcrumbs').econtrol('crumbs',window_url);} // to avoid double analytics calls
			
			
			$('.state_trigger').econtrol('updatetriggers'); // !!! this update should be done every time hash is changed		
			
		},	
		
		// track events with analytics
		trackevent: function(action) {
			var category,action,label;

			// get category name as page name from sitemap
			var page=window_url.page;
			if (page=='') {page='0';}
			var epage=$('#page'+page); 		// current page a element
			
			// if page found
			if (epage.length>0) {
				category=epage.attr('href');
				if (!action) {action=$(this).attr('rel');}
				label='';
				//alert('Track event: "' + category+' / ' + action+' / '+label+'"');				
				
				// custom vars.
				var slot=0;
				$('#ga_customvar span').each(function(index) {					
					var name= $(this).attr('class');
					var value=$(this).html();
					slot++; // we need to store values in different slotes
					_gaq.push(['_setCustomVar',	slot, name,value,2]);
					//alert(name+'='+value);
				});

				
				_gaq.push(['_trackEvent', category, action, label]);
			}
			
		},
		
		// make a call
		makecall: function (req1,state,changeurl) {

			return this.each(function(){
				var elem=this;
				$(elem).load(req1,'{}',function(responseText, textStatus, XMLHttpRequest) {					
					// opera could block XML calls due to security settings.
					if (textStatus==undefined) { 
						// FF gets status undefined when file is not found
						$.fn.econtrol.myerror($(elem).attr('id'),'Undefined status of response for '+req1);
					} else if (textStatus=='success') {
						
						if ($(elem).html().length==0) {
							// !!! in Oprera error doesn't appear when document not found
							$.fn.econtrol.myerror($(elem).attr('id'),'Empty result '+req1);
						} else {						
							$('#'+$(elem).attr('id')+' .state_trigger').econtrol('updatetriggers'); // update triggers href after the content of well is loaded.
						}
					} else {
						$.fn.econtrol.myerror($(elem).attr('id'),'Error during request '+req1);
					}
					$(elem).removeClass('loading');
					
					
					// Correct state in URL					
					var cst=$(elem).find('.view_wrapper');
					if (cst.length!=0 && 1==2){	// is turned of because of location.replace problems in Opera and Safari.				
						
						cstate=String(cst.attr('id')).slice(5);	// get state name "6" from string "view_6"
						if (cstate!=state) {
							//alert('Correct state is '+cstate+' and not '+state+'. '+window_url.url+'|'+changeurl);
							var well=$(elem).attr('id');
							// // delete page from history
							if (changeurl==true) {
								window_url.changestate(well,cstate);
								window_url.buildurl();
								myoptions.callmode='0'; // block calls
								$('#'+well).econtrol('setstate',cstate,false);
								
								if (location!=window_url.url) {global_blockhash=true;} // block change hash handler only if URL changed
								location=window_url.url;
								// update triggers
								$('.well').econtrol('refresh_state_control');
							}							
						}
					}
					
					// callback 				
					if (myoptions.callcount>=0) {
						myoptions.callback($(elem).attr('id'),state);
					}
				});
			});
		},
			
		// generate hash-tag for selected wells and store it
		hash: function() {
			var state,well,hash,reg,prevstate,prevhash,arr;
			return this.each(function(){
				well=$(this).attr('id');
				state=$.fn.econtrol.getdata($(this).attr('id'),'state');
				hash=well+'='+state;
				$.fn.econtrol.storedata($(this).attr('id'),'hash',hash);				
				// updating global hash			
				well_url.changestate(well,state);
				
				
			});
		},
		
		
		// set state for selected wells
		setstate: function (newstate,changeurl) {			
			// !!! check the state is avaible
			var states,prevstate,state;
			return this.each(function(){
				// check for state is avaible
				states=$.fn.econtrol.getdata($(this).attr('id'),'states');
				if (String(states).search(newstate)==-1 && newstate!=0){	// Don't block 0 state.
					$.fn.econtrol.myerror($(this).attr('id'),'Unknown state "'+newstate+'"');											
				} else {					
					
					prevstate=$.fn.econtrol.getdata($(this).attr('id'),'prevstate');
					state=$.fn.econtrol.getdata($(this).attr('id'),'state');				
					$.fn.econtrol.storedata($(this).attr('id'),'prevstate',state);				
					$.fn.econtrol.storedata($(this).attr('id'),'state',newstate);				
									
					// Perfom differnt actions after state is changed depending on settings
					if (myoptions.callmode=='ajax')	{
						$.fn.econtrol.mycallproc($(this).attr('id'),newstate,prevstate,changeurl);												
					} else if (myoptions.callmode=='states') {
						$(this).html(newstate);
					} else if (myoptions.callmode=='0') { // Block calls
						
						myoptions.callmode='ajax';
					}					
					// Change hash					
					$(this).econtrol('hash');									
				}
			});
			
			
		},
		
		// make a check call and trigger hash on success
		checkcall: function (url) {
			var a=$(this);
			$.ajax({
				url: url,					
				context: document.body,
				success: function(data){
					var myData = $.parseJSON(data);
					if (myData.status=='1') {
						var id=a.attr('rel');
						$.fn.econtrol.triggerhash('myid|'+id);
					} else {
						$.fn.econtrol.myerror('','Event ID not set');
					}
				},
				error: function(jqXHR, textStatus, errorThrown) {
					$.fn.econtrol.myerror('','Error while setting Event ID');
				}
			});		
		},
		
		// build bread crumbs
		crumbs: function(newurl,nolightbox){
			var page,map,epage;
			var url=new myurl();
			page=newurl.page;
			if (page=='') {page='0';} else {}
			map=$('#sitemap'); 			// this is where the structure stored
			epage=$('#page'+page); 		// current page a element
			
			if (map.length==0) {$.fn.econtrol.myerror('breadcrumbs','Sitemap not found');return true;}
			if (epage.length==0) {$.fn.econtrol.myerror('','Page '+page+' not found');return true;}
			$.fn.econtrol.analytics(page);
			return this.each(function(){
				var bread=$(this);

				var html='';
				epage.parents('li').each(function(){
					var li=$(this);
					var a=li.find('a:first-child');
					if (a.length!=0) {
						
						// get state trigger directive from rel attribute and build it into myURL object
						url.parse('myid|'+a.attr('rel'));
						var newpage=String(a.attr('id')).replace('page','');
						url.page=newpage;
						url.buildurl();
						
						// special class for lightbox crumbs
						var crclass="state_trigger";
						if (a.attr('class')=='trigger_lightbox') {var crclass="crumb_lightbox";}
						
						// create a crumb
						if (html!="") {var sep='<span>&gt;</span>';} else {var sep='';} // separator code
						html='<a href="#" class="'+crclass+' id_crumb_'+a.attr('id')+'" id="crumb_'+a.attr('id')+'|'+url.hash+'">'+a.html()+'</a> '+sep+html;
					}
					else {
						$.fn.econtrol.myerror('','Parent page not found for page '+page+'');return true;
					}
					
				});
				
				bread.html(html);
				
				// trigger lightbox for special pages	
				// !!! this code could be improved. but straight method http://fancybox.net/blog to call lighbox directly doesn't work. 
				if (epage.is('.trigger_lightbox') && !nolightbox) {
					var fbpath=eval(myoptions.fbpath);	
					epage.live('click',function(e) {
						
						// different lightbox params for pages
						
						var w=700; // lighbox width
						var p='10';	// padding
						var h='90%'	// height												
						
						if (page.search('_37')>=0) {w='80%';} // direction page						
						if (page=='28') {w=400;h=350;p=0} // contact us page
						if (page.search('_29')>=0) {w=400;h=300;p=0} // invite a friend


						$.fancybox({
							'width'				: w,
							'height'			: h,
							'autoScale'			: false,
							'modal'				: false,
							'padding'			: p,
							'centerOnScroll'	: false,
							'titleShow'			: false,
							'hideOnOverlayClick': false,
							'showCloseButton'	: true,
							'enableEscapeButton': true,
							'showNavArrows'		: false,
							'overlayShow'		: true,
							'opacity'			: true,
							'overlayOpacity'	: '0.6',
							'overlayColor'		: '#000',
							'speedIn'			: 300,
							'transitionIn'		: 'fade',
							'transitionOut'		: 'none',
							'type'				: 'iframe',
							'href'				: fbpath,
							'onClosed'			: function(){
								// need to return back 		
								var tempurl=new myurl();
								tempurl.parse(newurl.url);
								
								tempurl.page=prev_url.page;
								if (prev_url.page=='') {
									tempurl.page='0';
								}
								tempurl.buildurl();
								window.location=tempurl.url;
								
							}
						});
						
					});					
					setTimeout(function() {/*alert('lightbox');*/;epage.click();}, 200); // need that to wait for lightbox ready
				}
			});
			
			
			// update page triggers
			$('.page_trigger').click(function(e) {
			
			});
			
			
		}
	};
	
	
	
	// we can call methods like $('div').econtrol('methodname')
	$.fn.econtrol = function( method ) {    
		if ( methods[method] ) {
		  return methods[ method ].apply( this, Array.prototype.slice.call( arguments, 1 ));
		} else if ( typeof method === 'object' || ! method ) {
		  return methods.init.apply( this, arguments );
		} else {
		  $.error( 'Method ' +  method + ' does not exist on jQuery.econtrol' );
		}   
	}
	
	/* global methods */	
	
		
	// simple error handler
	$.fn.econtrol.myerror = function (well,msg){
		// 
		if (!myoptions.displayerrors) {
			if (window.console != undefined) {
				console.error(msg);
			}
		} else {		
			if (well=='') {
				alert(msg);
			} else if ($.find('#'+well)=='') {
				alert(msg);		
			} else {
				$('#'+well).html('<b>Error</b>:'+msg);
			}
		}
	},
	
	// analitics \ add pageview to tracker
	$.fn.econtrol.analytics = function (id){		
		var epage=$('#page'+id);

		if (epage.length!=0) {
			
			$('#analytics').html(epage.attr('href'));
			
			// custom vars.
			var slot=0;
			$('#ga_customvar span').each(function(index) {					
				var name= $(this).attr('class');
				var value=$(this).html();
				slot++; // we need to store values in different slotes
				_gaq.push(['_setCustomVar',	slot, name,value,2]);
				//alert(name+'='+value);
			});
				
				
			
			
			_gaq.push(['_trackPageview', epage.attr('href')]);		
			//alert('analytics pageview: "'+epage.attr('href')+'"');
		}
		else {
			$.fn.econtrol.myerror('','Unknown page '+id+' for analytics');
		}
	},
	
	
	// trigger change of window.url hash tag usually from elements with no href attribute
	$.fn.econtrol.triggerhash = function (id,refresh) {
		var url,href,arr,arrw,state,reg,hash,slide;
		//if (myoptions.callcount>=0) {$.fn.econtrol.myerror('','Hash trigger handler is busy with previous call. Triggerhsh '+id);return;}		
		
		var curl = new myurl(),turl=new myurl();
		curl.parse(window_url.url);		
		turl.parse(id);		
		if (refresh) {
			var r=Math.floor(Math.random()*1000)
			turl.changestate('ref',r);			
		}		
		curl.statesreplace(turl);
		curl.buildurl();
		
/*		
		if (curl.url==window_url.url) { // forse to refresh wells with 0 states.
		}
*/		//alert(curl.show());		
		window.location=curl.url;		
	},
	
	//	show / hide globlal loader div
	$.fn.econtrol.loader = function (flag) {
		if (flag) { 
			$('#gload').show();			
		} else {
			$('#gload').hide();
		}
	},
	
	// trigger sequence of hashes 
	$.fn.econtrol.multihash = function (hashes) {	// hashes = array
		// each hash could be "well1=state1&well2=state2" or "-2" or "*29" format but not both at once
		var url=new myurl();
		
		if (myoptions.callcount>=0) {$.fn.econtrol.myerror('','Hash trigger handler is busy with previous call');return;}		
		
		myoptions.callcount=0; // reset calls count
		myoptions.hashes=hashes; // keep array of hashes			
		myoptions.currenthash=0;			
		myoptions.tempurl=new myurl(); // store changes of URL here			
		myoptions.tempurl.parse(window_url.url);
		
		if (hashes[myoptions.currenthash][0]=='load') { // loader
			
		} else {
			url.parse('#'+hashes[myoptions.currenthash][0]);			
			myoptions.tempchangeurl=hashes[myoptions.currenthash][1]; 
		}
		
		// check format
		if (url.slide!='' && url.states!='') {$.fn.econtrol.myerror('','Bad hash format for multi trigger');return;}
		
		// number of calls or slides to wait 			
		if (url.slide!='') { // slide
			myoptions.callsexpected=1;
			$('#slider').econtrol('slider_slide',url.slide);	
		} else { // refresh wells
			myoptions.callsexpected=url.states.split('&').length;				
		}
		
		// call back will execute after each trigger hash is done
		myoptions.callback=function(well,state) {
		
			// check if the well is in our hash
			
			if (myoptions.hashes[myoptions.currenthash][0].search(well+'=')==-1 && well!='slide' && well!='page'  && well!='loader' ) {return;}
			
			//alert(myoptions.callcount+'|'+well+'|'+state+'|'+myoptions.callsexpected);
			
			//if (myoption.callcount>=0) {$.fn.econtrol.myerror('','Hash trigger handler is busy with sequence of calls');return}
			//$.fn.econtrol.myerror('','Loging sequence: '+ myoptions.callcount+'|'+well+'|'+state+'|'+myoptions.callsexpected);
			
			myoptions.callcount++;
			
			if (myoptions.callcount>=myoptions.callsexpected) {
				myoptions.currenthash++;
				
				if (myoptions.currenthash<myoptions.hashes.length) {
					
					// fix adds 2nd and 3rd value to an array
					if (myoptions.hashes[myoptions.currenthash].length==2) {
						myoptions.hashes[myoptions.currenthash][2]=false;							
					} else if (myoptions.hashes[myoptions.currenthash].length==1) {
						myoptions.hashes[myoptions.currenthash][1]=false;
					}
				
					if (myoptions.hashes[myoptions.currenthash][0]=='load') { // loader
						myoptions.callsexpected=1;
						$.fn.econtrol.loader(myoptions.hashes[myoptions.currenthash][1]);
						myoptions.callback('loader');			
					} else {
				
						myoptions.tempchangeurl=myoptions.hashes[myoptions.currenthash][1]; 
						var suburl=new myurl();
						myoptions.callcount=0;						
						suburl.parse('#'+myoptions.hashes[myoptions.currenthash][0]);												
						// check format
						if (suburl.slide!='' && suburl.states!='') {$.fn.econtrol.myerror('','Bad hash format for multi trigger');return;}
						
						// number of calls or slides to wait 			
						if (suburl.slide!='') { // slide
							myoptions.callsexpected=1;
							$('#slider').econtrol('slider_slide',suburl.slide);	
							myoptions.tempurl.slide=suburl.slide; // save last slide position to apply for window URL
						} else if (suburl.page!='') { // change page
							myoptions.tempurl.page=suburl.page;	
							myoptions.callsexpected=1;
							myoptions.callback('page',suburl.page);
						} else { // refresh wells
							myoptions.callsexpected=suburl.states.split('&').length;
							if (myoptions.hashes[myoptions.currenthash][1]) {myoptions.tempurl.statesreplace(suburl);} // change url;
							$.fn.econtrol.refreshwells(suburl.states,myoptions.hashes[myoptions.currenthash][2]);
						}	
					}
				} else { // end of sequence
					myoptions.callcount=-1;	
					myoptions.tempurl.buildurl();
					
					
					if (location!=myoptions.tempurl.url) {global_blockhash=true;} // block change hash handler only if URL changed					
					location=myoptions.tempurl.url;					
				}
			}
		
		}
		
		if (hashes[myoptions.currenthash][0]=='load') { // loader
			myoptions.callsexpected=1;
			$.fn.econtrol.loader(hashes[myoptions.currenthash][1]);
			myoptions.callback('loader');			
		} else {
			
			// fix adds 2nd and 3rd value to an array
			if (myoptions.hashes[myoptions.currenthash].length==2) {
				myoptions.hashes[myoptions.currenthash][2]=false;							
			} else if (myoptions.hashes[myoptions.currenthash].length==1) {
				myoptions.hashes[myoptions.currenthash][1]=false;
			}
				
			
			if (url.slide!='') { // slide
				myoptions.callsexpected=1;	// number of calls or slides to wait 
				$('#slider').econtrol('slider_slide',url.slide);	
				myoptions.tempurl.slide=url.slide; // save last slide position to apply for window URL			
			} else if (url.page!='') { // change page
				myoptions.tempurl.page=url.page;
				myoptions.callsexpected=1;

				myoptions.callback('page',url.page);
				
			} else { // refresh wells
				myoptions.callsexpected=url.states.split('&').length; // number of calls or slides to wait
				if (myoptions.hashes[myoptions.currenthash][1]) {myoptions.tempurl.statesreplace(url);} // change url;
				$.fn.econtrol.refreshwells(url.states,myoptions.hashes[myoptions.currenthash][2]);				
				
			}	
		}
	}
	
	// 
	$.fn.econtrol.callproc = function(well,state,changeurl) {
		//if (myoptions.callcount>=0) {$.fn.econtrol.myerror('','Hash trigger handler is busy with previous call. Callproc '+well+'='+state);return;}	
		$('#'+well).econtrol('setstate',state,changeurl);
	}

	
	// perform ajax call when state is changed
	$.fn.econtrol.mycallproc = function(well,state,prevstate,changeurl) {
		var hash;
		hash=encodeURIComponent(window_url.hash);
		var page=window_url.page;
		var slide=window_url.slide;
		
		// build request string
		var req=eval(myoptions.callurl);				
		// calling well method
		// !!! standard delay() doesn't work here. i have to use setTimeout which is not correct inside jQuery.
		$('#'+well).addClass('loading');
		if (myoptions.calldelay>0) {
			setTimeout(function() {$('#'+well).econtrol('makecall',req,state,changeurl);}, myoptions.calldelay);
			
		} else {
			$('#'+well).econtrol('makecall',req,state,changeurl);			
		}
		
		// Refresh Coldfusion debugger well
		if ($('#cfdebug').length!=0) {
			$('#cfdebug').addClass('loading');
			var cfdebugreq = "";
			if(req.search("localhost") >= 0){
				cfdebugreq = "http://localhost/cadillac/wells/cfdebug_control.cfm";
			} else {
				cfdebugreq = "http://192.168.16.15/cadillac/wells/cfdebug_control.cfm";
			}
			//var cfdebugreq = "http://192.168.16.15/cadillac/wells/cfdebug_control.cfm"
			if (myoptions.calldelay>0) {
				//setTimeout(function() {$('#cfdebug').econtrol('makecall',cfdebugreq);}, myoptions.calldelay);
			} else {
				//$('#'+well).econtrol('makecall',cfdebugreq);
			}	
		}
	}

	// refresh well state from hash
	$.fn.econtrol.refreshwells = function(hash,forcerefresh) {
		var well,
			state,
			well_state,
			curstate,
			refresh=false;
			
		if (hash.search(/(&|#)ref\=/ig)>0) {
			refresh=true;
			//hash=hash.replace(/(&|#)ref\=[0-9]/ig,'');			
		}
		
		var wells=hash.split('&');
		
		if (hash=='') {$('.well').econtrol('refresh_state_control',true);return false;} // need to refresh crumbs etc. here.
		
		// check for refresh flag in hash like "r=1233"
		
		
		// !!! we can create a check for number of well to refresh. if it more then 3 then we can trigger a page refresh
		
		for (var i=0;i<wells.length;i++)	{
			
			well_state=wells[i].split('=');
			state=well_state[1];
			well=well_state[0];
			if (well=='ref') {continue;}
			if ($.find('#'+well)=='') {$.fn.econtrol.myerror('body','Unknown well ' + well);continue;}
				
			curstate=$.fn.econtrol.getdata(well,'state');
			defstate=$.fn.econtrol.getdata(well,'defaultstate');
			
			
			if (myoptions.refreshwells) // refresh wells after paged loaded
			{	
				if (defstate!='' || state!=curstate || refresh || forcerefresh)  {			
					$('#'+well).econtrol('setstate',state,true);				
					$.fn.econtrol.storedata(well,'defaultstate','');
				} else {
					if (myoptions.callcount>=0) {
						myoptions.callback(well,state);
					}							
				}
			} else if (state!=curstate || refresh || forcerefresh) {	
				$('#'+well).econtrol('setstate',state,true);
			} else {
				if (myoptions.callcount>=0) {
					myoptions.callback(well,state);
				}		
			}
		
			
		}
		$('.well').econtrol('refresh_state_control',true);
		
		
	}
	
	// return global varibales
	$.fn.econtrol.getvar = function(name)	{
		eval('var v='+name);
		return v;
	}
	
	// set global varibales
	$.fn.econtrol.setvar = function(name,value)	{
		eval(name+'='+value);
		return value;
	}	
	
	// store state data 
	$.fn.econtrol.storedata = function (id,name,value) {
	
		value=jQuery.data(document.body,'well_'+id+'_'+name,value);		
		return value;
	}
		
	// get state data
	$.fn.econtrol.getdata = function (id,name) {		
		return jQuery.data(document.body,'well_'+id+'_'+name);	

	}
	
	// bind a hashchange event handler 
	$(window).bind( 'hashchange', function(e) {
		
		var newurl= new myurl();
		prev_url.parse(window_url.url);
		newurl.parse(window[ 'location' ][ 'href']);
		
		//alert(global_blockhash);
		if (global_blockhash) { // block everything just change URL and refresh triggers
			global_blockhash=false;
			window_url.parse(window[ 'location' ][ 'href']);
			$('.well').econtrol('refresh_state_control'); 			
			return;
		}
		// mix states  in URL with current well states.
		if (well_url.states!=window_url.states) {
			//window_url.statesreplace(well_url);
		}
		// Slide 
		if (newurl.slide!=window_url.slide) {
			$('#slider').econtrol('slider_slide',newurl.slide);
			
		}
		// change breadcrumbs
		if (window_url.page!=newurl.page) {$('#breadcrumbs').econtrol('crumbs',newurl);} 
		
		// Update wells states only if hash is different 
		if (newurl.states!=window_url.states) {	// new states			
			window_url.parse(newurl.url);
			$('.well').econtrol.refreshwells(window_url.states);						
		} else if (newurl.slide!=window_url.slide) { // new slide
			window_url.parse(newurl.url);
			$('.well').econtrol('refresh_state_control',true); // we need to update all triggers with new hash
		} else if (newurl.page!=window_url.page) { // new page
			window_url.parse(newurl.url);
			$('.well').econtrol('refresh_state_control',true); // we need to update all triggers with new hash
		}

			
	});
})(jQuery); 

