/*global CHUMS, YAHOO, Y, google */
"use strict";

CHUMS.StoreMap = (function () {
        var URL = {
                DS_SEARCH: "/json/stores.json.php"
        },
        MILES_TO_METERS = 1609.344,
        elements = {
                content: null,
                form: null,
                debug: null,
                message: null
        },
        IDs = {
                CONTENT: "searchresults",
                FORM: "searchform",
                MAP: "googlemap",
                MESSAGE: "message",
                MAPICON: "mapicon"
        },
        lookup = {
                addresses: [],
                timer: null,
                delay: 2000
        },
        
        map = null,
        mapOptions = null,
        geocoder = null,
        infoWindow = null,
        markerImage = null,
        searchCircle = null,
        
        iconSrc = null,
        homeMarker = null,
        markers = [],
        markerListeners = [],
        browserSupportGeo = false,
        mapDefaults = {
                lat: 38.960332040195475,
                lng: -94.5219898223877,
                zoom: 4
        },
        loggedIn = false,
        init, search, searchCenter, getZoomLevel, clearMarkers, handleAddressClick, addAddress, setMarker, getNewLocations;
        
        init = function () {
                elements.form = Y.Dom.get(IDs.FORM);
                elements.content = Y.Dom.get(IDs.CONTENT);
                elements.message = Y.Dom.get(IDs.MESSAGE);
                loggedIn = (typeof elements.form.loggedin !== "undefined" && elements.form.loggedin.value === "1");
                                
                iconSrc = Y.Dom.get(IDs.MAPICON).src;
                
                //set up listeners
                Y.Event.addListener(elements.form, "submit", search);
                Y.Event.addListener(elements.content, "click", handleAddressClick);
                
                try {
                        mapDefaults.lat = elements.form.pos.value.substr(0, elements.form.pos.value.indexOf(","));
                        mapDefaults.lng = elements.form.pos.value.substr(elements.form.pos.value.indexOf(",") + 1, elements.form.pos.value.length);
                } catch (er) {
                        
                }
                
                
                mapOptions = {
                        zoom: 16,
                        center: new google.maps.LatLng(mapDefaults.lat, mapDefaults.lng),
                        mapTypeId: google.maps.MapTypeId.HYBRID
                };
                
                map = new google.maps.Map(Y.Dom.get(IDs.MAP), mapOptions);
                
                markerImage = new google.maps.MarkerImage(iconSrc, 
                        new google.maps.Size(24, 32),
                        new google.maps.Point(0, 0),
                        new google.maps.Point(16, 32));
                
                homeMarker = new google.maps.Marker({
                        clickable: true,
                        draggable: true,
                        map: map,
                        position: map.getCenter(),
                        title: "Your location"
                });
                google.maps.event.addListener(homeMarker, 'dragend', searchCenter);
                
                if (typeof navigator.geolocation !== "undefined") {
                        browserSupportGeo = true;
                        navigator.geolocation.getCurrentPosition(function (position) {
                                var initialLocation = new google.maps.LatLng(position.coords.latitude, position.coords.longitude);
                                map.setCenter(initialLocation);
                                homeMarker.setPosition(initialLocation);
                                searchCenter();
                        });
                }
                
                geocoder = new google.maps.Geocoder();
                infoWindow = new google.maps.InfoWindow();
        };
        
        handleAddressClick = function (ev) {
                var target = Y.Event.getTarget(ev),
                re = /cust_([0-9]+)$/, 
                id = null,
                div = document.createElement("DIV");
                while (target.id !== elements.content.id) {
                        id = target.id.match(re);
                        if (id !== null) {
                                Y.Dom.addClass(div, "customer_entry");
                                div.innerHTML = target.innerHTML;
                                infoWindow.setContent(div);
                                infoWindow.open(map, markers[id[1]]);
                                return;
                        }
                        target = target.parentNode;
                }
        };
        
        search = function (ev) {
                Y.Event.preventDefault(ev);
                map.setZoom(getZoomLevel());
                if (elements.form.homeaddress.value === "") {
                        YAHOO.lang.later(250, null, searchCenter);
                        homeMarker.setPosition(map.getCenter());
                        return;
                }
                geocoder.geocode({'address': elements.form.homeaddress.value}, function (results, status) {
                        if (status === google.maps.GeocoderStatus.REQUEST_DENIED) {
                                CHUMS.alertErrors("This webpage is not allowed to use the Google GeoCoder.");
                        } else if (status === google.maps.GeocoderStatus.INVALID_REQUEST) {
                                CHUMS.alertErrors("This GeocoderRequest was invalid.");
                        } else if (status === google.maps.GeocoderStatus.OVER_QUERY_LIMIT) {
                                CHUMS.alertErrors("This webpage has gone over the requests limit in too short a period of time.");
                        } else if (status === google.maps.GeocoderStatus.OK) {
                                map.setCenter(results[0].geometry.location);
                                homeMarker.setPosition(results[0].geometry.location);
                                searchCenter();
                        } else {
                                CHUMS.alertErrors("There was an error with this lookup. Please retry later.");
                        } 
                });
        };
        
        getZoomLevel = function () {
                var range = elements.form.range, 
                zoom = 6;
                
                switch (range.options[range.selectedIndex].value) {
                case '1': 
                        zoom = 14; 
                        break;
                case '10' : 
                        zoom = 11; 
                        break;
                case '25' : 
                        zoom = 10; 
                        break;
                case '50' : 
                        zoom = 9; 
                        break;
                case '100' : 
                        zoom = 8; 
                        break; 
                case '100' : 
                        zoom = 6; 
                        break; 
                case '1000' : 
                        zoom = 5; 
                        break; 
                case '5000' : 
                        zoom = 3; 
                        break; 
                }
                return zoom;
        };
        
        searchCenter = function () {
                elements.form.pos.value = homeMarker.getPosition().toUrlValue(6);
                Y.Connect.setForm(elements.form);
                Y.Connect.asyncRequest('get', URL.DS_SEARCH, {
                        success: function (o) {
                                var data, i, iLen, circleOpts;
                                try {
                                        data = YAHOO.lang.JSON.parse(o.responseText);
                                } catch (er) {
                                        CHUMS.alertErrors(o.responseText);
                                }
                                if (typeof data !== "undefined") {
                                        circleOpts = {
                                                center: homeMarker.getPosition(),
                                                radius: elements.form.range.value * MILES_TO_METERS,
                                                map: map,
                                                fillColor: '#666666',
                                                fillOpacity: 0.05,
                                                strokeColor: '#ff0000',
                                                strokeWeight: 2,
                                                strokeOpacity: 0.25
                                        };
                                        searchCircle = new google.maps.Circle(circleOpts);
                                        if (data.Customers.length === 0) {
                                                elements.content.innerHTML = "No results found within " + elements.form.range.value + " mile" + (elements.form.range.value === "1" ? "" : "s");
                                        } else {
                                                elements.content.innerHTML = 'Results [<span id="resultcount">0</span>/' + data.Customers.length + ']<hr>';
                                        }
                                        for (i = 0, iLen = data.Customers.length; i < iLen; i += 1) {
                                                addAddress(data.Customers[i]);
                                        }
                                }
                                lookup.timer = setTimeout(getNewLocations, lookup.delay);
                        },
                        failure: function (o) {
                                CHUMS.alertErrors(o.responseText || o.statusText);
                        },
                        timeout: 30000,
                        cache: false
                });
                clearMarkers();
                elements.content.innerHTML = "Reloading ...";
        };
        
        getNewLocations = function () {
                clearTimeout(lookup.timer);
                if (lookup.addresses.length > 0) {
                        var cust = lookup.addresses.shift();
                        geocoder.geocode({'address': cust.address + ", " + cust.csz}, function (results, status) {
                                var custEl;
                                if (status === google.maps.GeocoderStatus.REQUEST_DENIED) {
                                        CHUMS.alertErrors("This webpage is not allowed to use the geocoder.");
                                } else if (status === google.maps.GeocoderStatus.INVALID_REQUEST) {
                                        CHUMS.alertErrors("This GeocoderRequest was invalid.");
                                } else if (status === google.maps.GeocoderStatus.OVER_QUERY_LIMIT) {
                                        CHUMS.alertErrors("This webpage has gone over the requests limit in too short a period of time. Queries will now slow down.");
                                        lookup.delay *= 2;
                                        lookup.timer = setTimeout(getNewLocations, lookup.delay);
                                } else if (status === google.maps.GeocoderStatus.ERROR || status === google.maps.GeocoderStatus.UNKNOWN_ERROR) {
                                        lookup.timer = setTimeout(getNewLocations, lookup.delay);
                                } else if (status === google.maps.GeocoderStatus.OK) {
                                        cust.loc.lat = results[0].geometry.location.lat();
                                        cust.loc.lng = results[0].geometry.location.lng();
                                        setMarker(cust);
                                } else {
                                        custEl = Y.Dom.get("cust_" + cust.id);
                                        if (custEl !== null) {
                                                custEl.innerHTML = '<div class="customer">' + cust.customername + '</div><div class="address">Invalid: ' + cust.address + '</div>';
                                        }
                                }
                                
                                lookup.timer = setTimeout(getNewLocations, lookup.delay);
                        });
                }
        };
        
        addAddress = function (cust) {
                var div = document.createElement("DIV");
                div.id = 'cust_' + cust.id;
                Y.Dom.addClass(div, "customer_entry");
                div.innerHTML = '<div class="customer error">' + cust.customername + '</div>';
                elements.content.appendChild(div);

                if (cust.loc.lat !== null && cust.loc.lng !== null) {
                        setMarker(cust);
                } else {
                        lookup.addresses.push(cust);
                }
        };
        
        clearMarkers = function () {
                var i, iLen;
                for (i = 0, iLen = markers.length; i < iLen; i += 1) {
                        if (typeof markers[i] !== "undefined") {
                                markers[i].setMap(null);
                        }
                        if (typeof markerListeners[i] !== "undefined") {
                                google.maps.event.removeListener(markerListeners[i]);
                        }               
                }
                markers = [];
                markerListeners = [];
                lookup.addresses = [];
                if (typeof searchCircle !== 'undefined' && searchCircle !== null) {
                        searchCircle.setMap(null);
                        searchCircle = null;
                }
        };
        
        setMarker = function (cust) {
                var custEl, marker;
                
                custEl = Y.Dom.get("cust_" + cust.id);  
                custEl.innerHTML = '<div class="customer">' + cust.customername + '</div>' + 
                        '<div class="address">' + cust.address + '<br>' + cust.csz + '</div>' + 
                        (loggedIn === true ? '<div class="acct">' + cust.ardivisionno + '-' + cust.customerno + (cust.shiptocode !== '' ? ' [' + cust.shiptocode + ']' : '') + '</div>' : '') + 
                        '<div class="distance">Distance: ' + (Math.round((cust.distance * 10) / MILES_TO_METERS) / 10) + ' mi.</div>';
                
                marker = new google.maps.Marker({
                        position: new google.maps.LatLng(cust.loc.lat, cust.loc.lng),
                        map: map,
                        title: cust.customername,
                        icon: markerImage
                });
                markers[cust.id] = marker;
                markerListeners[cust.id] = google.maps.event.addListener(marker, 'click', function () {
                        Y.UserAction.click(custEl);
                });
                Y.Dom.get('resultcount').innerHTML = markers.length;
        };
        
        Y.Event.onDOMReady(init);
}());
