var SG = new function() {
	this.logged_in = null;
	this.COUNTRY_ID_USA = 840;

	this.removeArtist = function (a_id) {
		$.get('/flag/remove_favorite/artist/'+a_id);
		$('#artistdiv-'+a_id).remove();
		if ($('.favartist').length===0) {
			$('#favmsg').show();
		}
	};

	this.removeFriend = function (f_id) {
		    $.get('/flag/remove_favorite/friend/'+f_id);
		    $('#frienddiv-'+f_id).remove();
	};

	this.FB = new function() {
		this.inited = null;
		this.onlike = function(url) {
			if (SG.logged_in===1) {
				SG.ajax('POST','/ajax/fbonlike',{url:url});
			} 
		};
		this.stream_publish = function(att, action_links, redir_url) {
			FB.ui(
				{
					method: 'stream.publish',
					message: '',
					attachment: att, 
					action_links: action_links
					//user_message_prompt: 'Share your thoughts about Connect'
				},
				function(response) {
					if (response && response.post_id) {
						document.location.href = redir_url;
						//alert('Post was published.');
					} else {
						document.location.href = redir_url;
						//alert('Post was not published.');
					}
				}
			);
		};
	};
	this.ajax_cookie_timeout = 180; // 3 minutes
	this.ajax = function(method, url, data, callback, error_cb) {
		method = method.toUpperCase();
		data = data || {};
		
		if (method == 'GET') {
			var ac = SG.cookie.get('anticache');
			if (ac) {
				data.anticache = ac;
			}
		}
		else {
			SG.cookie.set('anticache', (new Date()).getTime(), 0, SG.ajax_cookie_timeout);
		}
		
		var rq = {
			type: method,
			url: url,
			data: data
		};

		if (callback) {
			rq.success = callback;
		}
		if (error_cb) {
			rq.error = error_cb;
		}

		$.ajax(rq);
	};

	this.error = function() {
		console.log.apply(console, arguments);
	};

	this.cookie = new function() {
		this.get = function(name) {
			if (document.cookie.length>0) {
				c_start=document.cookie.indexOf(name + "=");
				if (c_start!=-1) {
					c_start=c_start + name.length+1;
					c_end=document.cookie.indexOf(";",c_start);
					if (c_end==-1) {
						c_end=document.cookie.length;
					}
					return unescape(document.cookie.substring(c_start,c_end));
				}
			}
			return "";
		};

		this.set = function(name, value, expiredays, expireseconds) {
			var exdate = new Date();
			if (expiredays) {
				exdate.setDate(exdate.getDate() + expiredays);
			}
			if (expireseconds) {
				exdate.setSeconds(exdate.getSeconds() + expireseconds);
			}
			document.cookie = name+ "=" +escape(value) + ((!expiredays && !expireseconds) ? "" : ";expires="+exdate.toGMTString());
		};
	};

	this.ajax_click_link = function(link, success, error) {
		var l = $(link);
		var url = l.attr('href');
		var cb = function(data, textstatus) {
			if (textstatus != 'success') {
				return;
			}
			if (success) {
				success(data, textstatus);
			}
		};
		var err = function(xhr, textstatus, errorthrown) {
			if (error) {
				error(xhr, textstatus, errorthrown);
			}
		};
		$.ajax({
			type: 'GET',
			url: url,
			success: cb,
			error: err
		});
	};

	this.ajax_submit_form = function(form, success, error) {
		var f = $(form);
		var url = f.attr('action');
		if (f) {
			var inputs = f.find('input,textarea');
			var data = {ajax:1};
			inputs.each(function(i) {
				data[ this.name ] = this.value;
			});
			var cb = function(data, textstatus) {
				if (textstatus != 'success') {
					return;
				}
				if (success) {
					success(data, textstatus);
				}
			};
			var err = function(xhr, textstatus, errorthrown) {
				if (error) {
					error(xhr, textstatus, errorthrown);
				}
			};
			SG.ajax('POST', url, data, cb, err);
		}
	};

	this.add_highlight_controls = function(item_ids) {
		var url = '/json/item-highlight-status';
		var cb = function(data, ts) {
			for (var i in item_ids) {
				var iid = item_ids[i];
				var t = $('span#hc_'+iid);

				var link = $('<a></a>');
				if (data[iid]) {
					link.attr('href', '/flag/highlight/off/'+iid);
					link.html('Dehighlight in SMJ');
				}
				else {
					link.attr('href', '/flag/highlight/on/'+iid);
					link.html('Highlight in SMJ');
				}
				t.html(link);
			}
		};

		$.post(url, {'item_ids[]': item_ids}, cb, 'json');
	};

	this.gallery = new function() {
		var self = this;

		this.args = null;
		this.inited = false;
		
		// div order inside target:
		// stretcher_left=0 shrinker_right=600 pane_left=600 pane_center=600 pane_right=600
		//
		// next -> scroll right
		// load content into pane_right
		// animate shrinker_right w=600 -> w=0
		// empty pane_center
		// remove stretcher_left
		// stretcher_left = shrinker_right
		// shrinker_right = pane_left
		// pane_center = pane_right
		// new pane_right
		//
		// previous -> scroll left
		// load content into pane_left
		// animate stretcher_left w=0 -> w=600
		// remove pane_right
		// empty pane_center
		// pane_right = pane_center
		// pane_center = pane_left
		// pane_left = shrinker_right
		// shrinker_right = stretcher_left
		// new stretcher_left w=0

		this.item_viewer_init = function(wrapper, init_args, env_args) {
			self.inited = true;
			var cookie = SG.cookie.get('gallery-hash');
			if (cookie) {
				document.location.hash = '#'+cookie;
				SG.cookie.set('gallery-hash', '');
			}

			self.env = {
				baseurl: '/ajax/items/',
				linkable: 1,
				featured: 0
			};
			for (var i in env_args) {
				self.env[i] = env_args[i];
			}

			if (self.env.linkable) {
				if (document.location.hash && document.location.hash!='#pic') {
					var h = document.location.hash.substr(1).split('/');
					var keys = ['type', 'user', 'show', 'pic'];
					for (var i = 0; i < h.length; ++i) {
						init_args[ keys[i] ] = h[i];
					}
				}
			}

			self.args = init_args;

			self.anim_speed = 'fast';
			if (self.args.type == 'video') {
				self.anim_speed = 'fast';
			}
			self.anim_mode = 'swing';

			self.working = false;
			self.photo_loading = false;
			self.photo_loading_timeout = null;

			self.wrapper = $(wrapper);

			self.unit = self.wrapper.width();

			self.target = self.newdiv(self.unit*5, {});

			self.wrapper.css({overflow: 'hidden'});
			self.wrapper.append(self.target);

			self.stretcher_left = self.newdiv(0);
			self.target.append(self.stretcher_left);

			self.shrinker_right = self.newdiv(self.unit);
			self.target.append(self.shrinker_right);

			self.pane_left = self.newdiv(self.unit);
			self.target.append(self.pane_left);
		
			self.pane_center = self.newdiv(self.unit, {'float': 'left', 'height': 'auto'});
			self.pane_center.append($('<center>').append($('<img>').attr('src', '/static/sg/img/loading.gif')));
			self.target.append(self.pane_center);

			self.pane_right = self.newdiv(self.unit);
			self.target.append(self.pane_right);
			
			self.wrapper.scrollLeft(self.unit*2);

			self.prefetch_div = self.newdiv(0, {'zIndex': -200, 'position': 'absolute', 'top': 0, 'left': 0});
			$(document).append(self.prefetch_div);

			self.load_contents(self.pane_center, self.args, function() {
				$(document).trigger('galleryload'+self.currentargs());
			});
			self.track();
		};

		this.anchor = function() {
			if (self.env.linkable && self.args && document.location.hash) {
				SG.cookie.set('gallery-hash', document.location.hash.substr(1));
			}	
		};

		this.track = function() {
			 var
				gapathname = window.location.pathname,
				gasearch = window.location.search,
				gahash = escape(window.location.hash);

			 try {
				 pageTracker._trackPageview(gapathname + gasearch + gahash);
			 } catch(err) {}
		};

		this.newdiv = function(w,css) {
			if (typeof(css) == 'undefined') {
				css = {
					'float': 'left',
					'height': '1px'
				};
			}
			css.width = w;
			var d = $('<div></div>').css(css);
			return d;
		};

		this.set_loader = function(where, on) {
			var exists = $('#slowpic-loader');
			if (on && !exists.length) {
				var i = $('<div id="slowpic-loader"></div>').append($('<img src="/static/sg/img/loading.gif"/>'));
				where.prepend(i);
			} else if (!on && exists.length) {
				exists.remove();
			}
		};

		this.load_contents = function(where, args, on_append_done) {
			var url = self.argformat(args);
			if (typeof(on_append_done) != 'function') {
				on_append_done = function(){};
			}
			if (args.type == 'photo') {
				if (self.photo_loading_timeout) {
					clearTimeout(self.photo_loading_timeout);
				}
				self.set_loader(null, false);
				self.photo_loading = true;
				self.photo_loading_timeout = setTimeout(function(){
						if (self.photo_loading) {
							self.set_loader(where.find('div.content-holder div.centered'), true);
						}
						self.photo_loading_timeout = null;
				}, 1000);

			}

			var cb = function(data) {
				where.height('auto');
				where.empty();
				where.append(data).ready(function() {
					on_append_done();
					var nav = where.find('a.nav');
					if (args.type == 'photo') {
						self.prefetch(nav);
					}
					var photos = where.find('img.photo');
					if (photos.length && !photos.get(0).complete) {
						photos.load(function(){
							self.photo_loading = false;
							if (self.photo_loading_timeout) {
								clearTimeout(self.photo_loading_timeout);
								self.photo_loading_timeout = null;
							}
							self.set_loader(null, false);
						});
					} else {
						if (self.photo_loading_timeout) {
							clearTimeout(self.photo_loading_timeout);
							self.photo_loading_timeout = null;
						}
						self.photo_loading = false;
						self.set_loader(null, false);
					}
				});
			};
			SG.ajax('GET', self.env.baseurl+url, {}, cb);
		};

		this.prefetch = function(elts) {
			self.prefetch_div.empty();
			elts.each(function(i) {
				SG.ajax('GET', $(this).attr('href'), {}, function(d) { self.prefetch_div.append(d); });
			});
		};

		this.argformat = function(args) {
			if (self.env.featured) {
				return isNaN(args.pic) ? 0 : 0+args.pic;
			}
			else {
				return [args.type, args.user, args.show, args.pic].join('/');
			}
		};

		this.currentargs = function () {
			if (self.env.linkable && document.location.hash && document.location.hash!='#pic') {
				return document.location.hash.substr(1);
			} else {
				return self.argformat(self.args);
			}
		};

		this.flip = function(arg_diff, dir, link) {
			if (self.working) {
				return;
			}

			self.working = true;
			var args = self.args;
			for (var i in arg_diff) {
				args[i] = arg_diff[i];
			}

			if (self.env.linkable) {
				document.location.hash = '#'+self.argformat(args);
			}

			self.track();

			var where, cb;
			if (dir == 'left') {
				where = self.pane_left;
				cb = function() {
					self.stretcher_left.animate({width: self.unit+0}, self.anim_speed, self.anim_mode, function() {
						self.pane_right.remove();
						self.pane_center.empty().height('1px');

						self.pane_right = self.pane_center;
						self.pane_center = self.pane_left;
						self.pane_left = self.shrinker_right;
						self.shrinker_right = self.stretcher_left;
						
						self.stretcher_left = self.newdiv(0);
						self.target.prepend(self.stretcher_left);

						self.working = false;
						$(document).trigger('galleryload'+self.currentargs());
					});
				};
			} else if (dir == 'right') {
				where = self.pane_right;
				cb = function() {
					self.shrinker_right.animate({width: 0}, self.anim_speed, self.anim_mode, function() {
						self.stretcher_left.remove();
						self.pane_center.empty().height('1px');

						self.stretcher_left = self.shrinker_right;
						self.shrinker_right = self.pane_left;
						self.pane_left = self.pane_center;
						self.pane_center = self.pane_right;

						self.pane_right = self.newdiv(self.unit);
						self.target.append(self.pane_right);

						self.working = false;
						$(document).trigger('galleryload'+self.currentargs());
					});
				};
			} else {
				where = self.pane_center;
				cb = function() {
						self.working = false;
						$(document).trigger('galleryload'+self.currentargs());
				};
			}

			self.load_contents(where, args, cb);
		};
	
		this.local_switch_show = function(show_id) {
			SG.error('SG.gallery.local_switch_show() unimplemented. ajax/item-browser calls this, but the surrounding page has to implement it');
		};
	};

	this.hide_state_if_nonus = function(sel, elt_spec) {
		var cid = $(sel).val();
		if (cid == SG.COUNTRY_ID_USA) { // this is the US country_id. this also sucks. o well
			$(elt_spec).show();
		} else {
			$(elt_spec).hide();
			$(elt_spec).get(0).selectedIndex=0;
		}
	};

	this.festival = function() {
	};
	this.festival.tweetsdisplayinit = function (twitterfeedurl) {
		$('#festivaltweets .tweetcontainer').attr('scrollTop',0);
		$('#festivaltweets .tweetcontainer').load(twitterfeedurl);
		$('#festivaltweets .tweetScrollDown').click(function(){
			$('#festivaltweets .tweetcontainer').animate({
				scrollTop:$('#festivaltweets .tweetcontainer').attr('scrollTop')+$('#festivaltweets .tweetcontainer').attr('offsetHeight')
			},1500);
		});
		$('#festivaltweets .tweetScrollUp').click(function(){
			$('#festivaltweets .tweetcontainer').animate({
				scrollTop:$('#festivaltweets .tweetcontainer').attr('scrollTop')-$('#festivaltweets .tweetcontainer').attr('offsetHeight')
			},1500);
		});
		$('#festivaltweets .tweetRefresh').click(function(){
			$('#festivaltweets .tweetcontainer').attr('scrollTop',0);
			$('#festivaltweets .tweetcontainer').load(twitterfeedurl);
		});
	};
	this.FestivalDaySelect = function(day) {
		if (day) {
			$('.days').each(function() {
				if ($(this).hasClass('day_'+day)) {
					$(this).show();
				} else {
					$(this).hide();
				}
			});
		} else {
			$('.days').show();
		}
		return false;
	};
	this.waitfor_gmaps_js = function(do_what,i) {
		if (typeof(i)=='undefined') {
			i=0;
		}
		if (i>=5) {
			return false;
		}
		if (typeof(google)!='object' || typeof(google.maps)!='object') {
			setTimeout(function(){
				SG.waitfor_gmaps_js(do_what,i+1);
			},1000);
		} else {
			do_what();
		}
	};
	this.waitfor_fb_connect_js = function (do_what) {
		if (typeof(FB)=='undefined' || typeof(FB.Connect)=='undefined' || typeof(FB.Connect.requireSession)=='undefined') {
			setTimeout(function() {SG.waitfor_fb_connect_js(do_what);},1000);
		} else {
			do_what();
		}
	};

	this.load_gmaps_js = function(cb,with_sensor) {
		var sensor;
		if (typeof(with_sensor)==='undefined' || !with_sensor) {
			sensor = 'false';
		} else {
			sensor = 'true';
		}
		SG.waitfor_gmaps_js(cb);
	};
	this.edit_tags = function (id) {
		$('#tags-'+id).load('/json/item_tie_formlet/'+id);
	};
	this.setlistplayer = function () {
		var a,songs,i,song;
		a = $('div.setlist .artist_name').html();
		if (!a) { // no artist found
			return;
		}
		songs = $('div.setlist div.list ol li');
		if (songs.length===0) { // no songs found
			return;
		}
		SG.ytapiplayercount=0;
		for (i=0;i<songs.length;++i) {
			song = songs[i];
			this.setlist_item_lookup(a,$(song));
		}
	};
	this.setlist_item_lookup = function (artist,songli) {
		var u = 'http://gdata.youtube.com/feeds/api/videos?q='+escape(artist)+' - '+escape(songli.html())+'&alt=json-in-script&callback=SG.setlist_cb';
		SG.ensure_loaded('js', u);
	};
	this.setlist_cb = function(a) {
		var params,atts,vid;
		SG.ensure_loaded('js','/static/sg/js/swfobject.js');
		$('#artist_show_setlist div.setlist').append('<h4>'+a.feed.entry[0].title.$t+'</h4>');
		$('#artist_show_setlist div.setlist').append('<div id="ytapiplayer'+SG.ytapiplayercount+'"></div>');
		params = { allowScriptAccess: "always" };
		atts = { id: "myytplayer" };
		vid = a.feed.entry[0].link[0].href.split('=')[1];
		swfobject.embedSWF("http://www.youtube.com/v/"+vid+"&enablejsapi=1&playerapiid=ytplayer", 
			"ytapiplayer"+SG.ytapiplayercount, "180", "151", "8", null, null, params, atts);

		SG.ytapiplayercount++;
	};
	this.autofill_city_state_by_zip = function(zip, location_str, city) {
		var h, cb;

		zip = $(SG.htmlid_or_domnode(zip));
		city = $(SG.htmlid_or_domnode(city));
		location_str = $(SG.htmlid_or_domnode(location_str));
		

		cb = function(r, st) {
			if (st === 'success') {
				if (r.city && r.state) {
					location_str.html(r.city+', '+r.state);
					if (city) {
						city.val(r.city);
					}
				}
			} else {
			}
		};

		h = function(e) {
			var v = zip.val();
			$.post('/json/zip', {zip: v}, cb, 'json');
		};
		zip.bind('keyup', h);
		zip.bind('change', h);
	};

	this.ensure_loaded = function(type, url,cb) {
		var h,found,tag,fn,elt;
		h = $('head');
		found = false;

		switch (type) {
		case 'js':
			tag = 'script';
			fn = function() {
				if (this.src == url) {
					found = true;
				}
			};
			elt = $('<script type="text/javascript">').attr('src', url);
			break;
		case 'css':
			tag = 'link';
			fn = function() {
				if (this.href == url) {
					found = true;
				}
			};
			elt = $('<link rel="stylesheet" type="text/css" href="'+url+'"/>');
			break;
		}
		h.find(tag).each(fn);
		if (!found) {
			h.append(elt);
			if (typeof(cb)==='function') {
				elt.ready(function(){
					cb();
				});
			}
		} else {
			if (typeof(cb)==='function') {
				cb();
			}
		}
	};

	this.add_message = function(content, st) {
		st = (st === 1 || st === 0) ? st : null;
		var div = $('div#messages_holder');
		var subdiv = div.children('div#status_bar');
		if (!subdiv.length) {
			subdiv = $('<div id="status_bar">');
			div.append(subdiv);
		}
		var ul = subdiv.children('ul');
		if (!ul.length) {
			ul = $('<ul>');
			subdiv.append(ul);
		}
		var li = $('<li>');
		if (st === 0 || st === 1) {
			var span = $('<span class="h2">').append(
					$('<img align="absmiddle">')
					.attr('alt', (st == 1 ? 'Success!' : 'Failure'))
					.attr('src', (st == 1 ? '/static/sg/img/icons/success.png' : '/static/sg/img/icons/error.png'))
			);
			li.append(span);
		}
		li.append(content);
		ul.append(li);
		subdiv.slideDown('slow', function() { subdiv.find('li').addClass('shown'); }).fadeTo(5000, 1).slideUp('slow', function() { $('#status_bar li.shown').remove(); });
	};

	this.make_message_box_fixed = function() {
//		$('div#messages_holder').css({ position: 'fixed'});
		$('div');
	};

	this.cancel_send_m2m = function(name) {
		GB_hide();
		SG.add_message('Your message to '+name+' was canceled and not sent');
	};

	this.ok_send_m2m = function(name) {
		GB_hide();
		SG.add_message('Your message to '+name+' has been sent', 1);
	};

	this.flag_review = function(elt, type, id1, id2) {
		$.get('/flag/review/'+type+'/'+id1+'/'+id2, { bg: 1 });

		if (elt !== undefined && elt !== null) {
			$(elt.parentNode).find('input[type=checkbox]').attr('disabled', 'disabled');
			$(elt.parentNode).find('a.flag').remove();
		}
		return false;
	};

	this.htmlid_or_domnode = function(what) {
		if (typeof(what) == 'string') {
			return '#'+what;
		} else {
			return what;
		}
	};

	this.init_search = function(id_pfx, options) {
		var self = this;
		this.pfx = id_pfx;

		this.tabs = $('#'+this.pfx+'_tabs');
		this.frame = $('#'+this.pfx+'_wrap');
		this.pagers = this.frame.find('.'+this.pfx+'_pager');
		this.filter = $('#'+this.pfx+'_controls');
		this.crumbs = this.frame.find('.'+this.pfx+'_crumbs');
		this.top_breadcrumb = $('#'+this.pfx+'_top_breadcrumb');

		this.options = options;
		this.ctrl = null;

		this.empty = function() {
			self.frame.find('.row').remove();
		};
		this.is_empty = function() {
			return self.frame.find('.row').length !== 0 ? false : true;
		};

		this.append = function(e) {
			$(e).insertBefore(self.pagers.get(1));
			return;
		};

		this.get_results = function() {
			SG.fill_header();
			SG.fill_filters();
			SG.fill_loading();

			var cb = function(r, st) {
				if (st == 'success' && r.error === '') {
					SG.fill_results(r);
				} else {
					SG.fill_error(st, (st == 'success' ? r.error : null));
				}
				$('.spinning-loader').fadeOut(500,function(){$(this).remove();});
			};
			$.post('/json/search', SG.options, cb, 'json');
		};

		this.init_options = function() {
			var h = document.location.hash;
			if (h !== '' && h!=='#pic') {
				h = h.substr(1).split('&');
				if (h.length>0) {
					SG.options = {};
				}
				for (var i = 0; i < h.length; ++i) {
					var p = h[i].split('=');
					var k = p.shift();
					p = p.join('=');
					var num = parseInt(p, 10);
					if (!isNaN(num) && num+'' == p+'') {
						p = num;
					}
					p = unescape(p);
					if (k == 'upcoming' || k == 'pos') {
						p = parseInt(p, 10);
					}
					SG.options[k] = p;
				}
			}
		};

		this.init_controls = function() {
			if (self.tabs) {
				self.init_tabbar();
			}
			if (self.pagers) {
				self.init_pagers();
			}
			self.fill_header();
		};

		this.init_pagers = function() {
			if (self.ctrl !== null) {
				self.pagers.empty();
			
				self.pagers.each(function(i) {
					if (SG.ctrl.has_prev == 1) {
						$(this).append(
								$('<a>')
								.attr('href', '#')
								.bind('click', function() {
									SG.options.pos = SG.ctrl.prev.pos;
									SG.get_results();
									return false;
								})
								.html('previous '+SG.ctrl.pgsize))
							.append(' ');
					}
					$(this).append(SG.ctrl.rec_from+'-'+SG.ctrl.rec_to+' of '+SG.ctrl.cnt+' results');
					if (SG.ctrl.has_next == 1) {
						$(this).append(' ')
							.append(
								$('<a>')
								.attr('href', '#')
								.bind('click', function() {
									SG.options.pos = SG.ctrl.next.pos;
									SG.get_results();
									return false;
								})
								.html('next '+SG.ctrl.pgsize));
					}
				});
			}
		};

		this.init_tabbar = function() {
			var recent,upcoming;
			SG.tabs.empty();
			recent = $('<li>')
				.append($('<a>')
						.attr('href', '#')
						.html('Recent Shows <span id="search_recent_count"></span>')
						.bind('click', function() {
							SG.options.upcoming = 0;
							recent.addClass('active');
							upcoming.removeClass('active');
							SG.get_results();
							return false;
						}));
			upcoming = $('<li>')
				.append($('<a>')
						.attr('href', '#')
						.html('Upcoming Shows <span id="search_upcoming_count"></span>')
						.bind('click', function() {
							SG.options.upcoming = 1;
							recent.removeClass('active');
							upcoming.addClass('active');
							SG.get_results();
							return false;
						}));
			if (SG.options.upcoming === 1) {
				upcoming.addClass('active');
			} else if (SG.options.upcoming === 0) {
				recent.addClass('active');
			} else {
				upcoming.removeClass('active');
				recent.removeClass('active');
			}
			SG.tabs.append(recent, upcoming);
		};

		this.fill_filters = function() {
			var target = function(n) {
				return SG.filter.find('.filter.'+n);
			};
			var empty = function(t) {
				t.find('.filter_item').remove();
			};
			var labelformatters = {
				'date': function(t) {
					var parts = t.split('-');
					return parts[1]+'/'+parts[0];
				}
			};
			var on = function(n) {
				var t = target(n);
				empty(t);
				var text = SG.options[n];
				if (n in labelformatters) {
					text = labelformatters[n](text);
				}
				t.append($('<div class="filter_item on">')
						.append(text)
						.append(' ')
						.append(
							$('<a>')
							.attr('href', '#')
							.html('x')
							.bind('click', function() {
								SG.options[n] = '';
								off(n);
								SG.get_results();
								return false;
							})));
				t.append($('<div class="filter_item on">').append(
							$('<a>')
							.attr('href', '#')
							.html('change')
							.bind('click', function() {
								make_active(n);
								return false;
							})));

			};
			var off = function(n) {
				var t = target(n);
				empty(t);
				t.append($('<div class="filter_item off">').html('no '+n+' specified'));
				t.append($('<div class="filter_item off">').append(
							$('<a>')
							.attr('href', '#')
							.html('select '+n)
							.bind('click', function() {
								make_active(n);
								return false;
							})));
			};

			var formlings = {
				'artist': function(n) {
					var is_ac_active;
					var i = $('<input type="text">')
					.bind('keydown', function(evt) {
						if (evt.keyCode == 13 || evt.keyCode == 9) { // newline or tab
							var input = this;
							setTimeout(function() { input.blur(); }, 0);
						}
					})
					.bind('blur', function() {
						if (is_ac_active) {
							setTimeout(function() {$(i).blur();}, 0);
							return;
						}
						var input = this;
						setTimeout(function() {
							SG.options[n] = input.value;
							on(n);
							SG.get_results();
							
						}, 0);
					});
					return [i, function() { 
						SG.artistNamesAutocomplete(i, function(state, evt) {
							is_ac_active = state;
						}); 
						i.focus(); 
					}];
				},

				'date': function(n) {
					var format_date = function(y, m) {
						var today = new Date();
						
						y = parseInt(y, 10);
						m = parseInt(m, 10);

						if (isNaN(y)) {
							y = today.getFullYear();
						} /*else if (y < 1900) {
							y += 1900;
						}*/
						if (isNaN(m)) {
							m = today.getMonth()+1;
						}
						return y+'-'+m+'-01';
					};

					var first = $('<select class="month"><option selected /><option value=1>Jan</option><option value=2>Feb</option><option value=3>Mar</option><option value=4>Apr</option><option value=5>May</option><option value=6>Jun</option><option value=7>Jul</option><option value=8>Aug</option><option value=9>Sep</option><option value=10>Oct</option><option value=11>Nov</option><option value=12>Dec</option></select>')
						.bind('change', function() {
							if (second.val() && first.val()) {
								SG.options.date = format_date(second.val(), first.val());
								on(n);
								SG.get_results();
							}
						}).bind('focus', function (e){
							first.has_focus = true;
						})
						.bind('blur', function(e) {
							first.has_focus = false;
						});
						/*first.has_focus = true;*/
					var cur_year = new Date().getFullYear();
					var until = cur_year + 1;
					var second = $('<select class="year">').append('<option/>');
					for (var i = until; i > 1904; i--) {
							second.append('<option>'+i+'</option>'); 
					}
					second.append('</select>')
						.bind('keydown', function(evt) {
							if (evt.keyCode == 13 || evt.keyCode == 9) {
								this.change();
							}
						}).bind('change', function() {
							if (second.val() && first.val()) {
								SG.options.date = format_date(second.val(), first.val());
								on(n);
								SG.get_results();
							}
						}).bind('focus', function (e){
							second.has_focus = true;
						})
						.bind('blur', function(e) {
							second.has_focus = false;
						});
					var one_cb = function(e) {
						setTimeout(function(e){
							if (first.has_focus || second.has_focus) {
								$(window).one('click',one_cb);
							} else {
								SG.get_results();
							}
						},0);
					};
					$(window).one('click',one_cb);

					var f = $('<span>')
						.append(first)
						.append(second);

					return [f, function() { first.focus(); }];
				},
				'venue':function(n) {
					var ac_is_active = false;
					var i = $('<input type="text">').bind('keydown', function(evt) {
							if (evt.keyCode == 13 || evt.keyCode == 9) { // newline or tab
								this.blur();
							}
					}).bind('blur', function() {
						if (ac_is_active) {
							setTimeout(function() { $(i).blur(); }, 0);
							return;
						}
						SG.options[n] = this.value;
						on(n);
						SG.get_results();
					});
					var fn = function(st) {
						ac_is_active = st;
					};
					return [i, function() { SG.venueNamesAutocomplete(i, [i], fn); i.focus(); }];
				},
				'location': function(n) {
					var i = $('<input type="text"><br/><span class="lightgrey">City or zip code</span>')
						.bind('keydown', function(evt) {
							if (evt.keyCode == 13 || evt.keyCode == 9) {
								this.blur();
							}
						})
						.bind('blur', function() {
							SG.options[n] = this.value;
							on(n);
							SG.get_results();
						});
					return [i, function() { i.focus(); }];
				}
			};

			var make_active = function(n) {
				var t = target(n);
				empty(t);
				var formling = formlings[n](n);
				t.append($('<div class="filter_item active">').append(formling[0]));
				formling[1](); // this is the callback we return (does a focus() mostly)
			};

			var crumb = function(n) {
				var text = SG.options[n];
				if (n in labelformatters) {
					text = labelformatters[n](text);
				}

				var i = $('<span class="crumb"></span>')
					.append(text)
					.append(' ')
					.append($('<a>')
							.attr('href', '#')
							.html('x')
							.bind('click', function() {
								SG.options[n] = '';
								off(n);
								SG.get_results();
								return false;
							}));
			
				SG.crumbs.append(i).append(' ');
			};
			
			var filters = ['artist', 'date', 'venue', 'location'];

			SG.crumbs.empty().append('<span class="title">Results for:</span> ');

			for (var i = 0; i < filters.length; ++i) {
				if (filters[i] in SG.options && SG.options[ filters[i] ] !== '') {
					on(filters[i]);
					crumb(filters[i]);
				} else {
					off(filters[i]);
				}
			}
		};

		this.fill_loading = function() {
			self.append($('<div class="spinning-loader" style="position: fixed; left:50%; top:50%;"><img src="/static/sg/img/loading.gif"></div>'));
		};

		this.fill_header = function() {
			self.frame.find('div.header').empty();
			var add = function(cl, t) {
				self.frame.find('div.header').append(
						$('<div class="unit table_col">')
						.addClass(cl)
						.append($('<h4>').html(t)));
			};

			add('date', 'Date');
			add('artist', 'Artist');
			add('venue', 'Venue');
			if (SG.options.upcoming === 0) {
				add('recaps', 'Recaps');
			}
			add('action', (SG.options.upcoming === 0 ? 'Who Was There' : 'Who\'s Going'));
		};

		this.cell = function(cl) {
			return $('<div>')
				.addClass('unit table_col')
				.addClass(cl);
		};

		this.create_artist = function(e) {
			var t_headliner_pic = 'artist' in e && e.artist.length > 0 && e.artist[0].artist_picture_url
				? e.artist[0].artist_picture_url
				: '/static/sg/img/missing/micro.jpg';

			var c = self.cell('artist');
			var names = $('<div></div>')
					.addClass('unit size4of5 lastUnit')
					.append($('<h2></h2>')
						.append($('<span class="mainact"></span>')
							.append($('<a class="primary_link"></a>')
								.attr('href', '/show/index/'+e.show_id)
								.html(e.artist[0].artist_name))));
			if ('artist' in e) {
				names.append('<br/>');
				if (e.artist.length>1) {
					for (var i = 1; i < e.artist.length; ++i) {
						if (i>2) {
							continue;
						}
						names.append(e.artist[i].artist_name + '<br/>');
					}
				}
			}
			var headline = $('<div>')
				.addClass('show_headline')
				.append($('<div>')
						.addClass('unit')
						.append($('<a>')
							.attr('href', '/show/index/'+e.show_id)
							.append($('<img>')
								.addClass('showimage')
								.attr('src', t_headliner_pic))))
				.append(names);
			c.append(headline);

			return c;
		};
		
		this.create_venue = function(e) {
			var c = self.cell('venue');
			if ('venue' in e && e.venue.length > 0) {
				var a = $('<a class="name"></a>')
					.attr('href', '/venue/index/'+e.venue[0].venue_id)
					.html(e.venue[0].venue_name);

				var loc = $('<div class="location"></div>')
					.append(e.venue[0].venue_city+' '+e.venue[0].venue_state);

				c.append(a, loc);
			}
			return c;
		};
		
		this.create_date = function(e) {
			var c = self.cell('date');
			c.append($('<span class="tx-small"></span>')
								.html(e.date_formatted));
			return c;
		};

		this.create_recaps = function(e) {
			var c = self.cell('recaps');
			var s = e.stats;
			if ('story' in s && s.story > 0
					|| 'photo' in s && s.photo > 0
					|| 'video' in s && s.video > 0)
			{
				var add = function(cl, t) {
					c.append($('<a class="recap_icon"></a>')
							.addClass('icon_'+cl)
							.attr('href', '/show/index/'+e.show_id+'/'+cl)
							.html(t));
				};
				if ('story' in s) {
					add('stories', 0+s.story);
				}
				if ('photo' in s) {
					add('photos', 0+s.photo);
				}
				if ('video' in s) {
					add('videos', 0+s.video);
				}
			} else {
				c.append($('<a>').attr('href', '/show/index/'+e.show_id).html('Add Recap'));
			}
			return c;
		};
		
		this.create_button = function(t, cl) {
			var b = $('<button></button>')
				.html(t);
			return $('<div class="UIButton"></div>')
				.addClass(cl)
				.append(b);
		};

		this.create_action = function(e) {
			var c = self.cell('action');

			var user = 'attend' in e && ('user' in e.attend) && e.attend.user == 1;

			if (user) {
				var s = $('<div class="attendance set">').html(e.future ? '(You are going!)' : '(You were there!)');
				c.append(s);
			} else {
				
				var b = self.create_button(
						(e.future ? 'I\'m going!' : 'I was there!' ),
						'pink');
					if(SG.logged_in) {		
						b = b.bind('click', function() {
							var set = function() {
								SG.get_results();
							};
							$.get('/show/attend/'+e.show_id, {}, set);
							return false;
						});
					} else {
						b.bind('click',function() {
											var jumpto = "/searchlogin/"+SG.get_url();
											document.location = jumpto;
											return false;
										});
					}
				c.append(b);
			}
			return c;
		};
		
		this.create_entry = function(e) {
			var datefield = self.create_date(e);
			var artist = self.create_artist(e);
			var venue = self.create_venue(e);
			var action = self.create_action(e);
			var recaps = null;
			
			if (SG.options.upcoming === 0) {
				recaps = self.create_recaps(e);
			}
			var wrap = $('<div>')
				.addClass('line row row_link');
			wrap.append(datefield, artist, venue);
			if (recaps) {
				wrap.append(recaps);
			}
			wrap.append(action);
			return wrap;
		};
		
		this.get_url = function() {
			var url = [];
			for (var i in SG.options) {
				if (SG.options[i] !== '') {
					url.push(i+'='+SG.options[i]);
				}
			}
			return url.join('&');
		};

		this.fix_url = function() {
			document.location.hash = '#'+this.get_url();
		};

		this.fill_results = function(r) {
			var i;
			self.empty();
			SG.options = r.crit;
			SG.options.pos = r.ctrl.pos;
			for (i in SG.options) {
				var n = parseInt(SG.options[i], 10);
				if (!isNaN(n) && n+'' == SG.options[i]+'') {
					SG.options[i] = n;
				}
			}
			self.ctrl = r.ctrl;
			self.fix_url();
			self.fill_breadcrumbs();
			self.init_pagers();
			if(r.results.length === 0) {
				self.fill_empty();	
			} else {
				for (i = 0; i < r.results.length; ++i) {
					var e = self.create_entry(r.results[i]);
					self.append(e);
				}
				SG.initRowLinks();
			}

			var ocb = function(r, st) {
				if (st == 'success' && r.error === '') {
					if (r.oppositecount !== undefined) {
						$('#search_'+(r.crit.upcoming == 1 ? 'upcoming' : 'recent')+'_count').html('');
						$('#search_'+(r.crit.upcoming == 1 ? 'recent' : 'upcoming')+'_count').html('('+r.oppositecount+')');
					}
				}
			};
			
			$('#search_'+(r.crit.upcoming == 1 ? 'recent' : 'upcoming')+'_count').html('');
			$.post('/json/search-oppositecount', SG.options, ocb, 'json');

		};
		
		this.fill_empty = function() {
			var innertext = self.crumbs.clone().find('.crumb').each(
				function (e) {
					$(this).find('a').remove(); 
					$(this).text($.trim($(this).text()));
					if(e) {
						$(this).text(', '+$(this).text() );
					}
				}
			);
			$('#search_wrap').empty();
			$('#search_wrap').append($('<div class="row">')
			.append('Sorry. We were not able to find any matches for "')
			.append(innertext)
			.append('". Try another search or add a show to our archive. ')
			);
		};
			
		this.fill_breadcrumbs = function() {
			var a = $('<span>');
			if (SG.options.upcoming == 1) {
				a.html('Upcoming Shows');
			} else {
				a.html('Recent Shows');
			}

			self.top_breadcrumb.empty().append(a);
		};

		this.fill_error = function(st, e) {
			self.empty();
			self.append(st + ' ' + e);
		};
		
		this.init_options();
		this.init_controls();
		this.get_results();
	};

	this.popupIframe = function(src, title, w, h) {
		w = w || 400;
		h = h || 400;
		SG.ensure_loaded('js', '/static/sg/js/greybox.js');
		SG.ensure_loaded('css', '/static/sg/css/greybox.css');
		GB_show(title, { type: 'iframe', src: src }, w, h);
	};

	this.promptDelete = function(url, title) {
		var content = '<h1>'+title+'</h1>';
		content += '<form method="get" action="'+url+'">';
		content += '<div class="UIButton_pink"><button type="submit">Yes</button></div>';
		content += '<div class="UIButton_grey"><button onclick="GB_hide(); return false;">No</button></div>';
		content += '</form>';
		GB_show(title, content, 200, 400);
	};

	this.hideStateWorldwide = function(countryid, stateid,hide) {
		var state = $('#'+stateid);
		var country = $('#'+countryid);

		if (country.val() == SG.COUNTRY_ID_USA) {
			state.attr('disabled', false);
			if(hide) {
				state.parent().parent().show();
			}
		} else {
			state.attr('disabled', true);
			if(hide) {
				state.parent().parent().hide();
			}
		}
		country.change(function () {
			if (country.val() == SG.COUNTRY_ID_USA) {
				state.attr('disabled', false);
				if(hide) {
					state.parent().parent().show();
				}
			} else {
				state.attr('disabled', true);
				if(hide) {
					state.parent().parent().hide();
				}
			}
		});
			
	};

	this.NartistsFields = 4;
	this.moreArtistFields = function(targetdiv) {
		var t = $('#'+targetdiv).get(0);
		if (!t) {
			return;
		}
		var n = document.createElement('input');
		n.type = 'text';
		n.name = 'artists[]';
		n.id = 'artists'+SG.NartistsFields;
		SG.NartistsFields++;
		t.appendChild(n);

		var div = document.createElement('div');
		div.id = n.id+'_results';
		t.appendChild(div);

		//var br = document.createElement('br');
		//t.appendChild(br);

		SG.artistNamesAutocomplete(n.id);
	};

	this.initStatusBar = function() {
		var sb = $('#status_bar').get(0);
		if (sb) {
			$(sb).css({display:"block"}).vkfade('FFFFFF');
		}
	};

	this.jquery_is_a_dead_walrus_is_hidden = function(elt) {
		return $(elt).css('display') == 'none';
	};

	this.jquery_is_a_dead_walrus_showhide = function(elt, bool) {
		if (bool) {
			$(elt).css({display: 'none'});
		} else {
			$(elt).css({display: 'block'});
		}
	};

	this.jquery_is_a_dead_walrus_toggle = function(elt) {
		if (SG.jquery_is_a_dead_walrus_is_hidden(elt)) {
			SG.jquery_is_a_dead_walrus_showhide(elt, false);
		} else {
			SG.jquery_is_a_dead_walrus_showhide(elt, true);
		}
	};

	this.toggleShowMainPane = function() {
		SG.jquery_is_a_dead_walrus_toggle($('#show_main_expanded'));
		SG.jquery_is_a_dead_walrus_toggle($('#show_main_collapsed'));
	};
	this.toggleUserMainPane = function() {
		SG.jquery_is_a_dead_walrus_toggle($('#user_main_expanded'));
		SG.jquery_is_a_dead_walrus_toggle($('#user_main_collapsed'));
	};
	this.toggleArtistMainPane = function() {
		SG.jquery_is_a_dead_walrus_toggle($('#artist_main_expanded'));
		SG.jquery_is_a_dead_walrus_toggle($('#artist_main_collapsed'));
	};

	this.ratingFormSubmit = function(type, id, link, extra_on_success) {
		var f = '#rating-form-'+type+'-'+id;

		if ($(link.childNodes[0]).attr('addedsrc')) {
			$(link.childNodes[0]).attr('src',$(link.childNodes[0]).attr('addedsrc'));
			$(link.childNodes[0]).get(0).onmouseout = null;
			$(link.childNodes[0]).get(0).onmouseover = null;
		}

		this.ajax_submit_form(f, function(data) { 
				var wrap_span = $(link).closest('span.thumbsup_reload');
				wrap_span.replaceWith(data);
				if (extra_on_success) {
					extra_on_success(data);
				}
			},
			function(x){if(x.status==401){SG.gallery.anchor(); window.location='/user';}}
		);
	};
	
	this.initTextAreas = function() {
		var tas;
		var i;
		tas = $('.counter_limited');
		for (i = 0; i < tas.length; ++i) {
			$(tas[i]).charCounter(140);
		}
		
		tas = $('.counter_limited_recap');
		for (i = 0; i < tas.length; ++i) {
			$(tas[i]).charCounter(20000, {container: "<span style='display:none;'></span>"});
		}
		
		tas = $('.expandable');
		for (i = 0; i < tas.length; ++i) {
			$(tas[i]).autogrow({maxHeight: 800, minHeight: 50});
		}
	};
	
	
			
	this.toggleSimpleRecap = function(link) {
		var box = $(link).find('div.add_recap');
		if (!box.length) {
			return;
		}
		box = box.get(0);

		if ($(box).hasClass('hidden')) {
			$(box).removeClass('hidden');
		} else {
			$(box).addClass('hidden');
		}
	};

	this.mergeField = function(id) {
		var div = document.getElementById('merge-'+id);
		var inputs = $(div).find('.merge').get();

		var ilen = inputs.length;

		if (ilen & 1) {
			return;
		}

		var ofs = ilen / 2;

		for (var i = 0; i < ofs; ++i) {
			inputs[i].value = inputs[i+ofs].value;
		}
	};
	
	this.scrollToPicture = function(id) {
		var picture = document.getElementById('photo_full_'+id);
		if (picture) {
			$.scrollTo(picture.parentNode.parentNode.parentNode);
		} else {
			if (!window.location.pathname.match(/^\/(artist|venue)\/index\/\d+(-[^\/]*)?\/photos/)) {
				var m = window.location.pathname.match(/^\/(artist|venue)\/index\/(\d+(-[^\/]*)?)/);
				if (m) {
					window.location = '/'+m[1]+'/index/'+m[2]+'/photos?jump='+id;
				}
			} else {
				window.location.search = '?jump='+id;
			}
		}
	};
	
	this.toggleVideo = function(element, video_id, nostop, onload_run) {
		if(!onload_run) {
			var vid = document.getElementById('video_player_'+video_id+'_noautoplay');
			if (vid) {
				$.scrollTo(vid.parentNode.parentNode);
			} else {
				if (!window.location.pathname.match(/^\/(artist|venue)\/index\/\d+(-[^\/]*)?\/videos/)) {
					var m = window.location.pathname.match(/^\/(artist|venue)\/index\/(\d+(-[^\/]*)?)/);
					if (m) {
						window.location = '/'+m[1]+'/index/'+m[2]+'/videos?jump='+video_id;
					}
				} else {
					window.location.search = '?jump='+video_id;
				}
				return false;
			}
		}
		
		var div = document.getElementById('video_player_'+video_id);
		var firstplayer = document.getElementById('video_player_'+video_id+'_noautoplay');
		var recap = document.getElementById('video_recap_'+video_id);
		if (firstplayer) {
			// nothing
		} 
		else if (div) 
		{
			if (!nostop) {
				div.parentNode.removeChild(div);
				element.childNodes[0].src = '/static/sg/img/icons/video_play.gif';
				if (recap) {
					recap.childNodes[0].src = '/static/sg/img/icons/video_play.gif';
				}
			}
		} 
		else 
		{
			div = document.createElement('div');
			div.id = 'video_player_'+video_id;
			div.className = 'video_player';
			element.parentNode.insertBefore(div, element.nextSibling);
			element.childNodes[0].src = '/static/sg/img/icons/video_play.gif';

			if (recap) {
				recap.childNodes[0].src = '/static/sg/img/icons/video_play.gif';
			}

			element.style.display = 'none';
			$(div).load('/video/'+video_id);
		}
	};

	this.addComment = function(item_id) {
		this.cancelComment();
		$('#add_comment_'+item_id).css({display: 'block'});
		$('#add_comment_'+item_id+ ' textarea').autogrow({maxHeight: 800, minHeight: 50});
	};

	this.submitComment = function(item_id, post_comment_button) {
		$(post_comment_button).html('Posting...');
		$(post_comment_button).unbind('click');
		$(post_comment_button).attr('onclick', '');
		$(post_comment_button).bind('click', function(){return false;});
		$(post_comment_button).attr('href', '#');

		this.ajax_submit_form('#add_comment_form_'+item_id, 
			function() { 
//				SG.make_message_box_fixed();
				if (SG.gallery.inited) {
					SG.gallery.flip({});
					SG.add_message('Your comment has been posted',1);
				}
				else {
					window.location = window.location;
					SG.add_message('Your comment has been posted',1);
				}
				$('#add_comment_'+item_id).css({display: 'none'});
			},
			function(x) {
				if (x.status==401){SG.gallery.anchor(); window.location='/user';} 
			}
		);
	};	

	this.cancelComment = function() {
		var cmt = $('div.adding_comment').get();
		for (var i = 0; i < cmt.length; ++i) {
			cmt[i].style.display = 'none';
		}
	};

	this.festivalNamesAutocomplete = function(htmlid) {
		htmlid = SG.htmlid_or_domnode(htmlid);
		var ac = $(htmlid).autocomplete('/json/festival', {matchContains:1});

	};
	this.featureNamesAutocomplete = function(htmlid) {
		htmlid = SG.htmlid_or_domnode(htmlid);
		var ac = $(htmlid).autocomplete('/json/feature', {matchContains:1});

	};

	this.artistNamesAutocomplete = function (htmlid, callback, blurcb) {
		htmlid = SG.htmlid_or_domnode(htmlid);
		var opts = {
			matchContains: 1,
			track_activity_callback: callback
		};
		if (blurcb !== undefined) {
			opts.onInputBlur = blurcb;
		}
		var ac = $(htmlid).autocomplete('/json/artists', opts);

	};

	this.countryNamesAutocomplete = function(htmlid) {
		htmlid = SG.htmlid_or_domnode(htmlid);
		var ac = $(htmlid).autocomplete('/json/countries', {
			matchContains: 1
		});
	};
	this.stateNamesAutocomplete = function(htmlid) {
		htmlid = SG.htmlid_or_domnode(htmlid);
		var ac = $(htmlid).autocomplete('/json/states', {
			matchContains: 1,
			extraParams: {
				country: function() {
					var a = $('#country').val();
					if (a == 'Country') {
						a = '';
					}
					return a;
				}
			}
		});
	};

	this.venueNamesAutocomplete = function (htmlid, fill_ids, cb, fill_default_labels) {
		htmlid = SG.htmlid_or_domnode(htmlid);
		fill_default_labels = fill_default_labels === undefined ? [] : fill_default_labels;

		var opts = {
			width: 350,
			formatItem: function(item, i, n) {
				var t = item[0];
				var city = jQuery.trim(item[1]);
				var state = item[2];
				var countryId = parseInt(item[3].split('-')[0]);
				var countryName = jQuery.trim(item[3].split('-')[1]);

				if (city) {
					t += ' (' + city;
					if (countryId===SG.COUNTRY_ID_USA) { // usa
						if (state) {
							t += ', ' + state;
						}
					} else if(countryName) {
						t += ', ' + countryName;
					}
					t += ')';
				}
				return t;
			},
			onItemSelect: function(item) {
				var extra = item.extra;
				var name = item.selectValue;
				var l = fill_ids.length;
				for (var i = 0; i < l; ++i) {
					if (fill_ids[i] == 'country') {
						var parts = extra[i].split('-');
						parts.shift();
						extra[i] = parts.join('-');
					}
					$(SG.htmlid_or_domnode(fill_ids[i])).val(extra[i]).removeClass('default');
				}
			},
			onInputBlur: function(is_value_from_select) {
				var e = $('#venue_form_rest');
				if (e) {
					if (is_value_from_select) {
						e.hide();
					} else {
						for (var i = 0; i < fill_ids.length; ++i) {
							//$(SG.htmlid_or_domnode(fill_ids[i])).val(
							//	fill_default_labels.length > i ? fill_default_labels[i] : ''
							//).addClass('default');
						}
						e.show();
					}
				}
			}

		};
		if (cb !== undefined) {
			opts.track_activity_callback = cb;
		}
		var ac = $(htmlid).autocomplete('/json/venues', opts);

	};

	this.cloneElementIntoParent=function(element){
		/*
			 Used in forms that allow users to add fields indefinitely, e.g. when listing the artists involved in a show. The duplicated element will have an incremented ID if the original element has one of the format "some_id_0".
		*/

		element= $('#'+element).get(0);
		var new_element=element.cloneNode(true);
		var old_id=element.id;
		var old_int=old_id.match('([0-9]{1,})')[0];
		var new_int=parseInt(old_int,10)+1;
		new_element.id=(old_id.replace(old_int, ''))+''+new_int;
		element.parentNode.appendChild(new_element);
		return false;
	};

	this.editSetlistItem=function(element){
		/* Used on the Setlist Editor page. This function makes a field editable, changes its appearance, and selects its current text. */

		$(element).addClass('editing');
		var inputs=element.getElementsByTagName('input');
		$(inputs[0]).bind('blur', function(){SG.finishRenamingSetlistItem(this.parentNode);});

		var finishEditing=function(){SG.finishRenamingSetlistItem(element);return false;};

		$(inputs[0]).bind('keydown', function(event){
			
		});


		inputs[0].readOnly=false;
		inputs[0].select();
		$('input').keydown(function(event){
			if(event.keyCode==13) {	
				var inputs=element.getElementsByTagName('input');
				$(element).removeClass('editing');
				inputs[0].readOnly=true;
				return false;
			}
		});
	};

	this.finishRenamingSetlistItem=function(element){
		/* To be called when a user, while editing an item, hits "enter" or focuses on any other DOM element. Makes field read-only. */

		var inputs=element.getElementsByTagName('input');
		$(element).removeClass('editing');
		inputs[0].readOnly=true;
	};

//	this.activateSortableSetlistItem=function(element){
//		/* Activates a YUI draggable object for an individual list item */
//		var this_dd = new YAHOO.example.DDList(element, "setlist_"+element.parentNode.id, {dragElId:'setlist_item_proxy'});
//		this_dd.on('startDragEvent', function(ev) { SG.finishRenamingSetlistItem(element); }, this_dd, true);
//	};

	this.deleteSetlistItem=function(element, confirmed){
		/* Asks for confirmation, then deletes a list item from the DOM */
		if(!confirmed){
			if(confirm("Delete this song?")){
				SG.deleteSetlistItem(element, true);
			}
			return;
		}

		element.parentNode.removeChild(element);

	};

	this.addSetlistItem=function(element, artist_id){
		/* Creates a new DOM element in the list, then calls the list item activation function to create a YUI draggable object */
		var artist = 'setlist['+artist_id+'][]';
		element = $('#'+element).get(0);
		var new_node= $('#example_list_item').get(0).cloneNode(true);
		var input=new_node.getElementsByTagName('input')[0];
		$(new_node).removeClass('hidden');

		var i=0;
		while(document.getElementById('item_'+artist_id+'_'+i)){
			i++;
		}

		new_node.id='item_'+artist_id+'_'+i;

		input.name=artist;
		input.value="Enter song title here";
		$(input).keydown(function(event){return event.keyCode!=13;});
		element.appendChild(new_node);
//		SG.activateSortableSetlistItem(new_node);
		SG.editSetlistItem(new_node);
	};

	/*
		setElementCSSVar, getElementCSSVar, and removeElementCSSVar are used for easy manipulation of data-holding and/or styling-indicative CSS classes. Variables are in the format "key_value". If setElementCSSVar is called on an element which currently has no corresponding class name, one will be created.

		 -- Usage Example --

		Beginning DOM element:
		<div id="test"></div>

		Executed JS:
		SG.setElementCSSVar('test', 'section', '5');

		Resulting DOM element:
		<div id="test" class="section_5"></div>
	*/

	this.removeElementCSSVar=function(element, varname){
		if (typeof(element) == 'string') {
			element = '#'+element;
		}
		var e = $(element).get(0);
		var is_true = e.className.match(varname);
		var vals = e.className.match(new RegExp(varname+"_([a-zA-Z0-9_-]{1,})"));
		if(vals && vals[0]) {
			$(e).removeClass(vals[0]);
		}
	};

	this.getElementCSSVar=function(element, varname){
		if (typeof(element) == 'string') {
			element = '#'+element;
		}
		var e = $(element).get(0);
		var is_true = e.className.match(varname);

		var vals = e.className.match(new RegExp(varname+"_([a-zA-Z0-9_-]{1,})"));

		return ((vals && vals.length) ? vals[1] : (is_true ? true : false));
	};

	this.setElementCSSVar=function(element, varname, newval){
		if (typeof(element) == 'string') {
			element = '#'+element;
		}
		var e = $(element).get(0);
		var is_true = e.className.match(varname);

		var vals = e.className.match(new RegExp("(^| )"+varname+"_([a-zA-Z0-9_-]{1,})"));
		if(vals && vals[2]){
			$(e).removeClass(varname+'_'+vals[2]);
		}
		$(e).addClass(varname+'_'+newval);
	};


	this.initRowLinks=function(root){
		/*

			When data is presented in tabular format, we want the user to be able to click anywhere within the row in order to visit the page represented by the row. The only exception is when the user clicks on an <a> tag within the row, which should have its own destination or JS.

			In order to do this we give all such rows a class of "row_link" and give the link which leads to the row's corresponding page a class of "primary_link". On page load, SG.initRowLinks searches for all such rows and attaches onClick events to them.

		*/

		if (!root) {
			root = document;
		}

		var row_link_nodes = $(root).find('.row_link');

		for (var i = 0; i < row_link_nodes.length; i++) {
			if ($(row_link_nodes.get(i)).hasClass('inited')) {
				continue; 
			}

			var primary_links = $(row_link_nodes.get(i)).find('a.primary_link');
			if (!primary_links.length) {
				continue;
			}

			var link = primary_links.get(0).href;
			var go_to_link = (function(link) {
				return function(e) {
					if (e.target.tagName != "A" && e.target.tagName != "a") {
						location.href=link;
					}
				};
			})(link);

			$(row_link_nodes.get(i)).bind('click', go_to_link);
			$(row_link_nodes.get(i)).bind('mouseover', function(){
					$(this).addClass('row_link_hovered');
			});
			$(row_link_nodes.get(i)).bind('mouseout', function(){
					$(this).removeClass('row_link_hovered');
			});
			$(row_link_nodes.get(i)).addClass('inited');
		}
	};


	this.starRating=function(star_rating_node){

		/* An SG.starRating object is created for each star rating on the page. Each star rating object starts out with a <form> element containing a hidden field, "rating", the value of which is set when the user selects a star rating via mouseclick. */

		var self=this;

		$(star_rating_node).addClass('inited');

		var this_form = $(star_rating_node).find('form');
		this.form = this_form.get(0);

		var default_stars = $(star_rating_node).find('.pink');
		this.default_stars = default_stars.get(0);

		var stars = $(star_rating_node).find('a.gold');
		if (!stars.length) {
			return;
		}
		this.stars = stars.get(0);
		this.hovering = false;

		var do_hover=function(e){
			var stars_width = this.offsetWidth;
			var hover_h = e.clientX - $(this).offset().left;

			var fifth;

			for(var i=5;i>=0;i--){
				if(hover_h>((stars_width/5)*i)){
					fifth=i+1;
					break;
				}
			}

			SG.setElementCSSVar(this, "hoveredrating", fifth);
			var new_avg_rating=SG.getElementCSSVar(self.default_stars,"avgrating")?SG.getElementCSSVar(self.default_stars,"avgrating"):SG.getElementCSSVar(self.default_stars, "rating");
			SG.setElementCSSVar(self.default_stars, "avgrating", new_avg_rating);
			SG.setElementCSSVar(self.default_stars, "rating", "0");

		};

		var stop_hover=function(e){
			self.hovering = false;
			$(self.stars).unbind('mousemove');
			SG.removeElementCSSVar(this, "hoveredrating");
			if(!SG.getElementCSSVar(this, "rating")){
				SG.setElementCSSVar(self.default_stars, "rating", SG.getElementCSSVar(self.default_stars,"avgrating")?SG.getElementCSSVar(self.default_stars,"avgrating"):SG.getElementCSSVar(self.default_stars, "rating"));
			}
		};

		var start_hover = function(e) {
			if (self.hovering) {
				return;
			}
			self.hovering = true;
			$(self.stars).bind('mousemove', do_hover);
			$(self.stars).bind('mouseleave', stop_hover);
		};

		var do_rate=function(e){
			var new_rating=SG.getElementCSSVar(this, "hoveredrating");
			SG.setElementCSSVar(this, "rating", new_rating);
			self.form.rating.value=new_rating;
			self.form.submit();
		};

		$(this.stars).bind('click', do_rate);
		$(this.stars).bind('mouseenter', start_hover);

	};

	this.initStarRatings=function(root){
		/* Finds all star rating elements on the page and creates corresponding JS objects, YUI listeners, etc. */
		if(!root) {
			root=document;
		}
		var star_rating_nodes = $(root).find('.rating_widget');
		for(var i=0;i<star_rating_nodes.length;i++){
			if ($(star_rating_nodes.get(i)).hasClass('inited')) { continue; }
			var temp = new SG.starRating(star_rating_nodes.get(i));
		}
	};

	this.showHiddenSetlists = function() {
		var lists = $('#artist_show_setlist').find('div.list').get();
		for (var i = 0; i < lists.length; ++i) {
			$(lists[i]).removeClass('hidden');
		}

		var see_all = $('#artist_show_setlist').find('a.see_all');
		see_all.removeClass('see_all');
		see_all.addClass('hidden');
	};

	this.initExpandedVideos = function () {
		// video_expanded
		var div = $('.video_expanded').get(0);
		if (div && div.id.split('_')[2]) {
			var vid = div.id.split('_')[2]+'_noautoplay';
			SG.toggleVideo(div,vid,0,1);
		}
	};

	this.fix_image = function(img) {
		img = $(img);
		var o_w = img.width(),
			o_h = img.height(),
			box = img.parent('div.image');
		if (!box) {
			return;
		}
		var t_w = box.width(),
			t_h = box.height();

		if (o_w > t_w || o_h > t_h) {
			if (o_w/t_w > o_h/t_h) {
				img.width(t_w);
			}
			else {
				img.width(t_h);
			}
		}
	};
};
SG.swipe = {};
SG.swipe.leftfn = null;
SG.swipe.rightfn = null;

