(function ($) {
  
  $.myTransit = function (options) {
    
    var keys = {
      up: 38,
      down: 40,
      enter: 13
    }
    var lookupTimer;
    var recents;
    if ($('#map').length > 0) {
      try {
        var geocoder = new google.maps.Geocoder();
        var latlng = new google.maps.LatLng(-27.456341, 153.032084);
        var mapOptions = {
          zoom: 13,
          center: latlng,
          mapTypeId: google.maps.MapTypeId.ROADMAP
        };

        var map = new google.maps.Map(document.getElementById('map'), mapOptions);        
      } catch (e) { };
    }
    
    if (false && (recent_data = $.cookie('recents')) != null) {
      recents = $.evalJSON(recent_data);      
      if (typeof(recents) != 'object') {
        recents = [];
      }
      if (recents.length > 0) {
        $('#recent').html('');
        $.each(recents, function (i) {
          var from_code = this.from_code;
          var to_code = this.to_code;
          $('<li />').text(this.from + ' to ' + this.to).click(function () {
            
          }).appendTo($('#recent'));
        });
        
      }
    } else {
      recents = [];
    }
    
    
    $('#loading').hide().ajaxStart(function () {
      $(this).fadeIn(300);
    }).ajaxStop(function () {
      $(this).fadeOut(300);
    });
    
    $('#back_to_options').hide().click(hideDetailView);
    $('.lookup').css('height', '0').css('opacity', 0);
    
    $('fieldset input').data('prev', '');
    $('input[tabindex=1]').focus();
    $('form').submit(function (e) {
      if (!locationsFilled()) {
        e.preventDefault();
      }
      // recents.unshift({
      //   from: $('#from .main').text(),
      //   from_code: $('#from input[type="hidden"]').val(),
      //   to: $('#to .main').text(),
      //   to_code: $('#to input[type="hidden"]').val(),
      // });
      // $.cookie('recents', $.toJSON(recents));
      

    });
    
    $('.location .options a.change').click(function (e) {
      var fieldset = $(this).parents('fieldset');
      var container = fieldset.children('.picker');
      var location = fieldset.find('.location');
      fieldset.find('input[type=hidden]').val('');
      
      location.fadeOut(300, function () {
        container.fadeIn(300);
      });
      e.preventDefault();
    });
    
    $('input[type=text]:first').focus();
    $('fieldset input[type=text]').attr('autocomplete', 'off').keydown(function (e) {
      var field = $(this);
      var fieldset = field.parents('fieldset');
      var lookup = fieldset.find('.lookup');
      var container = fieldset.children('.picker');
      switch(e.which) {
        case keys.down:
          current = $(fieldset.find('li.current')[0]);
          next = current.next('li');
          if (!next || next.length == 0) {
            next = fieldset.find('li:first');
          }
          current.removeClass('current');
          next.addClass('current');
          lookup.scrollTo(current.prev('li'), {duration: 50});
          e.preventDefault();
          break;
        case keys.up:
          current = $(fieldset.find('li.current')[0]);
          prev = current.prev('li');
          if (!prev || prev.length == 0) {
            prev = fieldset.find('li:last');
          }
          current.removeClass('current');
          prev.addClass('current');
          lookup.scrollTo(prev.prev('li').prev('li'), {duration: 50});
          e.preventDefault();
          break;
        case keys.enter:
          if ($(lookup).find('li').length != 0) {
            selectLocation(field);
          }
          e.preventDefault();
        default:
          if (field.data('prev') != field.val() && field.val().length > 1) {
            clearTimeout(lookupTimer);
            lookupTimer = setTimeout(function () { 
              field.data('prev', field.val());
              updateLookup(field);
            }, 600);
          }
      }
    });
    
    $('#when').focus(function () {
      this.select();
    }).livesearch({
      searchCallback: function (value) {
        $.post('/chronic_eval', {time: value}, function (data) {
          $('#when_eval').text(data);
          if (data.match('require')) {
            $('#when').addClass('invalid');
          } else {
            $('#when').removeClass('invalid');
          }
        })
      },
      innerText: 'now',
      minimumSearchLength: 3
    });
        
    function selectLocation(field) {
      var fieldset = field.parents('fieldset');
      var lookup = fieldset.find('.lookup');
      var container = fieldset.children('.picker');
      
      fieldset.find('input[type=hidden]').val(getLocationCode(field));
      
      if (locationsFilled()) {
        $('#when').focus();
      }
      
      fieldset.nextAll('fieldset').find('input[type=text]:first').focus();
      
      geocoder.geocode({
          address: getAddress(field)
        },
        function (results, status) {
          if (old_marker = field.data('marker')) {
            old_marker.setMap(null);
          }
          if (results.length > 0) {
            
            var marker = new google.maps.Marker({
                map: map, 
                position: results[0].geometry.location,
                icon: getIconForField(field)
            });
            field.data('marker', marker);
            updateBounds();
            
          }
          lookup.animate({height: 0, opacity: 0}, function () {
            $(this).hide();
          });
          container.fadeOut(300, function () {
            fieldset.find('.location .main').html(getAddress(field));
            if (results.length > 0) {
              fieldset.find('.location .secondary').html(results[0].formatted_address);
            } else {
              fieldset.find('.location .secondary').html('Unable to locate on Google Maps. Not to worry, I just can\'t put it on a map for you');
            }
            
            fieldset.find('.location').fadeIn(300, function () {
              
            });
          });
          
          
      });
    }
    
    function updatePlanner() {
      $.post('/plan', $('form').serialize(), function (data) {
        console.log(data);
      });
    }
    
    function locationsFilled() {
      var count = 0;
      $('#from_to input[type=hidden]').each(function () {
        if ($(this).val().length > 0)
          count++;
      });
      return count == 2;
    }
    
    function updateBounds() {
      var bounds = new google.maps.LatLngBounds();
      var positions = [];
      $('fieldset input').each(function (i) {
        var marker = $(this).data('marker');
        if (marker) {
          positions[i] = marker.getPosition();
          bounds.extend(positions[i]);
        }
      });
      map.fitBounds(bounds);
    }
    
    function hideDetailView() {
      $('#overlay').fadeOut(400);
      $('#back_to_options').fadeOut(400);
      $('#marker').css('zIndex', -1);
      $('ol.journeys > li.focus').fadeOut(400, function () { $(this).remove() });
    }
    
    function getIconForField(field) {      
      if (field.parents('fieldset')[0].id == 'from') {
        return "http://www.google.com/intl/en_us/mapfiles/ms/micons/yellow-dot.png"
      } else {
        return "http://www.google.com/intl/en_us/mapfiles/ms/micons/green-dot.png"
      }
    }
    
    function getAddress(field) {
      return field.parents('fieldset').find('li.current').text();
    }
    
    function getLocationCode(field) {
      return field.parents('fieldset').find('li.current').data('code');
    }
    
    function updateLookup(obj) {
      parent = $(obj.parents('fieldset'));
      set = parent.find('input[type="text"]');
      (lookup = parent.find('.lookup')).addClass('loading').html('<ul><li class="loading">Loading...</li></ul>');
      lookup.animate({
        height: '30px',
        opacity: 1
      });
      $.getJSON('/lookup?street=' + escape(set[0].value) + '&suburb=' + escape(set[1].value), function (data) {
        lookup.html('<ul></ul>');
        list = lookup.find('ul');
        if (data.length == 0) {
          list.append('<li>No results found.</li>');
        } else {
          lookup.animate({
            height: ((v = data.length * 30) > 150 ? 150 : v) + 'px',
            opacity: 1
          });
          
          $.each(data, function (i, item) {
            var item = $(document.createElement('li'))
                              .css('opacity', 0)
                              .data('code', item[1])
                              .text(item[0]);
            list.append(item);
          });
          list.children('li').each(function (index) {
            $(this).animate({opacity: 0}, index * 10).animate({opacity: 1}, 700);
          });
          list.children('li:first').addClass('current');
          list.children('li').click(function () { selectLocation($(this)); });
        }
      });
    }
    
    return {
      activateDetailView: function () {
        $('#planner ol.journeys > li').click(function () {
          var focus = $(this).clone();
          $('#planner ol.journeys').append(focus.css({
                      position: 'absolute',
                      zIndex: 20,
                      borderLeft: 'solid 1px #8A8376',
                      backgroundColor: '#fff',
                    }).addClass('focus'));
          $('#overlay').empty();
          $('#marker').css('zIndex', 30);
          $('#overlay').css('height', this.offsetHeight + 30);
          $('#overlay').append('<div class="details"></div>');
          $('#overlay .details').hide().append(focus.find('dl').clone());
          $('#overlay').fadeIn(400, function () {
            focus.animate({
              left: 0
            }, 
            {
              easing: 'easeOutExpo',
              duration: (focus.css('left') == '0px' ? 0 : 400),
              complete: function () {
                $('#overlay .details').fadeIn(600);
                $('#back_to_options').fadeIn(600);
                
              }});
          });
          
          
        });
      }
    }
    
  }
  
})(jQuery);

