/**
 * Interpolis Maps
 * 
 */
Interpolis.Maps = (function ($) {

    var GC = new google.maps.Geocoder(); // A re-usable Geocoder object

    // default settings
    var settings = {
        map: {
            zoom: 15,
            // center: new google.maps.LatLng(51.574509, 5.056833),
            center: new google.maps.LatLng(51.562385000000012, 5.095670000000012),
            mapTypeId: google.maps.MapTypeId.ROADMAP,
            scrollwheel: false,
            disableDefaultUI: true,
            clubId: -1
        },
        paths: {
            balloon: '/Templates/Public/Pages/Idea/GetBalloon.aspx',
            idea: '/Templates/Public/Pages/Idea/GetBalloon.aspx',
            icons: '/static/images/icons/map/'
            // MOVED TO DIV inside data-feed-uri attribute feed: '/Templates/Public/Pages/Idea/GetIdeasJson.aspx?clubId='
                
            //balloon: 'includes/highlight.shtml',
            //idea: 'includes/idea.shtml',
            //icons: '/static/images/icons/map/'
            
        },
        zoom: {
            max: 18,
            min: 6
        }
    };

    /**
    * Controller
    * 
    */
    var Maps = {
        setLocation: function (lat, lng, zoom, clubId) {
            settings.map.center = new google.maps.LatLng(lat, lng);
            settings.map.zoom = zoom;
            settings.map.clubId = clubId;
        },

        init: function () {
            this.container = document.getElementById('google-map');
            this.map = new google.maps.Map(this.container, settings.map);
            this.markers = [];
			settings.paths.feed = $(this.container).attr('data-feed-uri'); 
			this.load(settings.paths.feed);
            Statistics.count('/Community/kaart');
        },

        load: function (address) {
            $.ajax({
                url: address + settings.map.clubId,
                type: 'GET',
                dataType: 'json',
                success: this.handleResponse.bind(this)
            });
        },

        handleResponse: function (response) {
            for (var i = 0; i < response.length; i++) {
                this.add(response[i]);
            }
            var id = $('#google-map').attr('LBi:active-idea');
            var marker = null;
			if (marker = this.find(id)) {
				this.map.setCenter(new google.maps.LatLng(marker.position.lat(), marker.position.lng())); // try to fix timing bug when ative ID is way outside viewport...
                this.activateIdea(id);
            } else {
                this.map.panTo(settings.map.center);
            }

            var q = window.location.search;
            var reg = /map=([a-z]+)/i;
            if (reg.test(q)) {
                var type = String(reg.exec(q)[1]);
                this.map.setMapTypeId(type);
                $('div.startlayer').fadeOut();
            }
        },

        handleClick: function (e) {
            var link = e.target;
            var rel = link.rel;
            var type = /map-([^ ]+)/.exec(rel)[1];

            var types = google.maps.MapTypeId;

            switch (type) {
                case 'zoomin': case 'zoomout':
                    this.zoom(e);
                    break;
                case 'refresh':
                    this.refresh();
                    break;
                case 'goto':
                    this.navigate(e);
                    break;
                case 'roudmap':
                    this.setMapType(e, types.ROADMAP);
                    break;
                case 'satellite':
                    this.setMapType(e, types.SATELLITE);
                    break;
                case 'terrain':
                    this.setMapType(e, types.TERRAIN);
                    break;
            }

            e.preventDefault();
        },

        navigate: function (e) {
            var code = $('#postcode').val();
            var self = this;
            if (code) {
                var formatted = 'netherlands, ' + code;
                GC.geocode({ address: formatted }, function (response) {
                    try {
                        var location = response[0].geometry.location;
                        self.map.setCenter(location);
                    } catch (e) {
                    }
                });
            }
        },

        refresh: function () {
            this.removeIdea();
            for (var i = 0; i < this.markers.length; i++) {
                this.markers[i].remove();
            }

            this.markers = [];
            this.load(settings.paths.feed);
        },

        add: function (options) {
            var settings = Interpolis.Maps.transmogrify(options);
            var marker = new Interpolis.Maps.Markers.Marker(settings);
            this.markers.push(marker);
        },

        find: function (ID) {
            var l = this.markers.length;
            for (var i = 0; i < l; i++) {
                var marker = this.markers[i];
                if (marker.LBi.ID == ID) {
                    return marker;
                }
            }

            return null;
        },

        getIdeas: function () {
            return this.markers;
        },

        addIdea: function () {
            if (this.ideaMarker) {
                return;
            }

            var map = this.map;
            var options = this.transmogrify({
                icon: '/static/images/icons/map/idea.png',
                details: settings.paths.idea,
                LBi: {
                    ID: -1,
                    active: true,
                    pos: {
                        lat: map.center.lat(),
                        lng: map.center.lng()
                    },
                    draggable: 'idea-drag'
                }
            });

            this.ideaMarker = new Interpolis.Maps.Markers.Marker(options);
        },

        removeIdea: function () {
            if (this.ideaMarker) {
                this.ideaMarker.remove();
                this.ideaMarker = null;
            }
        },

        activateIdea: function (id) {
            var active = this.find(id);
            if (active) {
                active.balloon.inflate();
            }
        },

        deflateIdeas: function () {
            // deflate all balloons
            var ideas = this.getIdeas();
            for (var i = 0; i < ideas.length; i++) {
                if (ideas[i].balloon) ideas[i].balloon.deflate();
            }

            // deflate possible idea marker balloon
            if (this.ideaMarker && this.ideaMarker.balloon) {
                this.ideaMarker.balloon.deflate();
            }
        },

        zoom: function (e) {
            this.deflateIdeas();
            var link = e.target;
            var direction = (/zoomin/i.test(link.className)) ? 'in' : 'out';
            var Z = this.map.getZoom();
            switch (direction) {
                case 'in':
                    Z = (Z < settings.zoom.max) ? Z + 1 : Z;
                    this.map.setZoom(Z);
                    break;
                case 'out':
                    Z = (Z > settings.zoom.min) ? Z - 1 : Z;
                    this.map.setZoom(Z);
                    break;
            }
        },

        setMapType: function (e, type) {
            var link = e.target;
            var menu = $(link).closest('ul');
            var items = menu.find('li');

            items.removeClass('active');
            $(link).closest('li').addClass('active');

            this.map.setMapTypeId(type);
        },

        transmogrify: function (opt) {
            return {
                position: new google.maps.LatLng(opt.LBi.pos.lat, opt.LBi.pos.lng),
                details: opt.details || settings.paths.balloon,
                map: this.map,
                icon: opt.icon,
                //  icon: settings.paths.icons + opt.icon + '.png', PATH IS SPECIFIED IN JSON
                title: opt.title,
                flat: true,
                LBi: {
                    ID: opt.LBi.ID,
                    title: opt.LBi.title,
                    theme: opt.LBi.theme,
                    active: opt.LBi.active,
                    draggable: (opt.LBi.draggable) ? settings.paths.icons + opt.LBi.draggable + '.png' : undefined
                }
            }
        }
    };

    /**
    * Markers
    * 
    */
    Maps.Markers = {

        /**
        * Marker
        * 
        */
        Marker: LBi.Class.extend(

			google.maps.Marker,

			function (opt) {
			    if (opt.LBi.draggable) {
			        google.maps.event.addListener(this, 'mousedown', function () { this.drag.start(this, opt.LBi.draggable); });
			        google.maps.event.addListener(this, 'mouseup', function () { this.drag.end(this, opt.icon); });
			    }

                this.setDraggable(true);

			    this.balloon = new Interpolis.Maps.Markers.Balloon(opt, this);
			    if (opt.LBi.active) {
			        this.balloon.inflate();
			    }

			    google.maps.event.addListener(this, 'click', function () {
			        this.balloon.inflate();

			        if (opt.LBi.title) {
			            var stat = '/Community/kaart/' + opt.LBi.theme + '/' + opt.LBi.title + '/view';
			            if (stat && window.pageTracker && opt.LBi.theme) {
			                window.pageTracker._trackPageview(stat);
			            }
			        }
			    });

			    if (/idea/i.test(opt.icon)) {
			        this.updateLocation();
			    }
			}, {

			    drag: {
			        start: function (self, icon) {
			            self.setIcon(icon);
			            self.balloon.deflate();
			            var pC = Interpolis.Maps.PROJECTION;

			            $('#google-map').bind('mousemove', function (e) {

			                P = pC.fromLatLngToDivPixel(self.getPosition());
			                C = pC.fromLatLngToDivPixel(Interpolis.Maps.map.getCenter());

			                P.x = e.pageX - $(this).offset().left + C.x - 478;
			                P.y = e.pageY - $(this).offset().top + C.y - 206;

			                if (self.balloon.element) self.balloon.setPosition(pC.fromDivPixelToLatLng(P));
			                self.setPosition(pC.fromDivPixelToLatLng(P));
			            });
			        },

			        end: function (self, icon) {
			            self.setIcon(icon);
			            $('#google-map').unbind();
			            self.updateLocation();
			        },

			        remove: function (self) {
			            google.maps.event.clearListeners(self, 'mousedown');
			            google.maps.event.clearListeners(self, 'mouseup');
			        }
			    },

			    updateLocation: function () {
			        var self = this;
			        var pos = this.getPosition();
			        GC.geocode({ latLng: pos }, function (response) {
			            self.setLocation(response[0].formatted_address);
			        });
			    },

			    setLocation: function (address) {
			        this.address = address;
			        LBi.Dispatcher.fire('idea-updated');
			    },

			    getLocation: function () {
			        return this.address;
			    },

			    decorate: function (response) {
			        var balloon = this.balloon;
			        balloon.element = $(response);
			        var B = this.balloon;

			        balloon.element.find('[rel=popup]').click(function () { B.deflate(); });
			        balloon.element.find('[rel=close]').click(function () { B.deflate(); });

			        balloon.setMap(Interpolis.Maps.map);

			        setTimeout(function () {
			            // draw follows setMap after a slight delay :( but is required to run before panning
			            balloon.panIntoView();
			        }, 500);
			    },



			    remove: function () {
			        this.balloon.remove();
			        this.balloon = null;
			        this.setMap(null);
			    },

			    balloon: null
			}
		),

        /**
        * Balloon marker
        * 
        */
        Balloon: LBi.Class.extend(

			google.maps.OverlayView,

			function (opt, marker) {
			    this.opt = opt;
			    this.element = null;
			    this.marker = marker;
			}, {

			    draw: function () {
			        if (!this.initialized) {
			            var target = $(this.getPanes().overlayMouseTarget);
			            LBi.DOM.append(target, this.element);
			            this.setPosition(this.marker.getPosition());
			            this.initialized = true;
			        }
			    },

			    remove: function () {
			    	if(this.initialized) {
			        this.deflate();
			        this.setMap(null);
			        this.initialized = false;
			      }
			    },

			    panIntoView: function () {
			        var sw = this.marker.getPosition();
			        var pr = this.getProjection();

			        if (!Interpolis.Maps.PROJECTION) {
			            Interpolis.Maps.PROJECTION = pr;
			        }

			        if (pr && this.initialized) {
			            var node = this.element[0];
			            var left = node.offsetLeft + node.offsetWidth;
			            var top = node.offsetTop;
			            var point = new google.maps.Point(left, top);
			            var ne = pr.fromDivPixelToLatLng(point);
			            var bounds = new google.maps.LatLngBounds(sw, ne);
			            Interpolis.Maps.map.panTo(bounds.getCenter());
			        }
			    },

			    inflate: function () {
			        var self = this;

			        Interpolis.Maps.deflateIdeas();

			        $.ajax({
			            type: 'GET',
			            data: '',
			            contentType: 'application/x-www-form-urlencoded',
			            url: this.opt.details,

			            success: function (response) {
			                var stat = $(response).find('span.analytics').html();
			                if (stat != null) {
			                    window.pageTracker._trackPageview(stat);
			                }
			                $(response).remove('span.analytics');
			                self.marker.decorate(response);
			            }
			        });
			    },

			    deflate: function () {
			        if (this.element) this.element.remove();
			        this.initialized = false;
			        this.element = null;
			    },

			    setPosition: function (LatLng) {
			        pos = this.getProjection().fromLatLngToDivPixel(LatLng);
			        if (this.element) this.element.css({ left: pos.x - 20, top: pos.y - (this.element.height() + 28) });
			    }
			}
		)
    };

    LBi.subscribe('initialize', function () {
        Maps.init();
    });

    return Maps;

})(jQuery);

