(function ($) {
  var EventMap = function (map, name, address) {
    var dragging = false;
    var elements;
    var faded = false;
    var fadeElements;
    var geocoder = new google.maps.Geocoder();
    var opacity = {
      min: 0.25,
      max: 0.82
    };
    var x;

    function initialize() {
      var event = map.parents('.event:first');
      elements = $('div[class^=event]:not(.fade)', event);
      fadeElements = $('div.fade', event);
      fadeElements.fadeTo(0, opacity.max);
      createGoogleMap();
      map.hover(over, out);
    }

    function createGoogleMap() {
      geocoder.geocode({ address: address }, function (results, status) {
        if (status == google.maps.GeocoderStatus.OK) {
          var latLng = results[0].geometry.location;
          var center = new google.maps.LatLng(latLng.lat() - 0.003, latLng.lng());
          var options = {
            zoom: 14,
            center: center,
            disableDefaultUI: true,
            mapTypeId: google.maps.MapTypeId.ROADMAP
          };
          var googleMap = new google.maps.Map(map.get(0), options);
          googleMap.panBy(0, -36);
          google.maps.event.addListener(googleMap, 'dragstart', dragStart);
          google.maps.event.addListener(googleMap, 'dragend', dragEnd);
          google.maps.event.addListener(googleMap, 'zoom_changed', zoomChanged);
          var marker = new google.maps.Marker({ map: googleMap, position: latLng });
          var content =
            '<div>' +
              name +
              '<br />' +
              '<a href="http://maps.google.com/maps?saddr=&daddr=' + address + '">Directions</a>' +
            '</div>';
          var miniPop = new MiniPop({ marker: marker, content: content });
          google.maps.event.addListener(marker, 'click', function () {
            togglePopup(miniPop);
          });
        }
      });
    }

    function dragEnd() {
      dragging = false;
      fadeIn();
    }

    function dragStart() {
      dragging = true;
      fadeOut();
    }

    function fadeIn() {
      if (faded) {
        faded = false;
        elements.stop().fadeTo(300, 1);
        // ie8 doesn't fade the date, so we need to do it separately
        $('p.date', elements).stop().fadeTo(300, 1);
        fadeElements.stop().fadeTo(300, opacity.max);
      }
    }

    function fadeOut() {
      if (!faded) {
        faded = true;
        elements.stop().fadeTo(300, opacity.min);
        // ie8 doesn't fade the date, so we need to do it separately
        $('p.date', elements).stop().fadeTo(300, opacity.min);
        fadeElements.stop().fadeTo(300, opacity.min);
      }
    }

    function out() {
      if (!dragging) {
        fadeIn();
      }
    }

    function over() {
      fadeOut();
    }

    function togglePopup(miniPop) {
      if (miniPop.visible) {
        miniPop.hide();
      } else {
        miniPop.show();
      }
    }

    function zoomChanged() {
      fadeOut();
    }

    initialize();
  };

  var MiniPop = function (options) {
    var marker = options.marker;
    var map = marker.map;
    var content = options.content;
    var miniPop = this;

    google.maps.event.addListener(map, 'click', function () {
      miniPop.hide()
    });

    this.visible = false;
    this.setMap(map);

    this.draw = function () {
      var latLng = marker.getPosition();
      var pos = this.get('projection').fromLatLngToDivPixel(latLng);
      var top = pos.y - 44;
      var left = pos.x + 7;
      content.css('top', top + 'px');
      content.css('left', left + 'px');
    };

    this.hide = function () {
      if (this.visible) {
        content.fadeOut(70);
        this.visible = false;
      }
    };

    this.onAdd = function () {
      content = $('<div>').addClass('popup').append(content);
      this.getPanes().floatPane.appendChild(content.get(0));
    };

    this.onRemove = function () {
      this.setMap(null);
      content.parentNode.removeChild(content);
    };

    this.show = function () {
      if (!this.visible) {
        content.fadeIn(70);
        this.visible = true;
      }
    };
  };

  $(document).ready(function () {
    MiniPop.prototype = new google.maps.OverlayView();
    new EventMap($('#map'), "Huberts", "80 S 8th St Minneapolis, MN 55402");
  });
})(jQuery);

