$(function(){

  // search box
  $('#search_submit').hide();  
  $('#search_text').css('background-position','0 -50px').focus(function(){
		$(this).css('background-position','0 -100px');
	  }).blur(function(){
		if($(this).val()==''){
			$(this).css('background-position','0 -50px');
		}
  }).keyup(function(event){
    /*
  	// 13 = enter
  	//  8 = backspace
  	// 32 = space
  	// 46 = delete
  	// 48 = (start of actual characters)
  	*/
  	if (!(event.keyCode >= '48' || event.keyCode == '13' || event.keyCode == '8' || event.keyCode == '46' || event.keyCode == '32')) return true;
  	
		clearTimeout(window.searchTimer);
	
		if ($('#search_text').val() == ''){
			$('#search_results').hide();
			$('#sidebar').show();
			return true;			
		};
					
		$('#search').submit(function(){return false})
		if(event.keyCode == '13'){ // on enter
			doSearch(20) // run the search 
			return false // and prevent the form from submitting
		}
		window.searchTimer = setTimeout('doSearch(20)',750)
  });


  // make the top trip slide down
  $('#sidebar ul.options li .directions').hide(function(){
    $(this).parents('ul').eq(0).find('li:first .directions').eq(0).slideDown('medium')
  })

  // trip planner accordion
  $('#sidebar ul.options li h3').click(function(){
    if ( $(this).siblings('div').is(':visible') ){return false}
    $(this).parents('ul').find('li .directions:visible').slideUp('medium')
    $(this).siblings('.directions').slideDown('medium')
  }).css({cursor:'pointer'})
  

	// flashes
	$('#flash .flashmsg').not('#iesucks').hide()
	setTimeout(function(){
  	$('.flashmsg.error').slideDown('slow')
		$('.flashmsg.notice').slideDown('slow').each(function(){
		  el = $(this)
		  setTimeout(function(){
		    el.slideUp('slow')
		  },4000+(el.text().length*100))
		})
	},500)


	// hide helpful messages
	$('#login_box, #trip_planner, .directions, #feedback')
	.find('.notice p').hide().end()
	.find('.notice h3').click(function(){
	  $(this).parent().find('p').toggle('fast');
	}).attr('title','Click here for more info')

  $('#feedback textarea')
  .css('overflow','hidden')
  .css('height','50px')
  .focus(function(){
    lh = parseInt($(this).css('line-height'))
    len = $(this).val().match(/((?:.){32}|\n)/ig)
    if (len == null) {len = []}
    nh = (1.5 + len.length) * lh
    $(this).height(nh < 50 ? 50 : nh)
  })
  .keyup(function(){
    lh = parseInt($(this).css('line-height'))
    len = $(this).val().match(/((?:.){32}|\n)/ig)
    if (len == null) {len = []}
    nh = (1.5 + len.length) * lh
    $(this).height(nh < 50 ? 50 : nh)
  })



  //
  // SIGNUP FORM STUFF
  //
  
  // enter in password box submits form
  $('#login_box input[name=password], #login_box input[name=email]').keyup(function(event){
    if(event.keyCode == '13'){
      $('.buttons [value="Log In"]').click();
    }
    return false;
  })

  // create login / signup button sets
  $('.buttons [value="Log In"]').wrap('<div class="loginButtons"/>').parent().prepend(' or ').prepend(
    $('<a href="/sign_up">Sign Up</a>').click(function(){
      $('.signupOnly').parent().show('fast',function(){
        $('#login_box input[value=]').eq(0).focus() // focus the first blank input
      })
      $('.signupButtons').show()
      $('.signupButtons input').removeAttr('disabled')
      $('.loginButtons input').attr('disabled','disabled')
      $('.loginButtons').hide()
      return false
    })
  )
  $('.buttons [value="Sign Up"]').attr('disabled','disabled').wrap('<div class="signupButtons"/>').parent().append(' or ').append(
    $('<a href="/log_in">Log in</a>').click(function(){
      $('.signupOnly').parent().hide('fast',function(){
        $('#login_box input[value=]').eq(0).focus() // focus the first blank input
      })
      $('.signupButtons input').attr('disabled','disabled')
      $('.signupButtons').hide()
      $('.loginButtons').show()
      $('.loginButtons input').removeAttr('disabled')
      return false
    })
  ).hide()
  
  $('.signupOnly').parent().hide()
  $('.buttons').css('fontSize','.7em')




  
  if ($("img.map").length > 0)
  {
    $("#sidebar img.map").after("<p id='makemapinterface_note' style='width:350px;font-size:.7em;text-align:right;margin:.5em 10px 0 10px;'><a href='#' onClick='makeMapInteractive();return false'>switch to interactive map</a></p>");
    $("#article img.map").after("<p id='makemapinterface_note' style='width:610px;font-size:.7em;text-align:right;margin:.5em 10px 1em 10px;'><a href='#' onClick='makeMapInteractive();return false'>switch to interactive map</a></p>");
  }


  // attach the trip planner link sexiness to the station and stop views
  $('#sidebar a[href^=/travel/]').click(function(){
    noun_name = $(this).attr('href').match(/([\w\d-_]*)\/?$/i)[1].replace(/_/g,' ').toProperCase()
    to_from = $(this).attr('href').match(/travel\/(to|from)\/.*$/i)[1]
    $('#trip_planner')
      .find('input[name=to], input[name=from]').val('').end()
      .find('input[name=when]').val('now').end()
      .find('input[name='+to_from+']').val(noun_name).end()
      .show()
      .find('input[type=submit]').get(0).focus()
    $('#trip_planner input[value=]').get(0).focus()
    return false
  })
  	
  // attach trip planner "Example" form auto-fill on click
  $('#trip_planner p.example').mouseup( function(){  
    $(this).prevAll('label').slice(0,1).find('input[type=text]').val($(this).text().replace('Example: ','')) 
  })
  
  // resize large images in feeds
  $('#headlines img').each(function(){
    if($(this).width() > 600) $(this).width(600);
  })
  
  // show things that are only available to JS-enabled browsers
  $('.js_only').css('display','block').each(function(){
    if($.browser.msie) $(this).replaceWith('<div class="warning"><p>This tool requires a browser with proper support for web standards.</p><p>On Windows, both <a href="http://getfirefox.com">Firefox</a> and <a href="http://opera.com">Opera</a> work very well.</p></div>')
  });
  
  // Cancel buttons should go back
  $('input[type=button][value=Cancel]').click(function(){
    history.go(-1)
  })


  // add the "reverse directions" button
  $('#trip_planner').append(
    $('<img src="/images/arrow_switch.png" id="reverse_trip" title="Reverse trip"/>').click(function(){
      tmp = $('input[name=from]').val()
      $('#trip_planner input[name=from]').val($('#trip_planner input[name=to]').val())
      $('#trip_planner input[name=to]').val(tmp)
      $('#trip_planner input[value=""]').add('#trip_planner input[name=when]').eq(0).select()
      return false;
    }).css({
      position:'absolute',
      top:'78px',
      left:'320px',
      border:'0',
      cursor:'pointer'
    })
  )

  // IE layout fixes
  if($.browser.msie && $.browser.version < 7){
    // fix button placement
    $('#sidebar').hide(1,function(){
      $('#sidebar').show()
    });
    // help links broken
    $('#sidebar h3').css('height','99.9%'); // FUCK YOU, IE. FUCK YOU SOOOO HARD.
    // search box readjustment
    $('#search_text').css('top',$('#search_text').offset().top-1).css('left',$('#sidebar').offset().left+10).css('position','absolute')
    // re-position reverse direction img
    $('#reverse_trip').css({left:'300px',top:'82px'})
  }
  
  //
  // autofill "from" with closest user-entered address, 
  // or best geolocation result if no address within a 1/2 km or so
  //
  if(navigator.geolocation && $('body').hasClass('homepage')){
    //if( document.location.href.indexOf('travel/from') != -1 ) return false    
    var geolocated = false

    // do we need to geolocate? look for a 'here' cookie
    var here = readCookie('here')
    if(here!=null) return false
        
    // show location throbber
    $('#trip_planner input[name=from]').addClass('locating')
    
  	// attempt the geolocation
  	navigator.geolocation.getCurrentPosition(function (loc) {
      // dunno why this happens twice sometimes
      if(geolocated == true) return false
      geolocated = true

      // accuracy sucks, give up
      if(loc.coords.accuracy > 500) return false;
  		
  		// grab the nearest locations from the API
			$.getJSON('/near/'+loc.coords.latitude.toString()+','+loc.coords.longitude.toString(), function(data, textStatus){

        if(data['locations'].length == 0 && data['user_places'].length == 0) return false
   		  
   		  // populate the 'from' field in the planner form, unless they've already got that value in the TO field
   		  //if ( $('#trip_planner input[name=to]') ) return false
   		  if(data['user_places'].length > 0)
   		  {
   		    if ($('#trip_planner input[name=to]').val() != data['user_places'][0]['name'] && $('#trip_planner input[name=from]').val() != data['user_places'][0]['name']){
     		    $('#trip_planner input[name=from]').val(data['user_places'][0]['name']).animate({'backgroundColor':'#ffff80'},0,function(){
     		      $(this).animate({backgroundColor:'white'},1500)
     		    })
   		    }
  	    }
 		    else if(data['locations'].length > 0) 
   		  {
   		    if ($('#trip_planner input[name=to]').val() != data['locations'][0]['name'] && $('#trip_planner input[name=from]').val() != data['locations'][0]['name']){
     		    $('#trip_planner input[name=from]').val(data['locations'][0]['name']).animate({'backgroundColor':'#ffff80'},0,function(){
     		      $(this).animate({backgroundColor:'white'},1500)
     		    })
   		    }
 		    }
 		    
        // hide location throbber
        $('#trip_planner input[name=from]').removeClass('locating')
			}) // $.getJSON
  		
  	}, function (e) {
  		//alert(e)
      // hide location throbber
      $('#trip_planner input[name=from]').removeClass('locating')
  	}) // navigator.geolocation.getCurrentPosition


  } //  if(navigator.geolocation)

  // tooltips (beautytips)
  $('td.stoptime span').css('cursor','help').css('position','relative').each(function(){
    if(!jQuery.bt) return false // gtfo if we don't have beautytips (i.e. in ie)
    $(this).bt('<div class="beautytip">'+$(this).attr('title')+'&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'+$(this).text()+'</div>',{
      showTip: function(box){
        $(box).css({opacity:0}).animate({opacity: 0,left:'+=12px'}, 0, function(){
          $(this).show().animate({opacity:1,left:'-=10px'}, 200)//.fadeIn(100);
        })
      },
      hideTip: function(box, callback){
        $(box).animate({opacity: 0,left:'+=10px'}, 200, callback);
      },
      padding: '14px 22px',
      shrinkToFit: true,
      fill: 'rgba(0,0,0,.7)',
      cornerRadius: 8,
      strokeWidth: 0,
      shadow: true,
      shadowOffsetX: 0,
      shadowOffsetY: 3,
      shadowBlur: 8,
      shadowColor: 'rgba(0,0,0,.7)',
      shadowOverlap: false,
      //noShadowOpts: {strokeStyle: '#999', strokeWidth: 2},
      closeWhenOthersOpen: true,
      positions: ['left','top']
    })
  })
  
  // highlight apropriate field on homepage for partial trip plan requests
  if(window.location.href.indexOf('/travel/to/')>0 && window.location.href.indexOf('/from/')==-1){
    $('#trip_planner input[name=to]').val($('#trip_planner input[name=to]').val().toProperCase())
    $('#trip_planner input[name=from]').focus().select()
  }
  if(window.location.href.indexOf('/travel/from/')>0 && window.location.href.indexOf('/to/')==-1){  
    $('#trip_planner input[name=from]').val($('#trip_planner input[name=from]').val().toProperCase())
    $('#trip_planner input[name=to]').focus().select()
  }

    
  // creates a "soft limit" for list length. if the list is longer 
  // than "outerBound" it will shrink to "innerBound" items, with 
  // the bolded one in the center of the list
	$('.list').not('[shape_id]').find('ul').not('.sortable').each(function(){
  	innerBound = 9;
  	outerBound = 14;

		items = $(this).find('li');

		if( items.length > outerBound ){
			index = items.index( $('li.current')[0] );
			// if this noun is part of the set, shrink around it
			if(index >= 0){
				if(index < Math.floor(innerBound/2)){
					low = 0;
					high = low + innerBound;
				}else if( index > (items.length - 1) - Math.floor(innerBound/2) ){
					high = items.length;
					low = high - innerBound;
				}else{
					low = index - Math.floor(innerBound/2);
					high = index + Math.floor(innerBound/2)+1;
				}
				
			}else{ // there is no index, hide more than innerBound
					low = 0;
					high = innerBound;
			}
			
			// now hide the elements that don't fall in our happy range
			items.not(items.slice(low,high)).hide();
			if(low > 0) items.eq(low).before('<li><em>...'+low+' more above</em></li>').prev().css({'font-size':'0.7em',color:'#808080',cursor:'pointer'}).click(function(){
				$(this).parent().parent().find('li').show().parent().find('em').parent().hide()
			});
			if(high < items.length) items.eq(high).after('<li><em>...'+(items.length - high)+' more below</em></li>').next().css({'font-size':'0.7em',color:'#808080',cursor:'pointer'}).click(function(){
				$(this).parent().parent().find('li').show().parent().find('em').parent().hide()
			});
		}
	})

  
}) // $()


