HAL = {
    openThePodBayDoors : function(){
        return console.log('I\'m sorry Greg, I\'m afraid I can\'t do that.');
    },
    _extended : false,
    _getTimeout : 300,
    please : {
        clearText : function(theField){
            if(thefield.defaultValue==thefield.value){ thefield.value = "" }
        },
        replaceText : function(thefield){
            if(thefield.value==""){ thefield.value = thefield.defaultValue }
        },
        preloadImages : function(){
            var d=document;
            if(d.images){
                if(!d.p) d.p=new Array();
                var i,j=d.p.length,a=preloadImages.arguments; for(i=0; i<a.length;i++)
                if(a[i].indexOf("#") != 0){
                    d.p[j]=new Image; d.p[j++].src=a[i];
                }
            }
        },
        handlePurchase : function(){
            HAL.hud.expand(function(){
                alert('You are being redirected to PayPal. When your transaction is completed, be sure to click the "return to merchant" link to receive your download immediately.');
                
                if($('form#download').length){
                    // Record event, then submit form
                    HAL.analytics.track.event('clicks','purchases','download-link',null,function(){
                        $('form#download').submit();
                    });
                }else{
                    return false;
                }
            });
        }
    },
    init : function(inits){
        // DOM Ready
        if($('#search input[type="text"]').val()) $('#search input[type="text"]').css('background-image','none');
        
        // Initialize extra inits
        if(inits) $.each(inits,function(i,obj){ if(typeof HAL[obj].init == 'function') HAL[obj].init(); });
    },
    maps : {
        _map : false,
        markers : [],
        windows : [],
        results : null,
        geocoder : null,
        distance : null,
        settings : {
            target : 'map',
            start_lat : 37.782516144529964,
            start_lon : -122.39229263305664,
            start_coord : [],
            map_options : {
                zoom : 13,
                center : null,
                mapTypeId : null,
                panControl : false,
                scaleControl : false,
                mapTypeControl : false,
                streetViewControl : false
            }
        },
        init : function(settings){
            // http://code.google.com/apis/maps/documentation/javascript/basics.html -- http://code.google.com/apis/maps/documentation/javascript/services.html#Geocoding
            if(settings) $.extend(HAL.maps.settings,settings);
            
            $('#search form').submit(function(){
                HAL.hud.search($('input[type="text"]',this).val());
                
                return false;
            });
            
            HAL.maps.settings.map_options.center = HAL.maps.coords([HAL.maps.settings.start_lat,HAL.maps.settings.start_lon]);
            HAL.maps.settings.map_options.mapTypeId = google.maps.MapTypeId.TERRAIN;
            HAL.maps._map = new google.maps.Map(document.getElementById(HAL.maps.settings.target),HAL.maps.settings.map_options);
        },
        coords : function(coords){
            return new google.maps.LatLng(coords[0],coords[1]);
        },
        search : function(val,c){
            // Initialize geocoder
            HAL.maps.geocoder = new google.maps.Geocoder();
            
            HAL.maps.geocoder.geocode({ address : val },function(results,status){
                HAL.maps.results = results;
                if(c) c(results,status);
            });
        },
        addMarker : function(location,settings){
            var i = (HAL.maps.markers.length)++;
            
            HAL.maps.markers[i] = new google.maps.Marker({
                map : HAL.maps._map,
                position : location,
                animation : (settings.animation) ? settings.animation : null,
                icon : (settings.icon) ? settings.icon : null
            });
            
            if(settings.infobox){
                HAL.maps.windows[i] = new google.maps.InfoWindow({
                    content : settings.infobox
                });
                
                google.maps.event.addListener(HAL.maps.markers[i],'click',function(){
                    HAL.maps.clearWindows();
                    HAL.maps.windows[i].open(HAL.maps._map,HAL.maps.markers[i]);
                });
            }
            
            if(settings.onComplete) settings.onComplete(HAL.maps.markers[i],HAL.maps.windows[i]);
        },
        clearMarkers : function(){
            $.each(HAL.maps.markers,function(i,item){
                item.setMap(null);
            });
        },
        clearWindows : function(){
            $.each(HAL.maps.windows,function(i,item){
                item.close();
            });
        }
    },
    hud : {
        collapse : function(c){
            $('#wrapper').fadeOut(600,function(){
                $('#search').animate({ marginTop : '20px' },300);
                $('#body').animate({ top : '20px', right : '320px' },300,function(){
                    if(c) c();
                });
            });
        },
        expand : function(c){
            $('#wrapper').fadeIn(600,function(){
                $('#search').animate({ marginTop : '100px' },300);
                $('#body').animate({ top : '20%', right : '50%' },300,function(){
                    if(c) c();
                });
            });
        },
        search : function(val){
            if(!val) val = $('#search input').val();
            var max = 100;
            
            HAL.hud.collapse(function(){
                HAL.maps.search(val,function(results){
                    if(typeof results[0] == 'undefined') return alert('Couldn\'t find any location with that name!');
                    
                    HAL.maps._map.setCenter(HAL.maps.coords([results[0].geometry.location.lat(),results[0].geometry.location.lng()+0.03]));
                    HAL.maps.clearMarkers();
                    HAL.maps.clearWindows();
                    
                    // Values of form
                    $('#search form input[name="lat"]').val(results[0].geometry.location.lat());
                    $('#search form input[name="lon"]').val(results[0].geometry.location.lng());
                    
                    HAL.ajax.post({
                        url : 'api/cities',
                        form : $('#search form'),
                        onSuccess : function(response){
                            $.each(response.data,function(i,location){
                                if(i > max) return false;
                                
                                HAL.maps.addMarker(HAL.maps.coords([location.city_lat,location.city_lon]),{
                                    infobox : '<div style="height: 100px; width: 300px; overflow: hidden;"><strong>'+location.city_name+'</strong><br /><strong>Zip Code:</strong> '+location.city_zip+'</em><br />County: '+location.city_county+'<br /><small><strong>'+location.distance+' miles away</strong> from '+results[0].formatted_address+'</small><br /></div><a href="javascript:{};" onclick="HAL.please.handlePurchase(); return false;" class="get-it-now"><span>download</span> Get MySQL Cities (.sql, 2.6MB)</a></div>'
                                });
                            });
                            
                            // Add initial pin
                            setTimeout(function(){
                                HAL.maps.addMarker(HAL.maps.coords([results[0].geometry.location.lat(),results[0].geometry.location.lng()]),{
                                    infobox : '<div style="height: 60px; width: 280px; overflow: hidden;"><strong>'+results[0].formatted_address+'</strong><br /><em><small>Click on any of the red pins on the map for more information about locations nearby.</small></em></div><a href="javascript:{};" onclick="HAL.please.handlePurchase(); return false;" class="get-it-now"><span>download</span> Get MySQL Cities (.sql, 2.6MB)</a>',
                                    animation : google.maps.Animation.DROP,
                                    icon : 'assets/images/marker_blue.png',
                                    onComplete : function(marker,window){
                                        setTimeout(function(){
                                            window.open(HAL.maps._map,marker);
                                        },800);
                                    }
                                });
                            },800);
                        }
                    });
                });
            });
        }
    },
    ajax : {
        settings : {
            'form' : false,
            'url' : false,
            'ajaxVars' : false,
            'okFlag' : 'ok',
            'errorFlag' : 'error',
            'onComplete' : false,
            'onParseError' : false,
            'onSuccess' : function(data){
                return true;
            },
            'onError' : function(data){
                alert((data.message) ? data.message : 'Error!');
            }
        },
        log : function(s){
            if(typeof console !== 'undefined') console.log(s);
        },
        post : function(settings,cb){
            // Defaults
            HAL.ajax.settings.ajaxVars = false; // Clear ajax variables each time function is called
            if(settings) $.extend(HAL.ajax.settings,settings); // Redefine settings (ajax vars, callbacks, etc.)
            if(cb) HAL.ajax.settings.onSuccess = cb; // Allow callback to be defined without using settings
            if(!HAL.ajax.settings.url && typeof $(HAL.ajax.settings.form).attr('action') !== 'undefined') HAL.ajax.settings.url = $(HAL.ajax.settings.form).attr('action'); // Set URL to the action of the form if URL is not defined

            // Requirements
            if((!HAL.ajax.settings.form && !HAL.ajax.settings.ajaxVars) || !HAL.ajax.settings.url){
                HAL.ajax.log('[URL && [Form Object || AjaxVars]] is required!')
                return false;
            }

            if(HAL.ajax.settings.form && !HAL.ajax.settings.ajaxVars) HAL.ajax.settings.ajaxVars = $(HAL.ajax.settings.form).serialize();

            // On error
            $.ajaxSetup({
                error : function(event,thrownError){
                    return HAL.ajax.settings.onError({ status : 'error' },event,thrownError);
                }
            });

            $.post(HAL.ajax.settings.url,HAL.ajax.settings.ajaxVars,function(data,response_status){
                // General oncomplete
                if(HAL.ajax.settings.onComplete) HAL.ajax.settings.onComplete(data,response_status);

                if(data.status == HAL.ajax.settings.okFlag){
                    return HAL.ajax.settings.onSuccess(data);
                }else if(data.status == HAL.ajax.settings.errorFlag){
                    return HAL.ajax.settings.onError(data);
                }else{
                    alert((data.message) ? data.message : 'Error!');
                }
            },'json');
        }
    },
    analytics : {
        executable : function(){
            if(typeof _gaq !== 'undefined'){
                return true;
            }else{
                this.log('Couldn\'t track event because analytics is not executable');
                return false;
            }
        },
        log : function(s){
            if(typeof console !== 'undefined') console.log(s)
        },
        track : {
            pageview : function(url,cb){
                // Track the pageview
                if(HAL.analytics.executable()){
                    var c = _gaq.push(['_trackPageview',url]);
                    HAL.analytics.log('Tracked '+url+' using _trackPageview');
                }

                if(cb){
                    return cb(c);
                }else{
                    return c;
                }
            },
            event : function(category,action,label,value,cb){
                if(HAL.analytics.executable()){
                    var c = _gaq.push(['_trackEvent',category,action,label,value]);
                    HAL.analytics.log('Tracked '+category+':'+action+' using _trackEvent');
                }
                
                if(cb){
                    return cb(c);
                }else{
                    return c;
                }
            }
        }
    }
}
