//Wrapper for no conflict
var MapUtilsWrapper =
{
    init: function()
    {
        this.bindFunction();
        this.calculateNumElements();
        this.setContainerDataIndex();

        $($('[data-add="location"]').find('input:first')).devbridgeAutocomplete({
            serviceUrl:  Routing.generate('cs_admin_map_locations_search_user_locations'),
            minChars: 3,
            maxHeight: 400,
            width: 'auto',
            zIndex: 99999,
            noCache: false,
            onSelect: function (suggestion) {
                $(this).val('');

                if(!MapUtilsWrapper.locationExists(suggestion.id)) {
                    var prototype = MapUtilsWrapper.container.insertPrototype();
                    
                    prototype
                        .remove()
                        .appendTo(MapUtilsWrapper.container);

                    $(prototype).data('element-index', MapUtilsWrapper.container.data('index')-1);

                    var data = { params: {}, data:{}};

                    data.params.container = MapUtilsWrapper.container;

                    data.data = suggestion;

                    //var latLngJson = JSON.parse(suggestion.data);

                    var latLng = new google.maps.LatLng(suggestion.data.lat, suggestion.data.lng);

                    map.setSimpleMarker(latLng);

                    MapUtilsWrapper.fillFormCollectionRow(data);
                }
                else {
                    msg = Translator.trans('cs_cms.maps.search.errors.location_suggest_exists');
                    showToastrNotification('error', msg);
                }
            },
            dataType: 'json'
        });
    },
    container: $($(".cs_map_locations").find("[data-prototype]")[0]),
    numElements : 0,
    calculateNumElements: function() {
        this.numElements = (this.container.children('tr').length)/2;
    },
    setContainerDataIndex :  function()
    {
        if( !isNaN(this.numElements) || this.numElements > 0 ) {
            this.container.data('index', this.numElements);
        }
    },
    bindFunction: function()
    {
        $(this.container).on('click', '.location-form-edit-location', function() {
            var editBlock = $(this).parents('tr:first').next();
            if (!editBlock.is(':visible')) {
                editBlock.show();
            }
            else {
                editBlock.hide();
            }
        })
        .on('click', '.location-form-delete-location', function() {
            var index = $(this).parents('tr:first').data('element-index');
            var id = $('#'+$(this).parents('tr:first').data('id-input')).val();
            $(this).parents('tr:first')
                .next()
                .remove()
                .end()
                .remove();

            MapUtilsWrapper.removeLocation(id);
            map.removeMarker(index);
        }).on('change update', '[data-field-update]', function() {
            var id = $('#'+$(this).parents('tr:first').data('id-input')).val();
            var field = $(this).data('field-update');
            var value = $(this).val();
            MapUtilsWrapper.updateMapLocationField(id, field, value);
        });
    },
    createEditable : function() {
        $('[data-plugin="editable"]').editable({
            validate: function (value) {
                if ($.trim(value) == '') {
                    return Translator.trans('cs_common_base.form.messages.errors.required');
                }
                else{
                    $('#'+$(this).data('for')).val(value).trigger('change');
                }
            },
            mode: 'inline'
        })
        .on('click', function(){
            $('.editable-input :first-child').select().addClass('form-control');
        })
        ;
    },
    geocoderResponseParser: function( result, status ) {
        if( status === google.maps.GeocoderStatus.OK )
        {
            map.result = result[0];
            map.change();
        }
        else
        {
            map.result = null;
            map.fail();
        }
    },
    googleMapsToComitium: function() {
        var addressComponents = map.parseAddressComponents(map.result.address_components);

        addressComponents = MapUtilsWrapper.arrayToJson(addressComponents);

        var params = { addressComponents : addressComponents, container : map.locationsContainer };

        Q.fcall(MapUtilsWrapper.locationTransformRequest, map.transformUrl, params )
            .then(MapUtilsWrapper.fillFormCollectionRow)
            .catch(function (error) {})
            .done();
    },
    locationTransformRequest: function( url, params ) {
        var d = Q.defer();

        var doneCallback = function(data)
        {
            var result = { data: data, params: params };
            d.resolve(result);
        };

        var failCallback = function()
        {
            d.reject(new Error(jqXHR.responseText));
        };

        $.post( url, { addressComponents :  params.addressComponents } )
            .done(doneCallback)
            .fail(failCallback);

        return d.promise;
    },
    fillFormCollectionRow: function( data ) {

        var index = $(data.params.container).data('index');
        index--;
        var latLng = map.getMarkerLatLang(index);

        var titleValue = '';

        if( typeof data.data.title !== 'undefined') {
            titleValue = data.data.title;
        } else {
            titleValue =  $('[data-add="location"]').find('input:first').val();
        }

        $("input[id$='_mapLocations_"+index+"_title']").val(titleValue).prev().html(titleValue).end().parents('tr:first').find('.info-icon').parent().append(data.data.type);

        $("input[id$='_mapLocations_"+index+"_address']").val( data.data.address );
        //Clean search input
        $('[data-add="location"]').find('input:first').val('');

        $("input[id$='_mapLocations_"+index+"_data']").val(JSON.stringify(latLng));

        if( typeof data.data.postal_code !== 'undefined' ) {
            $("input[id$='_mapLocations_"+index+"_postal_code']").val(data.data.postal_code);
        }

        if( typeof data.data.city !== 'undefined' ) {
            $("input[id$='_mapLocations_"+index+"_city']").val(data.data.city);
        }

        if( typeof data.data.province !== 'undefined' ) {
            $("input[id$='_mapLocations_"+index+"_province']").val(data.data.province);
        }

        if( typeof data.data.country !== 'undefined' ) {
            $("input[id$='_mapLocations_"+index+"_country']").val(data.data.country);
        }

        if( typeof data.data.zoom !== 'undefined' ) {
            $("input[id$='_mapLocations_"+index+"_zoom']").val(data.data.zoom);
        }

        $("input[id$='_mapLocations_"+index+"']").val(data.data.id);

        $(data.params.container).children('tr:even').show();

        MapUtilsWrapper.addLocation(data.data.id);

        MapUtilsWrapper.createEditable();
    },
    arrayToJson : function( array )
    {
        var json = {};
        for(var key in array )
        {
            //@TODO Mirar si hi ha alguna forma de posar la key amb format objecte Ex: json.key = array[key]
            json[key] = array[key];
        }

        return json;
    },
    initMap: function()
    {
        if( $('#cs_map').is(':visible') )
        {
            if( typeof map === 'undefined' || !(map instanceof ComitiumMaps) )
            {
                map = new ComitiumMaps();
                map.setLocationContainer(MapUtilsWrapper.container);
                var self = MapUtilsWrapper;
                MapUtilsWrapper.container.find("input[id$='_data']").each(function()
                {
                    var coords = JSON.parse($(this).val());
                    var latlng = new google.maps.LatLng(coords.lat, coords.lng);
                    map.setSimpleMarker(latlng);
                    self.addLocation(parseInt($(this).siblings(':last').val()));
                });

                var callback =  function() {
                    var zoomLevel = map.getZoom();
                    map.setManuallyZoomChanged(true);
                };

                map.addEventListenersToGoogleMaps('zoom_changed', callback );
            }
        }
    },
    updateMapLocationField: function(id, field, value)
    {
        $.post( Routing.generate('cs_admin_map_locations_update_field'), { id: id, field: field, value: value }, function(data)
        {
            //if( parseInt(data.status) === 200)
            //{
            //    showToastrNotification('success', data.msg);
            //}
            //else
            //{
            //    showToastrNotification('error', data.msg);
            //}
        });
    },
    locations: [],
    addLocation: function(id)
    {
        id = parseInt(id);
        if(!this.locationExists(id))
        {
            this.locations.push(id);
        }
    },
    removeLocation: function(id)
    {
        id = parseInt(id);
        var index = this.locations.indexOf(id);

        if( this.locationExists(id) )
        {
            this.locations.splice(index, 1);
        }
    },
    locationExists: function(id)
    {
        id = parseInt(id);
        return  this.locations.indexOf(id) !== -1;
    }
}