function doSearch(limit){
	limit = limit || 500;

	$.post("/search", { uri: $('#search_text').val(), limit:limit},
		function(json){
			// hide the sidebar
			$('#sidebar').hide();

			// set up the search results section
			if($('#search_results').size() == 0) $('#content').prepend('<div id="search_results"></div>');
			sr = $('#search_results').show();

			// get the results
			results = eval('('+json+')');
			
			// GTFO if there are no results
			if(results.length == 0)
			{
			  sr.empty().append("<h2>Hmmm... can't seem to find that.</h2><p>Your search doesn't seem to match anything around here.</p><p>We're still working hard to make search better.</p>");
				//sr.append("<p>You can always <a href='/new'>create a new page</a>.</p>");
			  return true;
			}
			
			// clear the old html, if any
			sr.empty();
			
			// write the html
			if(results.stations.length > 0){
				sr.append('<h2>Stations</h2><ul id="search_stations"/>');
				$(results.stations).each(function(i){
					$('#search_stations').append('<li><a href="/'+this.uri+'">'+this.name+'</a></li>');
				})
			}
			if(results.routes.length > 0){
				sr.append('<h2>Routes</h2><ul id="search_routes"/>');
				$(results.routes).each(function(i){
					$('#search_routes').append('<li><a href="/'+this.uri+'">'+this.name+'</a></li>');
				})
			}
			if(results.pages.length > 0){
				sr.append('<h2>Pages</h2><ul id="search_pages"/>');
				$(results.pages).each(function(i){
					$('#search_pages').append('<li><a href="/'+this.uri+'">'+this.name+'</a></li>');
				})
			}
			if(results.stops.length > 0){
				sr.append('<h2>Locations</h2><ul id="search_stops"/>');
				$(results.stops).each(function(i){
					$('#search_stops').append('<li><a href="/'+this.uri+'">'+this.name.replace(/(outh|orth|est|ast)bound On/,' on').replace(/\sAt\s/,' @ ').replace(/\bFarside$/,'(farside)')+'</a></li>');
				})
			}
			
			//sr.append("<p>Don't see it? Why not <a href='/new'>create a new page</a>.</p>");
			
			hidden = results.total - results.stations.length - results.routes.length - results.pages.length - results.stops.length;
			if(hidden > 0) $('#search_results li:last').append('<li id="show_all"><em>and '+hidden+' more...</em></li>');
			$("#show_all").click(function(){$(this).html('<em>Loading... brb</em>');doSearch()}).css('cursor','pointer')
		}
	);
} // doSearch