$($.myTransit);

    
function updateMarker(start_bound_time, end_bound_time) {
  var now = new Date();
  var time = now.getTime() / 1000;
  var time_offset = time - start_bound_time;
  var current_position = Math.round(time_offset / 12);

  if (current_position > 0 && time < end_bound_time) {
    $('#marker').css('top', current_position + 'px' );
    $('#marker').show();
    $('#marker div').text(formatTime(now));
  } else if (time > end_bound_time) {
    $('#marker').hide();
  }
  if (true || current_position % 5 == 0) {
    updateStartingIn();
  }
  setTimeout(function () { updateMarker(start_bound_time, end_bound_time); }, (Math.ceil(now.getTime() / 12000) * 12000) - now.getTime());
  
  
}

function formatTime(time) {
  if ((hour = (time.getHours() % 12)) == 0) {
    hour = 12;
  }
  am_pm = (time.getHours() >= 12 ? 'pm' : 'am')
  minutes = time.getMinutes();
  minutes = ((minutes + '').length == 1 ? '0' : '') + minutes;
  return hour + ':' + minutes + am_pm;
}

function updateStartingIn() {
  var now = new Date().getTime() / 1000 / 60;
  $('.remaining_time').each(function () {
    var time_until = Math.ceil($(this).attr('time') / 60 - now);
    var time = '', class = '';

    
    if (time_until < -2) {
      time = 'missed';
      $(this).removeClass('remaining_time')
      $(this).parents('ol.journey').addClass('missed').fadeTo(400, 0.5).find('dt.in').text('');
    }
    else if (time_until < 1) {
      time = 'now';
    }
    else if (time_until < 60) {
      time = time_until + 'min';
    }
    else {
      time = Math.floor(time_until / 60) + 'hr' + (time_until % 60) + 'm';
    }
    
    if (time_until > 30) {
      class = 'plain';
    }
    else if (time_until > 20) {
      class = 'green';
    }
    else if (time_until > 10) {
      class = 'yellow';
    }
    else if (time_until > 3) {
      class = 'red';
    }
    else {
      class = 'critical';
    }
    
    $(this).removeClass('plain green yellow red critical').text(time).addClass(class);
  });
}