/**
 * jQuery Gmap plugin file.
 */
(function($) {


    //GoogleMap class
    function GoogleMap(elementId, options) {
        this.map;
        this.geocoder;
        this.marker;
        this.initDone = false;
        this.elementId = elementId;
        this.addressData;
        this.boundsChanged = false;
        this.afterInit = function() {
        };
        this.onUpdateInputs = function() {
        };

        this.settings = $.extend({}, $.fn.gmap.defaults, options || {});
    }

    //GoogleMap class methods
    $.extend(GoogleMap.prototype, {

        /**
         * init()
         */
        init:function() {

            if (this.initDone) return this;

            var latlng = new google.maps.LatLng(this.settings.defaultLat, this.settings.defaultLng);
            var mapOptions = {
                zoom: this.settings.defaultZoom,
                center: latlng,
                mapTypeControl: true,
                /*scrollwheel: false,*/
                mapTypeId: google.maps.MapTypeId.ROADMAP,
                zoomControl: false,
                mapTypeControl: false
            }
            this.map = new google.maps.Map(document.getElementById(this.elementId), mapOptions);

            google.maps.event.addListener(this.map, "zoom_changed", jQuery.proxy(this.onZoomChanged, this));
            google.maps.event.addListener(this.map, "bounds_changed", jQuery.proxy(this.onBoundsChanged, this));
            this.geocoder = new google.maps.Geocoder();
            this.initDone = true;
            this.settings.afterInit.call();
            return this;
        },

        onBoundsChanged:function() {
            this.boundsChanged = true;
        },
        /**
         * findAddress
         */
        findAddress:function(address) {
            this.geocoder.geocode({'address': address, 'language': 'en'}, $.proxy(function(results, status) {
                if (status == google.maps.GeocoderStatus.OK) {
                    this.addressData = results[0]; //prvy najdeny

                    this.setMarker(this.getAddressGps());
                    //zoom to address bounds
                    this.fitAddressBounds();
                    this.updateInputs();


                }
            }, this));
        },

        findLocation:function(location, zoom) {


            this.geocoder.geocode({'location': location, 'language': 'en'}, $.proxy(function(results, status) {
                if (status == google.maps.GeocoderStatus.OK) {
                    this.addressData = results[0]; //prvy najdeny
                    var addressGPS = this.getAddressGps();
                  
                    this.map.setZoom(zoom);
                    this.setMarker(addressGPS);
                    //zoom to address bounds
                    //this.fitAddressBounds();
                    this.updateInputs();


                }
            }, this));
        },
        /**
         * fitAddressBounds
         */
        fitAddressBounds:function(addressData) {
            addressData = $.extend({}, this.addressData, addressData || {});
            this.map.fitBounds(this.addressData.geometry.bounds ? this.addressData.geometry.bounds : this.addressData.geometry.viewport);
        },
        /**
         * setMarker
         */
        setMarker:function(position) {
            if (!this.marker) {
                var markerOptions = {
                    map: this.map,
                    position: position,
                    clickable: false,
                    draggable: true,
                    animation: google.maps.Animation.DROP
                };
                this.marker = new google.maps.Marker(markerOptions);
                google.maps.event.addListener(this.marker, "dragend", $.proxy(this.onMarkerDragEnd, this));
            }
            else {
                this.marker.setPosition(position);
            }
            this.map.setCenter(position);


            if (!this.addressData) {
                this.findLocation(position);
            }


        },
        /**
         * onZoomChanged
         */
        onZoomChanged:function(data) {
            this.updateInputs();
        },
        /**
         * onMarkerDragEnd
         */
        onMarkerDragEnd:function(data) {
//            console.log('onMarkerDragEnd');
            this.geocoder.geocode({'location': data.latLng, 'language': 'en'}, $.proxy(function(results, status) {
//                console.log(status);
                if (status == google.maps.GeocoderStatus.OK) {
                    this.addressData = results[0]; //prvy najdeny
                    this.updateInputs();
                }

            }, this));
        },
        /**
         * getAddressGps
         */
        getAddressGps:function(addressData) {
            addressData = $.extend({}, this.addressData, addressData || {});
            if (!addressData.geometry) return '';
            return addressData.geometry.location;
        },
        /**
         * getAddressCountry
         */
        getAddressCountry:function(addressData) {
            addressData = $.extend({}, this.addressData, addressData || {});
            var addressComponents = addressData.address_components;
            for (var i = 0; i < addressComponents.length; i++) {
                if (addressComponents[i].types[0] == 'country') {
                    return addressComponents[i].long_name;
                }
            }
            return "";
        },
        /**
         * getAddressCity
         */
        getAddressCity:function(addressData) {
            addressData = $.extend({}, this.addressData, addressData || {});
            var addressComponents = addressData.address_components;

            var lastLocality = 'undefined';
            if (!addressComponents) return '';
            for (var i = 0; i < addressComponents.length; i++) {
                if (addressComponents[i].types[0] == 'locality') {
                    lastLocality = addressComponents[i].long_name;
                }
            }
            return lastLocality;
        },
        /**
         * getGpsLat
         */
        getGpsLat:function(addressData) {
            addressData = $.extend({}, this.addressData, addressData || {});

            var gps = this.getAddressGps(addressData);
            return gps.lat();
        },
        /**
         * getGpsLong
         */
        getGpsLong:function(addressData) {
            addressData = $.extend({}, this.addressData, addressData || {});

            var gps = this.getAddressGps(addressData);
            return gps.lng();
        },

        /**
         * updateInputs
         */
        updateInputs:function() {
            if (this.addressData) {
                var input = this.settings.inputs;
                $('#' + input.gmapCountry).val(this.getAddressCountry());
                $('#' + input.gmapCity).val(this.getAddressCity());
                $('#' + input.gmapGpsLat).val(this.getGpsLat());
                $('#' + input.gmapGpsLong).val(this.getGpsLong());
                $('#' + input.gmapZoom).val(this.map.getZoom());
            }


            var listener = google.maps.event.addListener(this.map, "idle", $.proxy(function() {

                this.onUpdateInputs.call();
                google.maps.event.removeListener(listener);

            }, this));
            this.settings.autoSave.call();


        },

        setCenter:function(position) {
            this.map.setCenter(position);
        },

        setZoom:function(zoom) {
            this.map.setZoom(zoom);
            // alert(this.map.getZoom());
        },
        checkResize:function() {
           
                google.maps.event.trigger(this.map, 'resize');
        }
    });

    //plugin code
    $.extend($.fn, {
        gmap:function(options) {
            //TODO: try to implement return this.each, to apply to all matched elements
            var gmap;
            var $this = $(this);
            //read gmap from data cache
            gmap = $this.data('gmap');
            if (!gmap) {
                gmap = new GoogleMap($this.attr('id'), options);
                //save gmap to data cache
                $this.data('gmap', gmap)
                //input autogenerating
            }
            return gmap;
        }
    });

    //plugin defaults settings
    $.fn.gmap.defaults = {
        inputs: {
            gmapCountry : 'Member_gmap_country',
            gmapCity : 'Member_gmap_city',
            gmapGpsLat : 'Member_gps_lat',
            gmapGpsLong : 'Member_gps_long',
            gmapZoom : 'Member_gmap_zoom'
        },
        defaultLat : 48.77067246880509,
        defaultLng : 19.874267578125,
        defaultZoom : 8,
        afterInit:function() {
        },
        autoSave:function() {
            
        }
    };
})(jQuery);