function makeMapInteractive() {
  var script = document.createElement("script");
  script.type = "text/javascript";
  script.src = "http://maps.google.com/maps?file=api&v=2.208&key="+$("img.map").attr("G_API_KEY")+'&async=2&callback=makeMapInteractive2';
  document.body.appendChild(script);
  $("#makemapinterface_note").html('loading ...');
} // makeMapInteractive

function makeMapInteractive2() {

  $("#sidebar img.map").replaceWith("<div id='map' class='map' style='height:300px; width:350px; margin: 0 10px;' lat='"+$("img.map").attr("lat")+"' lng='"+$("img.map").attr("lng")+"'></div>");
  $("#article img.map").replaceWith("<div id='map' class='map' style='height:400px; width:620px; margin: 0 0 1em 0;' lat='"+$("img.map").attr("lat")+"' lng='"+$("img.map").attr("lng")+"'></div>");
  //$("img.map").remove();
  $("#makemapinterface_note").remove();
  var script = document.createElement("script");
  script.type = "text/javascript";
  script.src = "/javascripts/maps.js";
  document.body.appendChild(script);
} // makeMapInteractive2



String.prototype.toProperCase = function(){
  return this.toLowerCase().replace(/\w+/g,function(s){
    return s.charAt(0).toUpperCase() + s.substr(1);
  })
} // String.prototype.toProperCase

function haversine(lat1, lon1, lat2, lon2) {
  var R = 6371; // earth's mean radius in km
  var dLat = (lat2-lat1) * Math.PI / 180
  var dLon = (lon2-lon1) * Math.PI / 180
  lat1 = lat1 * Math.PI / 180, lat2 = lat2 * Math.PI / 180;

  var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
          Math.cos(lat1) * Math.cos(lat2) * 
          Math.sin(dLon/2) * Math.sin(dLon/2);
  var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
  var d = R * c * 1000; // dist in m
  return d;
} // haversine

function createCookie(name,value,minutes) { // dont really need this, we set cookies in the request
	if (minutes) {
		var date = new Date();
		date.setTime(date.getTime()+(minutes*60*1000));
		var expires = "; expires="+date.toGMTString();
	}
	else var expires = "";
	document.cookie = name+"="+value+expires+"; path=/";
}

function readCookie(name) {
	var nameEQ = name + "=";
	var ca = document.cookie.split(';');
	for(var i=0;i < ca.length;i++) {
		var c = ca[i];
		while (c.charAt(0)==' ') c = c.substring(1,c.length);
		if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
	}
	return null;
}

function eraseCookie(name) {
	createCookie(name,"",-1);
}