MapUtilsWrapper.container.collection({
    button_template: MapUtilsWrapper.container.data('button-prototype'),
    label: false,
    insert: 'append',
    childrenFilter: 'tr',
    insertButtonSelector: '[data-add="location"]',
    afterCreate: function (e)
    {

    },
    beforeCreate: function(e)
    {
        var element = $(e.detail.element);
        element.hide();

        var index = MapUtilsWrapper.container.data('index');
        element.each(function()
        {
            $(this).data('element-index', index );
        });

        var location = $('[data-add="location"]').find('input:first').val();
        map.searchPlace(location);
    }
});

MapUtilsWrapper.createEditable();

function ComitiumMaps( options )
{
    var defaultOptions =
    {
        zoom: 2,
        center: new google.maps.LatLng(41.3891577, 2.1702614),
        mapTypeId: google.maps.MapTypeId.ROADMAP,
        mapContainer: 'cs_map'
    };

    this.defaultOptions = $.extend(defaultOptions, options);
    this.markers = [];
    this.zoom = this.defaultOptions.zoom;
    this.mapContainer = this.defaultOptions.mapContainer;
    this.map = new google.maps.Map(document.getElementById(this.mapContainer), this.defaultOptions);
    this.result = null;
    this.locationsContainer = null;
    this.transformUrl = Routing.generate('cs_admin_location_transform');
    this.manuallyZoomChanged = false;

    //@TODO comprobar si aixo es pot fer de alguna altra manera
    //@TODO Millorar el estat del objecte al fer el flux asincron
    //google.maps.Map.call( this,  document.getElementById(this.mapContainer), options );

    this.signals.add(MapUtilsWrapper.googleMapsToComitium);
}

