// Author: Joseph Lust 2009
// E mail: lifeofust (at) gmail.com

// Following will load application dependancies and launch map application
    // (1) load JS libraries needed
    
    // Loader functions to dynamically bring in our other dependencies
    function loadjscssfile(filename, filetype){
        if (filetype=="js"){ //if filename is a external JavaScript file
            var fileref=document.createElement('script');
            fileref.setAttribute("type","text/javascript");
            fileref.setAttribute("src", filename);
        }
        else if (filetype=="css"){ //if filename is an external CSS file
            var fileref=document.createElement("link");
            fileref.setAttribute("rel", "stylesheet");
            fileref.setAttribute("type", "text/css");
            fileref.setAttribute("href", filename);
        }
        if (typeof fileref!="undefined") {
            document.getElementsByTagName("head")[0].appendChild(fileref);
        } 
    }
    // (2) Initialize Global objects
    var mapObj      = null;
    var data        = null; // Our return object with store data
    var markers     = Array(); // Store markers to remove them and listeners later
    var geocoder    = null; // For storing recent searches and results
    var bounds      = null; // Route bounding box
    var mapListner  = null;
	var valid       = null; // Form validation object
	var myStart     = new GLatLng(38.7,  -95.8);// Center on NA
	var zipBoxTrans = 0.9; // Transparency on input box
    var null_str    = 'zip';
    var openMarkerIdStr = null; // Window centering
    var openMarkerTryCnt= null;
    
//    var storeIcon = new GIcon(); // Icon for draw/edit a point - only using a few of the many parameters    
      //storeIcon.image = 'http://img.easytonestores.com/shoe_profile_trim_sm_lt.gif';
      //storeIcon.iconSize = new GSize(44, 33);
      //storeIcon.iconAnchor = new GPoint(44, 33);
      //storeIcon.infoWindowAnchor = new GPoint(44, 33);
      	
	// (3) Set Event Hooks
	Event.observe(window, 'load',function() {
	    // On load completion, start validation, initiate map
        $('map_app_zip_div').hide(); // Hide so we can show later
	    load_map_app();
        // Set title - some browers can't handle it
	    $('map_app_zip').value = null_str; // hint for viewer    
	    showZipBox();   // Fade in for effect
	    
	    // Event triggers
        Event.observe('map_app_zip','keydown',function(e) {
	        if(Event.KEY_RETURN==e.keyCode) {getStores();}// Validate zip on enter press
        });
        Event.observe('map_app_zip','click',function(e) {
	        if($('map_app_zip').value==null_str) {$('map_app_zip').value='';}// Validate zip on enter press
        }); 
        
        // Track
        setTimeout('adTracker();',1500);      
	});
	
	function adTracker()
    {
        // Load tracker - pause to ignore bots and spiders
        loadjscssfile("http://js.easytonestores.com/js2/ad_load.js?key=easytone_map","js");
    }

    // (4) Program functions - initiated by user or event hooks
    function load_map_app() {
      if (GBrowserIsCompatible()) {
        // Make map
        mapObj = new GMap2($('map_app_canvas')); // Make a new map object, store globally
        mapObj.setCenter(myStart,3); // Initialize to initial national view
       
        // Choose type of maps
        mapObj.setMapType(G_NORMAL_MAP); //G_NORMAL_MAP G_SATELLITE_MAP G_HYBRID_MAP G_DEFAULT_MAP_TYPES
        // Draw controls
        //mapObj.addControl(new GSmallZoomControl());  // Zoom/Pan
        mapObj.enableScrollWheelZoom(); // Enable other controls       
        //mapObj.enablePinchToZoom(); // Allow Ipods/Iphones
      }
    }
    
    function getStores() {
        // Get the user location (entered as zip)
        var zip = $('map_app_zip').value;
        if(!isZip5(zip)) {UIShake(); return;} // Show user fail
            
        // Send server side, get coordinates
        geocoder = (geocoder) ? geocoder:new GClientGeocoder(); // Declare is absent
        geocoder.getLatLng(zip, function(point) {
            if(point) { // valid response
                hideZipBox(); // Hide
                // Fetch the stores from remote db
                var map_app_server = "http://js.easytonestores.com/js2/getStores.js/getStores.js?lat="+point.lat()+"&lon="+point.lng()+"&zip="+zip;
                loadjscssfile(map_app_server,"js"); // JSON will unpage self via displayStores()
            }
            else { // invalid response
                UIShake();
            }           
        });// Fly to point   
    }
    
    function displayStores(data) {
        // Self unpacking function of getStores
        //var data = json_data.evalJSON(true);
        if(data.success) {
            // Get bounding box, set display view
            
            // Move map to proper bounds
            var bounds = new GLatLngBounds(new GLatLng(data.bounds.lat.min,data.bounds.lon.min), new GLatLng(data.bounds.lat.max,data.bounds.lon.max));
            mapObj.setCenter(bounds.getCenter(),mapObj.getBoundsZoomLevel(bounds)-1); // Center,Zoom - bounce out to capture all points        
            
            // Parse and insert markers
//            var html = new Template("<table><tr><td><b>#{name}</b> #{dist}mi</td></tr><tr><td>#{mall}</td></tr><tr><td>#{address}</td></tr><tr><td>#{city} #{state}, #{zip}</td></tr><tr><td>#{phone}</td></tr></table>");
            var html = new Template("<div id='store_#{store_id}' class='map_app_store_info'><b>#{name}</b> #{dist}mi<br/>#{mall}<br/>#{address}<br/>#{city} #{state}, #{zip}<br/>#{phone}</div>");
            var phone = new Template('(#{a}) #{b}-#{c}'); // Format phone number
            var m = null, marker = null, id=null;
            for(n=0,l=data.store_info.length; n<l; n++) {
                m = data.store_info[n];
                m.phone = phone.evaluate({a: m.phone.substring(0,3),b: m.phone.substring(3,6),c: m.phone.substring(6,10)});
                id = "store_"+m.store_id;
                //marker = new createMarker(new GLatLng(m.lat,m.lon),{clickable: true, icon: storeIcon, title: m.mall},html.evaluate(m),id);
                marker = new createMarker(new GLatLng(m.lat,m.lon),{clickable: true, title: m.mall},html.evaluate(m),id);
                mapObj.addOverlay(marker);
            }
        }
        else {
            // Nothing found on server, reset view
            showZipBox();
            UIShake();
            return;
        }
    }
    
    function createMarker(point,opts,html,id) {
        var marker = new GMarker(point,opts);
        markers.push(marker); // Store for later
        GEvent.addListener(marker, "click", function() {
            marker.openInfoWindowHtml(html);
            openMarkerIdStr = id;// Prime DOM
//            openMarkerTryCnt = 0;
//            centerIW();
            setTimeout("centerIW()",300);
        });
        return marker;
    }

