// legacy code noone understands...

$(function() {
    // info that was retrieved using template tags
    var id = '#id_geo_location',
        $infoDiv = $('#infoForMapScript'),
        staticsUrl = $('.statics', $infoDiv).text();

    var geocoder = new GClientGeocoder();
    var map = new GMap2($(id + '_uploader__map')[0]);
    var marker = null;
    var user_data = null;
    var user_address_data = null;

    var $tr = $(id + '_query').parent().parent();
    var $errorDiv = $tr.find('.mapError');
    var $errorContainer = $errorDiv.find('.errorlist li');
    if (!$errorContainer.length) {
        $errorContainer = $('<div class="error"></div>').
                          wrap('<ul class="errorlist"></ul>').
                          prependTo($errorDiv);
    }
    var ops = {
        default_data: {
            lng: -74.044913,
            lat: 40.689605,
            zoom: 14,
            edited: false,
            hints: "Statue of Liberty, New York, NY 10004, USA",
            hide: true
        },
        coords_field: $(id + '_hidden'),
        hints_field: $(id + '_hints'),
        query_field: $(id + '_query'),
        hide_checkbox: $(id + '_checkbox'),
        map_div: $(id + '_mapdiv'),
        address_fields: $('#id_address,input:hidden[name=city],' +
                          'input:hidden[name=zip]'),
        /* this is very markup dependant :(*/
        set_error: function(err) {
            $tr.addClass('showError');
            $errorContainer.html(err);
        },
        clear_error: function() {
            $tr.removeClass('showError');
            $errorContainer.html('');
        },
        clear_field: $(id + '_clear'),
        query_submit: $(id + '_search'),
        error_NOADDR: $('.noAddress', $infoDiv).text(),
        error_NARROW: $('.narrow', $infoDiv).text()
    };
    if (!ops.kreciol) {
        ops.kreciol = $('<span class="kreciol mapKreciol">&nbsp; </span>').
                      hide().insertAfter(ops.query_field);
    }

    ops.default_data.point = new GLatLng(ops.default_data.lat,
                                         ops.default_data.lng);

    geocoder.setBaseCountryCode('us');

    function busy() {
        ops.kreciol.show();
        ops.query_field.attr('disabled', 'disabled');
    }
    function done() {
        ops.kreciol.hide();
        ops.query_field.removeAttr('disabled');
    }

    function placemark_to_addressdict(placemark) {
        var country = placemark.AddressDetails.Country;
        var address = {};
        var state = null;
        if (country)
            state = country.AdministrativeArea;
        if (state) {
            address.state = state.AdministrativeAreaName;
            var region = state;
            while (!('Locality' in region) &&
                   'SubAdministrativeArea' in region) {
                region = region.SubAdministrativeArea;
                if (region.PostalCode) {
                    address.zip = region.PostalCode.PostalCodeNumber;
                }
            }
            var city = region.Locality || region.DependentLocality;
            if (city) {
                if (city.DependentLocality) { // willage
                    address.city = city.DependentLocality.
                                           DependentLocalityName;
                } else {
                    address.city = city.LocalityName;
                }
                if (!address.zip && city.PostalCode) {
                    address.zip = city.PostalCode.PostalCodeNumber;
                }
                if (city.Thoroughfare) {
                    address.address = city.Thoroughfare.ThoroughfareName;
                }
            }
        } else if (!address.zip && country && country.PostalCode) {
            address.zip = country.PostalCode.PostalCodeNumber;
        }
        return address;
    }

    function geocode_at(seed, recenter) {
        ops.hints_field.val('...');
        ops.clear_error();
        marker.hide();
        busy();
        geocoder.getLocations(seed, function(response) {
            if (response && response.Status.code == 200) {
                done();
                document.r = response;
                if (response.Placemark.length) {
                    var p = response.Placemark[0];
                    var coords = recenter ?
                                 new GLatLng(p.Point.coordinates[1],
                                             p.Point.coordinates[0]) :
                                 seed;

                    var addr = {
                        coords: coords,
                        hints: p.address,
                        viewport: new GLatLngBounds(
                            new GLatLng(p.ExtendedData.LatLonBox.south,
                                        p.ExtendedData.LatLonBox.west),
                            new GLatLng(p.ExtendedData.LatLonBox.north,
                                        p.ExtendedData.LatLonBox.east)),
                        accuracy: p.AddressDetails.Accuracy
                    };
                    var zoom = map.getBoundsZoomLevel(addr.viewport);
                    user_address_data = placemark_to_addressdict(p);
                    set_data(addr.coords, zoom, addr.hints, true, recenter,
                             user_address_data);
                } else {
                   ops.set_error(ops.error_NOADDR);
                }
            } else {
               done();
               ops.set_error(ops.error_NOADDR);
            }
        });
    }

    function geocode_address() {
        var new_query_field = '';
        ops.address_fields.each(function() {
            if ($(this).val())
                new_query_field += ', ' + $(this).val();
        });
        ops.query_field.val( new_query_field.substring(2)+', USA' );
        geocode_at(ops.query_field.val(), true);
    }

    function set_data(point, zoom, hints, save, recenter, extra_data) {
        // set hints for given location
        ops.hints_field.html(hints);

        // center map
        if (recenter) {
            map.setCenter(point, zoom);
        }

        // show marker
        marker.setLatLng(point);
        marker.show();

        // save data
        if (save) {
            // lowercase globals FTW :E
            user_data = {
                point: point,
                lng: point.lng(),
                lat: point.lat(),
                zoom: map.getZoom(),
                edited: true,
                hints: hints
            };

            $(ops.coords_field).val(JSON.stringify($.extend({
                lng: user_data.lng,
                lat: user_data.lat,
                zoom: user_data.zoom,
                edited: user_data.edited,
                hints: user_data.hints
            }, extra_data)));
        }
    }

    // add map controls
    map.addControl(new GLargeMapControl());
    map.addControl(new GScaleControl());
    map.addControl(new GMapTypeControl());
    map.enableDoubleClickZoom();
    map.enableContinuousZoom();
    map.clearOverlays();

    // create arrow icon
    var arrowIcon = new GIcon(G_DEFAULT_ICON,
                              staticsUrl + 'img/pennysaver/maps/ad.png');
    arrowIcon.shadow = staticsUrl + 'img/pennysaver/maps/ad_shadow.png';
    arrowIcon.iconAnchor = new GPoint(25, 100);
    arrowIcon.shadowAnchor = new GSize(0,0);
    arrowIcon.imageMap = [0,0,50,0,50,100,0,100];
    arrowIcon.iconSize = new GSize(50, 100);
    arrowIcon.shadowSize = new GSize(150,100);

    // does it ever pass? its run when there's no data so...
    try {
        var data = JSON.parse($(ops.coords_field).val());
        if (data.hide) {
            data = ops.default_data;
        }
    } catch(err) {
        // default value - statue of liberty:
        var data = ops.default_data;
    }

    if ((data.address || data.city || data.state || data.zip) && !data.hints) {
        var hints = [];
        if (data.address) {
            hints.push(data.address);
        }
        if (data.city) {
            hints.push(data.city);
        }
        if (data.state) {
            if (data.zip) {
                hints.push(data.state + ' ' + data.zip);
            } else {
                hints.push(data.state);
            }
        } else if (data.zip) {
            hints.push(data.zip);
        }
        data.hints = hints.join(', ');
    }
    marker = new GMarker(
        new GLatLng(parseFloat(data.lat), parseFloat(data.lng)),
        {
            draggable: true,
            clickable: false,
            icon: arrowIcon
        }
    );
    document.marker = marker;

    if ((!('lat' in data) || !('lng' in data)) && data.hints) {
        geocode_at(data.hints, true);
    }

    set_data(marker.getPoint(), data.zoom, data.hints, true, true);


    //-----------------
    //  add callbacks
    //-----------------

    GEvent.addListener(marker, "dragend", function() {
        geocode_at(marker.getPoint());
    });
    map.addOverlay(marker);

    GEvent.addListener(map, 'zoomend', function() {
        if (user_data) {
            set_data(user_data.point, user_data.zoom, user_data.hints, true,
                     false, user_address_data);
        }
    });

    GEvent.addListener(map, 'dblclick', function(overlay, latlng) {
        geocode_at(latlng);
    });

    ops.query_field.change(function() {
        geocode_at($(this).val(), true);
    });

    ops.query_submit.click(function() {
        geocode_at(ops.query_field.val(), true);
    });

    if (ops.clear_field) {
        ops.clear_field.click(function() {
            $(ops.coords_field).val('');
            geocode_address();
        });
    }

    ops.hide_checkbox.bind('hide_map', function() {
        $(this).removeAttr("checked");
        ops.coords_field.val('');
        ops.map_div.hide();
    });

    ops.hide_checkbox.bind('show_map', function() {
        $(this).attr("checked", true);
        ops.map_div.show();
    });

    ops.hide_checkbox.click(function() {
        if ($(this).attr("checked")) {
            geocode_address();
            ops.map_div.show();
        } else {
            ops.coords_field.val('');
            ops.map_div.hide();
        }
    });

    if (ops.coords_field.val() && !data.hide) {
        ops.hide_checkbox.triggerHandler('show_map')
    } else {
        ops.hide_checkbox.triggerHandler('hide_map')
    }

});