ComitiumMaps.prototype.searchPlace = function( address )
{
    var locationSearcher = new google.maps.Geocoder(this.map);
    var request = { address : address };

    locationSearcher.geocode(request, MapUtilsWrapper.geocoderResponseParser );
}

ComitiumMaps.prototype.setMarker = function(location)
{
    //var customMarker = new google.maps.MarkerImage('http://assets0.domestika.org/avatars/000/066/170/66170-large.png?1418119928');
    var marker = new google.maps.Marker({
        map: this.map,
        position: location.geometry.location,
        draggable:true,
        animation: google.maps.Animation.DROP
        //icon: busMarkerImage
    });

    //var comitiumAddressComponents = this.parseAddressComponents(location.address_components);
    //marker.formatted_address = location.formatted_address;
    //marker.address_components = location.address_components;
    //marker.comitiumAddressComponents = comitiumAddressComponents;

    this.addMarker(marker);
}

ComitiumMaps.prototype.setSimpleMarker = function( latLng )
{
    var marker = new google.maps.Marker({
        map: this.map,
        position: latLng,
        draggable: true,
        animation: google.maps.Animation.DROP
    });

    this.addMarker(marker);
}

ComitiumMaps.prototype.addMarker = function(marker)
{
    var self = this;
    google.maps.event.addListener(marker, 'dragend', function(evt){
        //console.log('<p>Marker dropped: Current Lat: ' + evt.latLng.lat().toFixed(3) + ' Current Lng: ' + evt.latLng.lng().toFixed(3) + '</p>');
        var data = { lat: evt.latLng.lat(), lng:  evt.latLng.lng() };
        var index = self.markers.indexOf(marker);
        $("input[id$='_mapLocations_"+index+"_data']").val(JSON.stringify(data)).trigger('change');
    });

    var latLng = marker.getPosition();
    this.setCenter(latLng);
    this.markers.push(marker);
}

ComitiumMaps.prototype.removeMarker = function(index)
{
    if( this.markerExists(index) )
    {
        this.markers[index].setMap(null);
    }
}

ComitiumMaps.prototype.getMarkerLatLang = function(index)
{
    if( this.markerExists(index) )
    {
        var position = this.markers[index].getPosition();

        return { lat : position.lat(), lng : position.lng() };
    }
}

ComitiumMaps.prototype.markerExists = function(index)
{
    return typeof this.markers[index] !== 'undefined';
}

