﻿// Global "namespace" for Javascript functionality.
var C1 = function() {
    // Private Elements
    var startup = [];                       // An array that will contain functions to call during init
    var shaderId = 'shader';                // The id of the div that is used for lightbox functionality. TODO: consider moving this to a different location?
    var locationCookie = 'c1_location';     // The name of the cookie used to store location info.
    var cityCookie = 'c1_City'; 
    var stateCookie = 'c1_State';     // The name of the cookie used to store state info.
    var systemIdCookie = 'c1_systemID';     // The name of the cookie used to store system id.
    var zipCookie = 'c1_zipcode';           // The name of the cookie used to store zip code info.
    var oldSystemCookie = 'CableOneSystem';   // The name of the cookie used to store zip code info.
    var statesServiced = [];                // An array of the states that cableone services. Pulled from ajax.
    var selectedCities = [];                // An array of the cities available to the current state. Pulled from ajax.
    var _handlerPrefix = '/_controltemplates/';

    // Private function that fades an element by quicly changing its opacity.
    // o : The initial opacity of an element that will be faded.
    // inc : The increment to fade an element. Positive values to decrease opacity, negative to increase it. (This feels backwards, but is what prototype uses.)
    // eq : A function that provides returns a boolean. This determines when to exit the fade loop.
    // postFunc : An optional function that runs after the fade loop has completed.
    function fade(elem, o, inc, eq, postFunc) {
        function fadeloop() {
            if (eq(o)) {
                o += inc;
                $(elem).setOpacity(o);
                setTimeout(function() { fadeloop(); }, 10);
            } else {
                if (postFunc != null) {
                    postFunc();
                }
            }
        }
        fadeloop();
    }
    
    // Private function that displays/hides the appropriate location panels, depending on whether the user already specified a location.
    function displayLocationPanel(showLocation) {
        if (showLocation) {
            $('c1_LocationSet').hide();
            $('c1_LocationNotSet').show();
        } else {
            $('c1_LocationSet').show();
            $('c1_LocationNotSet').hide();
        }
    }

    // Gets the height of the page. This was grabbed from a webpage somewhere.
    function getHeight() {
          return document.body.offsetHeight + 50;
    }
    
    // 
    function storeZip(zip) {
        if (zip != null && zip != '') {
            C1.setCookie(zipCookie, zip, 14);
        }
    }

    // store old system id as cookie
    function storeOldSystem(code) {
        if (code != null && code != '') {
            C1.setCookie(oldSystemCookie, code, 365);
        }
    }

    // Creates a shader element if it does not already exist and makes it completely transparent.
    function getOrCreateShader(elemId) {
        var elem = $(elemId);
        if (elem == null) {
            elem = createDiv(elemId, { 
                backgroundColor: '#000',
                width: '100%',
                height: getHeight() + 'px',
                position: 'absolute',
                top: '0px',
                left: '0px',
                zIndex: C1.topZ
            });
            $(elem).hide();
        }
        $(elem).setOpacity(1.0);
        return elem;
    }
    
    // Creates the layer that displays the star for a city that is selected.
    function getOrCreateStar(elemId) {
        var elem = $(elemId);
        if (elem == null) {
            elem = createDiv(elemId, {
                width: '11px',
                height: '11px',
                position: 'absolute'
            }, $('statePicture'));
            elem.innerHTML = '<img src="' + _handlerPrefix + 'img.aspx?src=SiteCollectionImages/Map/SelLoc_Star1.gif" alt="star" />';
        }
        return elem;
    }
   
    // Creates a new div element and adds it to the document's body.
    function createDiv(elemId, style, parent) {
        var div = document.createElement('div');
        div.setAttribute('id', elemId);
        if (parent == null) {
            document.body.appendChild(div);
        } else {
            parent.appendChild(div);
        }
        $(div).setStyle(style);
        return div;
    }
    
    // Populates the statesServiced array if it has not been filled already.
    function getStates() {
        if (statesServiced.length == 0) {
            retrieveStates();
        }
    }
    
    // Populates a dropdown list with an array of objects.
    // list: the dropdown list
    // objects: the array of objects that will make up the list
    // valField: the property of the object that will fill the 'value' attribute of the dropdown option.
    // textField: the property of the object that will fill the 'text' attribute of the dropdown option.
    function bindList(list, objects, valField, textField) {
	    clearListItems(list);
        $(list).options[0] = new Option('Select a city');
        objects.each(function(item) {
            var o = new Option(item[textField], item[valField]);
            $(list).options[$(list).options.length] = o;
        });
    }

    function clearListItems(list) {
	  while ($(list).length > 0) {
	    $(list).remove(0)
	  }
    }
    
    // Retrieves a list of cities available for the selected state.
    // callback: a function to handle the list of cities. This is used because the asynchronous nature of the ajax call; it will return 
    // null before the call completes and cause unexpected behavior.
    // TODO: this could be cleaned up more since the function should ONLY retrieve cities. A refactoring could be to just give the callback
    // function the city array, and let that do whatever with it.
    function retrieveCities(callback) {
	    $('cityList').innerHTML = '';
        var a = new Ajax.Request(C1.ajaxUrl, {
            method: 'get',
            parameters: { f: 'getCities', state: C1.selectedState.Abbreviation },
            onSuccess: function(transport) {
                selectedCities = transport.responseText.evalJSON();
                var cityText = selectedCities.inject('', callback);
                $('cityList').innerHTML = cityText;
                bindList('c1_cityList', selectedCities, 'Name', 'Name');
            }
        });
    }

    //
    function test1(t) {
	  alert(t);
    }

    //
    function getCityByZip(zipCode, callback) {
        var a = new Ajax.Request(C1.ajaxUrl, {
            method: 'get',
            parameters: { f: 'getCityByZip', zip: zipCode},
            onSuccess: function(transport) {
                var city = transport.responseText.evalJSON();
                if (city == null) {
                    alert('zip code ' + zipCode + ' is not serviced.');
                } else {
                    C1.selectedState = { Abbreviation: city.State };
                    C1.selectedCity = city;
                    callback(city);
                }
            },
            onFailure: function(transport) {
                //alert('zip lookup failure: ' + transport.responseText);
            }
        });
    }
    
    function retrieveAreas(callback) {
        var a = new Ajax.Request(C1.ajaxUrl, {
            method: 'get',
            parameters: { f: 'getAreas', cityId: C1.selectedCity.Id },
            onSuccess: function(transport) {
                var areas = transport.responseText.evalJSON();
                callback(areas);
            },
            onFailure: function(transport) {
                //alert('retrieval error: ' + transport.responseText)
            }
        });
    }
    
    // Retrieves a list of states available from an ajax call.
    function retrieveStates() {
        var a = new Ajax.Request(C1.ajaxUrl, {
            method: 'get',
            parameters: { f: 'getStates' },
            onSuccess: function(transport) {
                statesServiced = transport.responseText.evalJSON();
            },
            onFailure: function(transport) {
                //alert('fail: ' + transport.responseText);
                //alert('A problem occurred retrieving list of states.');
            }
        });
    }
    
    // loops through the state array looking for a particular abbreviation.
    function lookupState(stateAbbr) {
        return lookup(statesServiced, function(state) {
            return state.Abbreviation == stateAbbr;
        });
    }
    
    // loops through the city array looking for a particular city name.
    function lookupCity(cityName) {
        return lookup(selectedCities, function(city) {
            return city.Name == cityName;
        });
    }
    
    // loops through an array, and performs a comparison operation, returning the first match.
    function lookup(arr, comparer) {
        for (var i = 0; i < arr.length; i++) {
            if (comparer(arr[i])) {
                return arr[i];
            }
        }
        return null;
    }
    
    function displayAreas() {
        retrieveAreas(function(areas) {
            var areaRows = areas.inject('', function(acc, area, index) {
                var cell = '<td>' + area + '</td>\n';
                acc += index % 2 == 0 ? '<tr>\n' + cell : cell + '</tr>\n';
                return acc;
            });
            if (areaRows.endsWith('</td>')) {
                areaRows += '<td></td>\n</tr>\n';
            }
            $('serviceAreaTable').innerHTML = '<table class="c1_list">\n<tbody>\n' + areaRows + '</tbody>\n</table>\n';
        });
    }
   
    // Public Elements
    var pub = {
        // Properties
        topZ: 100,                  // Z-Order of the highest element.
        loginActive: false,         // A flag stating that the login window is currently being displayed.
        locationActive: false,      // A flag stating that the location window is currently being displayed.
        ajaxUrl: _handlerPrefix + 'ajax.aspx',       // URL to the ajax handler.
        selectedState: null,        // The state currently selected by the user setting a location.
        selectedCity: null,         // The city currently selected by the user setting a location.
        handlerPathPrefix: _handlerPrefix,      // The prefix to insert before calls to http handlers. Needed because this differs from dev and production environments.
        
        // Functions
        
        effects: { // Effects namespace for functions that perform UI operations.

            // Bolds the text of the provided element.       
            embolden: function(elem) {
                $(elem).setStyle({ fontWeight: 'bold' });
            },
            
            // Unbolds the text of the provided element.
            unbold: function(elem) {
                $(elem).setStyle({ fontWeight: 'normal' });
            },
             
            // Displays an element as a "lightbox" by graying out the screen and displaying a specific element.
            lightbox: function(boxElem) {
                C1.effects.shade();
                var z = C1.topZ + 1;
                C1.effects.center(boxElem);
                $(boxElem).setStyle({ zIndex: z });
                $(boxElem).show();
            },
            
            // Returns the screen back to a pre-lightbox state.
            unLightbox: function(boxElem) {
                C1.effects.fadeOut(shaderId, function() { $(shaderId).hide(); });
                $(boxElem).hide();
            },
            
            // Centers an element to its parent element.
            center: function(boxElem) {
                var boxW = $(boxElem).getWidth();
                var screenW = $(boxElem).getOffsetParent().getWidth();
                var x = screenW / 2 - boxW / 2;
                $(boxElem).setStyle({ 
                    position: 'absolute',
                    top: '50px',
                    left: x + 'px'
                    });
            },
            
            // Shades the whole screen by overlaying a new div with a semi-transparent black background.
            shade: function() {
                // get or create an element that fills the whole screen
                var shader = getOrCreateShader(shaderId);
                shader.show();
                C1.effects.fadeIn(shaderId, 0.8);
            },
            
            // Fades in the specified div.
            fadeIn: function(elem, maxOpacity) {
                fade(elem, 0.0, 0.20, function(o) { return o < maxOpacity; });
            },
            
            // Fades out the specified div.
            fadeOut: function(elem, postFunc) {
                fade(elem, 1.0, -0.20, function(o) { return o > 0.0; }, postFunc );
            }
        },
        
        // Functionality for controls
        func: {
            searchZipCode: function(zipBox) {
                var zip = $F(zipBox);
                if (zip != null && zip != '') {
                     storeZip(zip);
                     // perform the actual search.
                     getCityByZip(zip, function(city) {
                         C1.func.setState(city.State);
                         //$('selectedCity').innerHTML = city.Name + ', ' + city.State;
                         //displayAreas();
			             C1.func.setLocation();
                     });
         	    }
         	    else 
         	    {
         	         alert('zip can not be blank');
         	    }
            },

            getOldSystem: function(oldSystem, callback) {
                var a = new Ajax.Request(C1.ajaxUrl, {
                    method: 'get',
                    parameters: { f: 'getCityByOldSystemId', oldSystem: oldSystem},
                    onSuccess: function(transport) {
                        var city = transport.responseText.evalJSON();
                        if (city != null) {
                            callback(city);
                        }
                    },
                    onFailure: function(transport) {
                        //alert('System lookup failure: ' + transport.responseText);
                    }
                });
            },

            // Displays the Set Your Location box.
            showSetLocation: function() {
		        $('c1_setLocationContainer').setStyle({'display': 'block'});
                $('c1_setLocationContainer').setStyle({'width': '600px'});
                C1.func.togglePanels(0);
                C1.effects.lightbox('c1_setLocationContainer');
                C1.effects.locationActive = true;
            },
            
            // Displays the Login box.
            showLogin: function() {
                C1.effects.lightbox('c1_loginBody');
                $$('div.c1_loginControls input')[0].focus();
                C1.effects.loginActive = true;
            },
            
            // Hides the 'set your location' box
            hideLocation: function() {
                if (C1.effects.locationActive) {
                    C1.effects.unLightbox('c1_setLocationContainer');
                    C1.effects.locationActive = false;
                }
            },
            
            // Hides the 'login' box.
            hideLogin: function() {
                if (C1.effects.loginActive) {
                    C1.effects.unLightbox('c1_loginBody');
                    C1.effects.loginActive = false;
                }
            },
            
            // Displays a star image at the provided coordinates.
            displayStar: function(x, y, container) {
                if (container == null) {
                    container = 'c1_statePicture';
                }
                var star = getOrCreateStar('locationStar');
                var pos = $(container).cumulativeOffset();
                star.setStyle({
                    position: 'absolute',
                    top: (240 + y) + 'px',
                    left: (50 + x) + 'px'
                });
                star.show();
            },
            
            // Hides the star image.
            hideStar: function() {
                var star = getOrCreateStar('locationStar');
                star.hide();
            },
            
            // Checks to see if a location has already been set by a user.
            checkLocation: function() {
                var loc = C1.readCookie(cityCookie);
                var state = C1.readCookie(stateCookie);
                $('yourLocation').innerHTML = loc + ', ' + state;
                displayLocationPanel(loc == null || loc == '');
            },
            
            // Sets the selected state object.
            setState: function(state) {
		$('cityList').innerHTML = '';
                if (typeof(state) == 'string') {
                    state = lookupState(state);
                }
                C1.selectedState = state;
                $('selectedState').addClassName("nobr");
                $('selectedStateFooter2').innerHTML = $('selectedStateFooter').innerHTML = $('selectedState').innerHTML = C1.selectedState.StateName;
                $('cityImage').src = $('stateImage').src = C1.selectedState.ImageUrl;
		$('serviceAreaTable').innerHTML = '';
                retrieveCities(function(acc, city) {
                    //acc += '<a onmouseover="javascript:C1.func.displayStar(' + city.StarCoordinates.X + ',' + city.StarCoordinates.Y + ')" onmouseout="javacsript:C1.func.hideStar()" href="javascript:C1.func.setCity(\'' + city.Name + '\')">' + city.Name + '</a><br />';
                    acc += '<div class="setLocationSystem" onclick="javascript:C1.func.setLocation();" onmouseover="javascript:C1.func.setCity(\'' + city.Name + '\')"><a class="systemLink" href="javascript:C1.func.setLocation();" onmouseover="javascript:C1.func.setCity(\'' + city.Name + '\')">' + city.Name + '</a></div>';
                    return acc;
                });
                
                C1.func.togglePanels(1);
            },
            
            // Sets the selected state via a dropdown list.
            setStateFromList: function(list) {
                C1.func.setState($F(list));
            },
            
            // Sets the selcted city via a dropdown list.
            setCityFromList: function(list) {
                C1.func.setCity($F(list));
		C1.func.setLocation();
            },
            
            // Sets the selected city and displays the 'areas serviced' panel.
            setCity: function(cityName) {
              if ((C1.selectedCity == null) || ( C1.selectedCity.Name != cityName )) {

                //C1.func.hideStar();
                $('selectedCity').innerHTML = cityName + ', ' + C1.selectedState.Abbreviation;
                var city = lookupCity(cityName);
                C1.selectedCity = city;

		$('serviceAreaTable').innerHTML = 'Loading...';
                displayAreas();                
                //C1.func.displayStar(city.StarCoordinates.X, city.StarCoordinates.Y);
              }
            },
            
            // Completes the 'set your location' functionality. 
            setLocation: function() {
                var days = null;
                var loc = C1.selectedCity.Name + ', ' + C1.selectedState.Abbreviation;
                $('yourLocation').innerHTML = loc;
                if ($('saveLocationFlag').checked) {
                    days = 365;
                }
                C1.setCookie(cityCookie, C1.selectedCity.Name, days);
                C1.setCookie(stateCookie, C1.selectedState.Abbreviation, days);
                C1.setCookie(systemIdCookie, C1.selectedCity.SystemID, days);
                //displayLocationPanel(false);
                //C1.func.hideLocation();
                document.location.reload(true);
            },

            // Completes the 'clear your location' functionality. 
            clearLocation: function() {
                C1.clearCookie(oldSystemCookie);
                C1.clearCookie(locationCookie);
                C1.clearCookie(cityCookie);
                C1.clearCookie(stateCookie);
                //displayLocationPanel(false);
                //C1.func.hideLocation();
                document.location.reload(true);
            },
            
            // Displays a 'set your location' panel.
            togglePanels: function(index) {
                if (index == null) {
                    index = 0;
                }
                $('c1_stepNum').innerHTML = index + 1 + '';
                $$('.c1_locationPanel').invoke('hide')[index].show();
            },
            
            // Populates the statesServiced array.
            initStates: function() {
                getStates();
            }
        },
        
        // Extracts an element from its current position and moves it to the bottom of the form.
        moveElem: function(elemId) {
            var elem = $(elemId).remove();
            var parent = $(document.body).childElements()[0];
            $(parent).insert(elem, {position: 'bottom'});
        },
        
        // Sets a cookie. Taken from quirksmode.org.
        setCookie: function(name, value, daysTilExpires, path) {
            if (path == null) {
                path = '/';
            }
            var today = new Date();
            var expire = new Date();
            expire.setTime(today.getTime() + 3600000 * 24 * daysTilExpires);
            document.cookie = name + "=" + value + ";expires=" + expire.toGMTString() + '; path=' + path;
        },
        
        // Reads a cookie. Taken from quirksmode.org.
        readCookie: function(name) {
            var nameEQ = name + "=";
	        var ca = document.cookie.split(';');
	        for(var i=0;i < ca.length;i++) {
		        var c = ca[i];
		        while (c.charAt(0)==' ') { 
		            c = c.substring(1,c.length);
		        }
		        if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
	        }
	        return null;
        },
        
        // Erases a cookie. Taken from quirksmode.org
        clearCookie: function(name) {
            var today = new Date();
            var expire = new Date();
            expire.setTime(today.getTime() - 1);
            document.cookie = name + "=;expires=" + expire.toGMTString() + '; path=/';
            document.cookie = name + "=;expires=" + expire.toGMTString() + '; path=/;domain=cableone.net';
            document.cookie = name + "=;expires=" + expire.toGMTString() + '; path=/;domain=www.cableone.net';
            //C1.setCookie(name, "", -1);
            //alert('Information has been cleared!');
        },
               
        // Adds a function to the initialization queue.
        addInit: function(func) {
            startup[startup.length] = func;
        },
        
        // Performs any functions that should be run at startup time.
        init: function() {
            for (var i = 0; i < startup.length; i++) {
                startup[i]();
            }
        }
    };
    return pub; 
}();