(function($){


    $.frontMap = function(el, options){
        // To avoid scope issues, use 'base' instead of 'this'
        // to reference this class from internal events and functions.
        var base = this;
        
        // Access to jQuery and DOM versions of element
        base.$el = $(el);
        base.el = el;

        // will be needed often
        base.$dots = base.$el.find('#dots');

        // Coordinates for the boat
        base.boatStops = [
            {x:  81, y: 283, stop: true},
            {x: 193, y: 175, stop: true},
            {x: 189, y: 200},
            {x: 272, y: 202},
            {x: 341, y: 191, stop: true},
            {x: 377, y: 240},
            {x: 433, y: 258},
            {x: 468, y: 231, stop: true},
            {x: 495, y: 275},
            {x: 550, y: 311, stop: true},
            {x: 570, y: 289},
            {x: 714, y: 214},
            {x: 751, y: 234, stop: true}
        ];

        // Name for transitionend event in different browsers
        base.transEvents = ['webkitTransitionEnd', 'oTransitionEnd', 'transitionend'];
        
        // Add a reverse reference to the DOM object
        base.$el.data("frontMap", base);
        
        base.init = function() {
            base.options = $.extend({},$.frontMap.defaultOptions, options);

            // link whole element
            base.$dots.delegate('li', 'click', function() {
                window.location = $(this).find('.read-more').attr('href');
            })

            // IE doesn't support opacity properly
            if(jQuery.support.opacity) {
                // remove no-js marker
                base.$dots.removeClass('no-js');
                base.$dots.find('.popup').css('display', 'none');
                base.bindHoverEvents();

            } else {
                // more ie fixes don't ask
                base.$dots.find('li.below').each(function() {
                    var tmp = $(this).find('h3').prependTo($(this).find('.hover-target'));
                    $(this).find('.hover-target').prepend(tmp);
                })
                // stupid ie7 bug needs some random modification to show the arrow.
                base.$dots.delegate('li', 'mouseenter', function() {
                    var $tmp = $(this);
                    setTimeout(function() {$tmp.find('.up-arrow').css('width', '40px');}, 10);
                });
                base.$dots.delegate('li', 'mouseleave', function() {
                    var $tmp = $(this);
                    setTimeout(function() {$tmp.find('.up-arrow').css('width', '10px');}, 10);
                });

            }
            
            base.startBoat();
            base.startPulsating();

        };

        base.startBoat = function() {
            var pos = base.boatStops[0];
            
            var $boat = $('<span id="boat" />');
            base.$el.append($boat);

            $boat.css({left: pos.x, top: pos.y});
            base.$boat = $boat;
            base.moveBoat({index: 1, reverse: false})
        }

        base.moveBoat = function(opts) {
            var pos = base.boatStops[opts.index];
            var dx = base.$boat.position().left-pos.x;
            var dy = base.$boat.position().top-pos.y;
            var distance = Math.sqrt(dx*dx + dy*dy);
            var time = distance * 28;

            opts.reverse = opts.index == base.boatStops.length -1 || opts.index == 0 ? !opts.reverse : opts.reverse;
            opts.index = opts.reverse ? opts.index -1 : opts.index +1;

            base.$boat.animate({
                left: pos.x,
                top:  pos.y
            }, time, 'linear', function() {
                if(typeof(pos.stop) !== "undefined") {
                    setTimeout(function(){base.moveBoat(opts)}, 1300);
                } else {
                     base.moveBoat(opts);
                }
            });
        }
        
        base.startPulsating = function() {
            base.$dots.find('.map-point.show-dot').each(function() {
                var $el = $(this);
                var interval = Math.random()*4000 +4000;
                //var interval = 4000;
                var pulseFunc;
                var $glow = $('<img class="glow" src="images/glow.png" />');
                $el.after($glow);
                if(!Modernizr.csstransitions) {
                    pulseFunc = function() {
                         $glow.animate({
                                left: -12,
                                top: -12,
                                height: 24,
                                width: 24
                            }, 800)
                            .animate({
                                left: -1,
                                top: -1,
                                height: 2,
                                width: 2
                            }, 800)
                    }
                } else {
                    for(var i in base.transEvents) {
                        base.$dots.delegate('.pulsate', base.transEvents[i], function(e) {
                            $(this).removeClass('pulsate');
                        });
                    }
                    pulseFunc = function() {$glow.addClass('pulsate')};
                }
                setTimeout(function() {
                    pulseFunc();
                    setInterval(pulseFunc, interval);
                }, interval - 4000);
            })
        }
        // Bind show/hide text events
        base.bindHoverEvents = function() {
            if(!Modernizr.csstransitions) {

                // fade in and place on top
                base.$dots.delegate('.hover-target', 'mouseenter', function(e) {
                    $(this).css('z-index', '40')
                    .find('.popup')
                    .stop()
                    .css({
                        display: 'block'
                    })
                    .animate({
                        opacity: 1
                    }, 'slow');
                });
                // out and lower
                base.$dots.delegate('.hover-target', 'mouseleave', function(e) {
                    var $li = $(this);
                    $li.find('.popup')
                    .stop()
                    .animate({
                        opacity: 0
                    }, 'slow', function() {
                        $(this).css('display', 'none');
                        $li.css('z-index', '30');
                    });
                });
            }
            else {
                base.$dots.delegate('.hover-target', 'mouseenter', function(e) {
                    // Non transitional attributes. Needs js
                    $(this).parent().css('z-index', '40');
                    var tmp = $(this).children('.popup')
                        .css({display: 'block'});

                    // Needed to handle a transition bug in at least webkit
                    setTimeout(function() {tmp.addClass('show')}, 10);
                });
                base.$dots.delegate('.hover-target', 'mouseleave', function(e) {
                    $(this).children('.popup')
                        .removeClass('show');
                });
                // Need to set display: none after the transition.
                for(var i in base.transEvents) {
                    base.$dots.delegate('.popup', base.transEvents[i], function(e) {
                        if($(this).css('opacity') == 0) {
                            $(this)
                                .css('display', 'none')
                                .parents('li').css('z-index', '30');
                        }
                    });
                }
            }
        };
        
        // Run initializer
        base.init();
    };
    
    $.frontMap.defaultOptions = {
    };
    
    $.fn.frontMap = function(options){
        return this.each(function(){
            (new $.frontMap(this, options));
        });
    };
    
    // This function breaks the chain, but returns
    // the frontMap if it has been attached to the object.
    $.fn.getfrontMap = function(){
        this.data("frontMap");
    };
    
})(jQuery);


$(function() {
    $('#front-map').frontMap();
})