ComitiumMaps.prototype.parseAddressComponents = function( addressComponents )
{
    var parsedComponents = [];
    for( var i = 0; i < addressComponents.length; i++ )
    {
        for(var j = 0; j < addressComponents[i].types.length; j++ )
        {
            switch(addressComponents[i].types[j])
            {
                case 'street_number':
                    this.setComponent(parsedComponents, 'street_number', addressComponents[i].long_name);
                    break;
                case 'postal_code':
                    this.setComponent(parsedComponents, 'postal_code', addressComponents[i].long_name);
                    break;
                case 'route':
                case 'street_address':
                case 'intersection':
                    this.setComponent(parsedComponents, 'address', addressComponents[i].long_name);
                    break;
                case 'locality':
                    this.setComponent(parsedComponents, 'locality', addressComponents[i].long_name);
                    break;
                case 'administrative_area_level_2':
                    this.setComponent(parsedComponents, 'province', addressComponents[i].long_name);
                    break;
                case 'administrative_area_level_1':
                    this.setComponent(parsedComponents, 'comunitat_autonoma', addressComponents[i].short_name);
                    break;
                case 'country':
                    this.setComponent(parsedComponents, 'country', addressComponents[i].short_name);
                    break;
                default:
                    break;
            }
        }
    }

    parsedComponents['zoom'] = this.getZoom();
    parsedComponents['data'] = this.getMarkerLatLang((this.markers.length-1));
    parsedComponents['title'] = $('[data-add="location"]').find('input:first').val();

    return parsedComponents;
}

ComitiumMaps.prototype.setComponent = function( array, key, value )
{
    array[key] = value;
    array.length++;
}

ComitiumMaps.prototype.getZoom = function()
{
    return this.map.getZoom();
}

ComitiumMaps.prototype.setZoom = function(zoom)
{
    this.map.setZoom(zoom);
}

ComitiumMaps.prototype.createLatitudeAndLongitudeObject = function( latitude, longitude )
{
    return new google.maps.LatLng(latitude, longitude);
}

ComitiumMaps.prototype.change = function()
{
    if( this.result !== null )
    {
        this.setMarker(this.result);
        this.signals.dispatch();
    }

}

/**
 *@argument latitude or google.maps.LatLng
 @argument longitude
 *
 */
ComitiumMaps.prototype.setCenter = function()
{
    var latLng = ( arguments.length > 1 ) ? this.createLatitudeAndLongitudeObject( arguments[0], arguments[1] ) : arguments[0];

    this.map.setCenter(latLng);

    if(this.isManuallyZoomChanged())
    {
        this.setZoom(this.getZoom());
    }
    else
    {
        this.setZoom(15);
    }
}

ComitiumMaps.prototype.fail = function( status )
{
    /* @TODO do tostr messages
     *
     * ERROR	There was a problem contacting the Google servers.
     * INVALID_REQUEST	This GeocoderRequest was invalid.
     * OK	The response contains a valid GeocoderResponse.
     * OVER_QUERY_LIMIT	The webpage has gone over the requests limit in too short a period of time.
     * REQUEST_DENIED	The webpage is not allowed to use the geocoder.
     * UNKNOWN_ERROR	A geocoding request could not be processed due to a server error. The request may succeed if you try again.
     * ZERO_RESULTS	No result was found for this GeocoderRequest.
     */
    var msg = '';
    if( status === google.maps.GeocoderStatus.ZERO_RESULTS )
    {
        msg = Translator.trans('cs_cms.maps.search.no_results');
        showToastrNotification('error', msg);
    }
    else
    {
        msg = Translator.trans('cs_cms.maps.search.no_results');
        showToastrNotification('error', msg);
    }

    var index = $(this.locationsContainer).data('index') > 0 ? $(this.locationsContainer).data('index')-1 : $(this.locationsContainer).data('index');
    $(this.locationsContainer).data('index', index);

    $(this.locationsContainer).children().filter(function() {
        return $(this).data('element-index') == index;
    }).remove();
}

ComitiumMaps.prototype.signals = new signals.Signal();

ComitiumMaps.prototype.setLocationContainer = function( container )
{
    this.locationsContainer = container;
}

ComitiumMaps.prototype.addEventListenersToGoogleMaps = function(event, callback)
{
    google.maps.event.addListener( this.map, event, callback );
}

ComitiumMaps.prototype.isManuallyZoomChanged = function()
{
    return this.manuallyZoomChanged;
}

ComitiumMaps.prototype.setManuallyZoomChanged = function( manuallyZoomChanged )
{
    this.manuallyZoomChanged = manuallyZoomChanged;
}
//END Comitium5 google maps wrapper
