var jQuery = jQuery || {};
var bm = bm || {};

bm.storeMap = (function ($) {

    var StoreMap = function (element, options) {
        this.$element = $(element);
        this.options = $.extend({}, StoreMap.DEFAULTS, options);
        this.storeList = false;
        this.gMarkers = false;
        this.gFitBounds = false;
        this.gBounds = false;
        this.gMap = false;
        this.gMarkerCluster = false;
        this.gMapInfoWindow = false;
        this.gAutocomplete = false;
        this.init();
    };

    StoreMap.VERSION = '0.0.1';

    StoreMap.DEFAULTS = {
        gAdditionalOptions: {
            infoWindow: true,
            centerMarker: true,
            fitBounds: true
        },
        mapConfiguration: {
            center: {
                lat: 51,
                lng: 9
            },
            gestureHandling: 'cooperative',
            zoom: 6,
            minZoom:4,
            scrollwheel: false,
            overviewMapControl: false,
            streetViewControl: false,
            panControl: false,
            mapTypeControl: false
        },
        markerIcon: '',
        clusterConfiguration: {},
        infoBoxConfiguration: {},
        autocompleteConfiguration: {
            use: true,
            field: '',
            options: {}
        }
    };

    StoreMap.prototype.init = function () {
        this.gMap = new google.maps.Map(this.$element.get(0), this.options.mapConfiguration);
        this.gMapInfoWindow = new InfoBubble(this.options.infoBoxConfiguration);
        if (this.options.autocompleteConfiguration.use) {
            autocompleteInit.call(this);
        }
        this.$element.trigger('init.bm.storemap');
    };

    StoreMap.prototype.update = function (options) {
        if (options) {
            this.options = $.extend({}, this.options, options);
        }
    };

    StoreMap.prototype.resize = function () {
        google.maps.event.trigger(this.gMap, 'resize');
    };

    StoreMap.prototype.updateStoreListCluster = function (results) {
        if (results.length > 0) {
            this.storeList = results;
            createMapMarkers.call(this);
            addMapMarkersToCluster.call(this);
            if (this.options.gAdditionalOptions.fitBounds) {
                fitMarkers.call(this);
            }
        } else {
            this.clearMap(this.options.mapConfiguration.center)
        }
    };

    StoreMap.prototype.clearAllMarkers = function () {
        this.gMarkerCluster.clearMarkers();
    };

    StoreMap.prototype.clearMap = function (geoData) {
        this.gMarkerCluster.clearMarkers();
        this.gMap.setZoom(10);
        this.gMap.setCenter(
            {
                lat: geoData.lat,
                lng: geoData.lng
            }
        );
    };

    StoreMap.prototype.getAutocompleteService = function () {
        return this.gAutocomplete;
    }

    var createMapMarkers = function () {
        var options = this.options;
        var map = this.gMap;
        var infoWindow = this.gMapInfoWindow;

        this.gMarkers = $.map(this.storeList, function (location, i) {
            var position = new google.maps.LatLng(
                parseFloat(location.lat),
                parseFloat(location.lng)
            );

            var marker = new google.maps.Marker({
                title: location.name,
                position: position,
                icon: options.markerIcon
            });
            if (options.gAdditionalOptions.infoWindow) {
                google.maps.event.addListener(marker,'click',function () {
                    if ($(window).width() < 991) {
                        $('body').trigger('bm.store.infowindow.mobile',location.infoWindow);
                    } else {
                        $(window).trigger('content.changed');
                        infoWindow.setContent(location.infoWindow);
                        infoWindow.open(map,marker);
                        if (options.gAdditionalOptions.centerMarker) {
                            map.setCenter(marker.getPosition());
                        }
                    }
                });
            }

            return marker;
        });
    };

    var addMapMarkersToCluster = function () {
        if (this.gMarkerCluster) {
            this.gMarkerCluster.clearMarkers();
        }
        this.gMarkerCluster = new MarkerClusterer(
            this.gMap, this.gMarkers, this.options.clusterConfiguration
        );
    };

    var fitMarkers = function () {
        var gBounds = new google.maps.LatLngBounds();
        $.map(this.gMarkers, function (marker, i) {
            gBounds.extend(marker.getPosition());
        });
        this.gBounds = gBounds;
        this.gMap.fitBounds(gBounds);
    };

    var autocompleteInit = function () {
        var self = this;
        var field = document.getElementById(this.options.autocompleteConfiguration.field);

        if ($(field).length > 0) {
            this.gAutocomplete = new google.maps.places.Autocomplete(field,this.options.autocompleteConfiguration.options)

                this.gAutocomplete.addListener('place_changed', function(){
                    try {
                        var location = this.getPlace().geometry.location;
                        $(field)
                            .data('lat', location.lat())
                            .data('lng', location.lng());

                    } catch (e) {
                        console.warn('Lat/Lng not found');
                        $(field)
                            .data('lat', false)
                            .data('lng', false);
                        //console.log(e);
                    }
                });

        }
    };

    // Contentfilter PLUGIN DEFINITION
    // ==========================

    function Plugin(option, additionalArguments) {
        return this.each(function () {
            var $this = $(this);
            var pluginData = $this.data('bm.storemap');

            if (!pluginData) {
                var options = $.extend({}, StoreMap.DEFAULTS, $this.data(), typeof option === 'object' && option);
                pluginData = new StoreMap(this, options);
                $this.data('bm.storemap', pluginData);
            } else {
                if (typeof option === 'string') {
                    pluginData[option](additionalArguments);
                } else {
                    pluginData.update(option);
                }
            }
        });

    }

    var old = $.fn.storemap;

    $.fn.storemap = Plugin;
    $.fn.storemap.Constructor = StoreMap;


    // Contentfilter NO CONFLICT
    // ====================

    $.fn.storemap.noConflict = function () {
        $.fn.storemap = old;
        return this;
    };


    // Contentfilter DATA-API
    // =================
}(jQuery));