SG.swipe.mousedown = function(e) {
	SG.swipe.x = e.clientX;
	return false;
};
SG.swipe.mouseup = function(e){
	if (SG.swipe.x!==null) {
		var diff = SG.swipe.x - e.clientX;
		if (diff>10) {
			// right
			SG.swipe.rightfn();
			SG.swipe.rightfn = null;
		} else if (diff<-10) {
			// left
			SG.swipe.leftfn();
			SG.swipe.leftfn = null;
		}
		SG.swipe.x = null;
	}
};
SG.swipe.init = function (jqelts,swleftfn,swrightfn) {
	SG.swipe.leftfn = swleftfn;
	SG.swipe.rightfn = swrightfn;
	SG.swipe.x = null;
	jqelts.select(function(){return false;});
	jqelts.mousedown(SG.swipe.mousedown);
	jqelts.mouseup(SG.swipe.mouseup);
};

$(document).ready(function() {
	if (!window.console) {
		window.console = {};
		window.console.log = function() {};
	}
	
	SG.initTextAreas();
	SG.initExpandedVideos();
	
	var nodes = $('input.text, input.text_big, textarea');
	function handleFocus() {
		if (!$(this).hasClass('default')) { return; }
		$(this).removeClass('default');
		$(this).addClass('wasdefault');
		this.last_value = this.value;
		this.value = '';
	}

	function handleBlur() {
		if (!$(this).hasClass('wasdefault')) { return; }
		if (!this.value || this.value == this.defaultValue) {
			$(this).addClass('default');
			this.value = this.last_value;
		}
	}

	$(nodes).bind('focus', handleFocus);
	$(nodes).bind('blur', handleBlur);
	
	for (var i = 0; i < nodes.length; ++i) {
		nodes[i].defaultValue = nodes[i].value;
	}

	nodes = $('form');
	function handleInputDefaultValuesOnSubmit() {
		var els = this.getElementsByTagName('textarea');
		for (var i = 0; i < els.length; ++i) {
			if (!$(els[i]).hasClass('default')) { continue; }
			if (els[i].defaultValue && els[i].defaultValue !== '' && els[i].value == els[i].defaultValue) {
				els[i].value = '';
			}
		}
		els = this.getElementsByTagName('input');
		for (i = 0; i < els.length; ++i) {
			if (!$(els[i]).hasClass('default')) { continue; }
			if (els[i].type == 'text' && els[i].defaultValue && els[i].defaultValue !== '' && els[i].value == els[i].defaultValue) {
				els[i].value = '';
			}
		}
	}

	$(nodes).bind('submit', handleInputDefaultValuesOnSubmit);


	SG.initRowLinks();
	SG.initStarRatings();
});


