/// <summary>
/// This module contains routines load a select control with all the Target stores near a given zip code.
/// </summary>
var TargetStoreLocater = function(){
    
    var zipCode;
    var selectName;    
    var http;
        
    /// <summary>
    /// Get an HTTP request object that can be used to make an asynchronous request to a server.
    /// </summary>
    /// <param name="url">
    /// The url to use to setup the http request.
    /// </param>
    /// <param name="callback">
    /// The function to be called on a state change of the request.
    /// </param>
    /// <returns>
    /// XmlHttpRequest object.
    /// </returns>
 	var setupHttpRequest = function(url, callback) 
 	{
 	    try
 	    {
 	        http = null;
		    if (window.XMLHttpRequest) 
                http = new XMLHttpRequest();
		    else if (window.ActiveXObject) 
			    http = new ActiveXObject('Microsoft.XMLHTTP');
            else
                throw new Error('Javascript XMLHttpRequest is not supported on this browser.');
    			
		    if (http != null)
		    {
			    if (typeof http.overrideMimeType != 'undefined') 
				    http.overrideMimeType('text/xml');
				    
	            http.onreadystatechange = callback;
		        http.open('GET', url, true);
		        http.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
		    }
		}
        catch (ex) 
        {
            throw new Error('Error occurred: [TargetStoreLocater.setupHttpRequest]\n\n' + ex.message);
        }
	};
		        
    /// <summary>
    /// The state change callback for the load stores request.
    /// </summary>
    var callback = function()
    {
        try 
        {
	        if (http.readyState != 4 || http.status != 200) 
		        return;
		        
            loadSelects(http.responseText);
        } 
        catch (ex) 
        {
            alert('Error occurred: [TargetStoreLocater.callback]\n\n' + ex.message);
        }
    };
    
    /// <summary>
    /// Load the previously indicated select control(s) with the stores in the indicated xml.
    /// </summary>
    /// <param name="storeXml">
    /// The xml text that holds the stores data to display.
    /// </param>
    var loadSelects = function(storeXml)
    {
        try
        {
            var stores = null;
            if (storeXml != '')
            {            
                //Convert the stores xml into an xml document.
                var stores = loadXml(storeXml);
            }
            
            //Update each select that should be updated. This may be more than one because up to 10 entries are 
            //possible for the code table.
            for (var i = 0; i < 10; i++)
            {
                var select = document.getElementsByName(selectName + '.' + i);
                
                if (select.length == 0) break;
                
                select = select[0];
                
                loadSelect(select, stores);
            }
        }
        catch (ex)
        {
            throw new Error("Error occurred: [TargetStoreLocater.loadSelects]\n\n" + ex.message);
        }
    };
    
    /// <summary>
    /// Load the indicated select control with the stores in the indicated xml document.
    /// </summary>
    /// <param name="stores">
    /// The xml document that holds the stores data to display.
    /// </param>
    var loadSelect = function(select, stores)
    {
        try
        {
            //First clear out the current options.            
            select.innerHTML = '';            

            if (stores != null)
            {            
                //Now add every store in the xml doc.
                var store = stores.firstChild.firstChild;
                
                while (store != null)
                {
                    //Convert xml node to an option element.
                    var option = document.createElement('option');
                    var value = store.firstChild.firstChild;
                    if (value != null)
                        option.value = value.nodeValue;
                        
                    value = store.firstChild.nextSibling.firstChild;
                    if (value != null)
                    {
                        option.text = value.nodeValue;      //Needed for Mozilla.
                        option.innerText = value.nodeValue; //Needed for IE
                    }
                        
                    select.appendChild(option);
                    store = store.nextSibling;
                }
            }
        }
        catch (ex)
        {
            throw new Error("Error occurred: [TargetStoreLocater.loadSelect]\n\n" + ex.message);
        }
    };
    
    /// <summary>
    /// Load the text into an Xml Document.
    /// </summary>
    /// <param name="text">
    /// The text to load.
    /// </param>
    /// <returns>
    /// An Xml Document with the text loaded.
    /// </returns>
    var loadXml = function(text)
    {
        // code for IE
        if (window.ActiveXObject)
        {
            var doc = new ActiveXObject('Microsoft.XMLDOM');
            doc.async = "false";
            doc.loadXML(text);
        }
        // code for Mozilla, Firefox, Opera, etc.
        else
        {
            var parser=new DOMParser();
            var doc=parser.parseFromString(text,"text/xml");
        };

        // documentElement always represents the root node
        var x = doc.documentElement;        
        
        return doc;
    };    



    /// <summary>
    /// Trim spaces from the beginning and end of the string.
    /// </summary>
    /// <param name="str">
    /// The string to trim.
    /// </param>
    /// <returns>
    /// The string with all leading and trailing spaces removed.
    /// </returns>
    var trim = function(str)
    {
       return str.replace(/^\s*|\s*$/g,"");
    }
    
    return {
        /// <summary>
        /// Locate the stores that are near the indicated zip code and load them into the indicated select control.
        /// </summary>
        /// <param name="zip">
        /// The zip code near which to locate the stores.
        /// </param>
        /// <param name="numStores">
        /// The maximum number of stores to return in the search.
        /// </param>
        /// <param name="searchRadius">
        /// The number of miles from the center of the zip code in which to search.
        /// </param>
        /// <param name="ctrlName">
        /// The name of a select control that will be loaded with the results of the search.
        /// </param>
        loadStores : function(zip, numStores, searchRadius, selectCtrlName)
        {
            try
            {
                selectName = selectCtrlName.split('.')[0];
                
                //Don't do this if the zip code has not changed.
                if (zipCode != zip)
                {
                    zipCode = zip;
                    
                    //var url = "http://localhost/SID_1/Default.asp?CUSTOM=TSL&zip=" + zip + "&numberOfStores=" + numStores + "&searchRadius=" + searchRadius;
                    var url = document.URL.split('?')[0] + "?CUSTOM=TSL&zip=" + zip + "&numberOfStores=" + numStores + "&searchRadius=" + searchRadius;
                    setupHttpRequest(url, callback);
                    http.send();
                }
            }
            catch (ex)
            {
                alert("Error occurred: [TargetStoreLocater.loadStores]\n\n" + ex.message);
                return null;
            }               
        },
        
        /// <summary>
        /// This is placed as the onchange event handler of the zip control in order to update the indicated
        /// select control when the zip changes.
        /// </summary>
        /// <param name="zipCtrl">
        /// The control that holds the zip code and has just been changed.
        /// </param>
        /// <param name="numStores">
        /// The maximum number of stores to return in the search.
        /// </param>
        /// <param name="searchRadius">
        /// The number of miles from the center of the zip code in which to search.
        /// </param>
        /// <param name="selectCtrlName">
        /// The name of a select control that will be loaded with the results of the search.
        /// </param>
        onChange : function(zipCtrl, numStores, searchRadius, selectCtrlName)
        {
            this.loadStores(trim(zipCtrl.value), numStores, searchRadius, selectCtrlName);
        }
    };
}();