function centerIW() {
    // Hunt down an info window in the dom, find container, computer geometry, execure map center
//    if(openMarkerTryCnt<10) { // 11 tries, then quit
        if($(openMarkerIdStr)) {
            //alert($(openMarkerIdStr));
            var IW = $(openMarkerIdStr).up('div',3);
            var MW = IW.up('div',1);
            var w = parseInt(IW.getStyle('left'))+parseInt(MW.getStyle('left'));
            var h = parseInt(IW.getStyle('top'))+parseInt(MW.getStyle('top'));
            mapObj.panBy(new GSize(31-w,18-h)); //w h with centering offsets
        }
//        else { // DOM not updated, demur
//           openMarkerTryCnt++; // pervent infinite loop
//           setTimeout("centerIW()",100);// Give DOM time to update 100ms
//        }
//    }
}
    
function resetStores() {
    // Clear all stores from the map
    for(n=0,l=markers.length; n<l; n++) {
        mapObj.removeOverlay(markers[n]); // Remove from map
        GEvent.clearListeners(markers[n]);// Remove from listeners
    }
    mapObj.setCenter(myStart,3); // Reinitialize to initial national view
    showZipBox(); // Allow reentry
}

    
function UIShake() {    // Indicate error to user
    if(!Prototype.Browser.IE) { // IE blows
        new Effect.Shake($('map_app_zip_div'));
    }
}

function showZipBox() {
    // Fade in the zip code entry box
    Effect.Appear('map_app_zip_div',{to : zipBoxTrans});
}

function hideZipBox() {
    // Fade in the zip code entry box
    Effect.Fade('map_app_zip_div',{from : zipBoxTrans});
}    

// Validate a zip code (5 digit)
function isZip5(str)
{
   if(str.length > 5) {return false;}
   
   var ValidChars = "0123456789";
   var IsNumber=true;
   var Char;
 
   for (i = 0; i < str.length && IsNumber == true; i++) 
      { 
      Char = str.charAt(i); 
      if (ValidChars.indexOf(Char) == -1) 
         {
         IsNumber = false;
         }
      }
   // Check to ensure within range, and real
   return (IsNumber && str>0 && str<=99999) ? true:false;
   
   }


