/**************************************************
 *  [preload] Preload Images
 **************************************************/
preloadedImages = new Array();
// Generic preload function
function preloadImage(url) {
    if(document.location.href.indexOf("description") != -1) {
        url = "../" + url;
    }
    var index = preloadedImages.length;
    preloadedImages[index] = new Image();
    preloadedImages[index].src = url;
    return preloadedImages[index];
}
// Pre-load button images
var pre_images = new Array("buttonbg.png", "mp3buttonbg.png", "pdfbuttonbg.png", "vidbuttonbg.png", "closedcart.png", "opencart.png", "overview/wide-hidepackages.png", "overview/wide-viewpackages.png");
for(var i=0; i<pre_images.length; i++) {
    var img = "img/" + pre_images[i];
    // Here we preload the 3 states of various buttons
    preloadImage(img);
    preloadImage(img.replace(".", "-over."));
    preloadImage(img.replace(".", "-down."));
}
preloadImage("img/defline-off.png");
preloadImage("img/defline-on.png");

/**************************************************
 *  [sniff] Browser Sniffing code
 **************************************************/
// Used to determine whether we should use the document.getElementById method (only IE and NS7/Mozilla)
var gebi = (document.getElementById) ? true : false;

/**************************************************
 *  [popup] Popup Windows
 **************************************************/
// Used to position a popup in the middle of a document window.
function getWindowBounds() {
    var rect = new Object();
    var ie_style;
    if(window.document.getElementById) {
        ie_style = isNaN(window.screenX);
    } else {
        ie_style = (document.all) ? true : false;
    }
    if(ie_style) {
        rect.x = window.screenLeft;
        rect.y = window.screenTop;
        rect.width = window.document.body.offsetWidth;
        rect.height = document.documentElement.clientHeight;
    } else {
        rect.x = window.screenX;
        rect.y = window.screenY;
        rect.width = window.outerWidth;
        rect.height = window.outerHeight;
    }
    return rect;
}
// Used to position a popup in the middle of a document window.
function getPopupCoordinates(width, height) {
    var point = new Object;
    var rect = this.getWindowBounds();
    point.x = rect.x + (rect.width-width)/2;
    point.y = rect.y + (rect.height-height)/2;
    if(point.x < 0) {
        point.x = 0;
    }
    if(point.x > rect.width) {
        point.x = 0;
    }
    if(point.y < 0) {
        point.y = 0;
    }
    if(point.y > rect.height) {
        point.y = 0;
    }
    return point;
}
// uses the above functions to create a window centered above the current page.
function showCenteredWindow(url, name, width, height) {
    var coords = getPopupCoordinates(width, height);
    var features = "resizable,scrollbars,"
        features += "width=" + width + ",";
        features += "height=" + height + ",";
        features += "left=" + coords.x + ",";
        features += "screenX=" + coords.x + ",";
        features += "top=" + coords.y + ",";
        features += "screenY=" + coords.y + ",";
    var popup = window.open(url, name, features);
    if((coords.x > 0) && (coords.y > 0)) {
        popup.moveTo(coords.x, coords.y);
    }
}
// Shows the "customquote" window
function showCustomQuote() {
    showCenteredWindow("customquote.jsp", "customquote", 400, 350);
    return false;
}
// Shows a definition
function showDefinition(term, popup) {
    var lowerTerm;
    var firstLetter;
    if(term == "_index") {
        lowerTerm = "";
        firstLetter = "index";
    } else {
        // make lowercase
        lowerTerm = term.toLowerCase();
        firstLetter = lowerTerm.substring(0,1);
        if(typeof firstLetter == "number") {
            firstLetter = "number";
        }
    }
    var anchor = lowerTerm.replace(/ /g,"_");
    if(popup) {
        var url = "definitions/" + firstLetter + ".jsp#" + anchor;
        showCenteredWindow(url, "define", 400, 350);
    } else {
        window.location = firstLetter + ".jsp#" + anchor;
    }
    return false;
}
// Shows a definition
function showMP3(file) {
    var url = "mp3player.jsp?file=" + escape("media/" + file);
    showCenteredWindow(url, "mp3", 320, 170);
    return false;
}

// Zooms in on an image
function galleryZoom(img, text) {
    showCenteredWindow("gallery.jsp?image="+escape(img)+"&caption="+escape(text), "gallery", 550, 450);
}

/**************************************************
 *  [function] Definition functions
 **************************************************/
function d_hover(id, over) {
    if(gebi) {
        var termId = "term_" + id;
        var obj = document.getElementById(termId);
        if(over) {
            obj.className = "definition definitionHover";
        } else {
            obj.className = "definition";
        }
    }
    return true;
}

/**************************************************
 *  [function] Package Cart Functions
 **************************************************/
document.currentPage = "none";
// toggles visibility of a package pricing list
function toggleVisible(id, state) {
    if(gebi) {
        var className = document.getElementById(id).className;
        if(arguments.length == 1) {
            // switch the style
            if(className=="packages") {
                state = true;
            } else {
                state = false;
            }
        }
        if(state) {
            document.getElementById(id).className = "packages visible";
            document.location = "#_" + id;
        } else {
            document.getElementById(id).className = "packages";
        }
        document.getElementById(id+"Button").blur();
        if(document.focus && (typeof document.focus == "function")) {
            document.focus();
        }
        // when hidden, show selected package list or generic message if nothing selected
        packageManager.categories[id].updateMessage();
    }
}
function jumpTo(id) {
    toggleVisible(id, true);
    /*document.location = ("#_" + id);*/
    /*document.focus();*/
}

function toggleCheckedFromRow(id) {
    if(ignore_package_click != id && gebi) {
        var cb = document.getElementById(id + "Checkbox");
        cb.checked = !cb.checked;
        toggleChecked(id, cb);
    }
    ignore_package_click = null;
}
ignore_package_click = null;

// handles (un)checking of a package
function toggleChecked(id, checkbox) {
    if(gebi) {
        // based on checkbox state, updated style
        var checked = checkbox.checked;
        var row = document.getElementById(id + "Row");
        // we have to split the class name up, and pull out the
        // "checked" class.  Then we add it back in if we need later.
        var oldClass = row.className;
        var classNames = oldClass.split(" ");
        var newClassName = "";
        for(var i=0; i<classNames.length; i++) {
            if(classNames[i] != "checked") {
                if(newClassName != "") {
                    newClassName += " ";
                }
                newClassName += classNames[i];
            }
        }
        if(checked) {
            row.className = newClassName + " checked";
            // here we add the selected packages to the list
            addToList(id);
        } else {
            row.className = newClassName;
            // here we remove unselected packages from the list
            removeFromList(id);
        }
        ignore_package_click = id;
    }
}
// Adds a package to the list
function addToList(id) {
    // adds an item to the list from the pagePackages
    
    var pack = packageManager.packages[id];
    // can't add if not listed on this page.
    if(pack != null) {
        // if it's already been added (say, by another page), ignore it
        if(findPackage(id) < 0) {
        
            // remove any excludes
            for(var i=0; i<pack.excludes.length; i++) {
                removeFromList(pack.excludes[i]);
            }
                
            // add to the list, sorted
            var loc = 0;
            for(; loc < selectedPackages.length; loc++) {
                if(pack.compareTo(selectedPackages[loc]) < 0) {
                    break;
                }
            }
            for(var i=selectedPackages.length; i>loc; i--) {
                selectedPackages[i] = selectedPackages[i-1];
            }
            selectedPackages[loc] = pack;
            //selectedPackages[selectedPackages.length] = pack;
            
            // redraw/store list
            updateList();
        }
    }
}
// Finds a package in the selected list
function findPackage(id) {
    var index = -1;
    for(var i=0; i<selectedPackages.length; i++) {
        if(selectedPackages[i].id == id) {
            index = i;
            break;
        }
    }
    return index;
}
// Asks the user before removing a package.
function askToRemove(id) {
    var idx = findPackage(id);
    if(idx >= 0) {
        var msg = "Is it OK to remove the package \"" + selectedPackages[idx].name + "\" from the list?"
        if(confirm(msg)) {
            removeFromList(idx);
        }
    }
}
// Removes a package from the list
function removeFromList(id) {
    // removes an item from the list  (any item can be removed)
    var index = -1;
    if(typeof id == "number") {
        if(id < selectedPackages.length) {
            index = id;
        }
    } else {
        // see if we can find the item to be removed
        index = findPackage(id);
    }
    // if it's been found...
    if(index > -1) {
        // bump everyone else up
        for(var i=index; i<selectedPackages.length-1; i++) {
            selectedPackages[i] = selectedPackages[i+1]
        }
        // drop the last item
        selectedPackages.length = selectedPackages.length-1;
        
        // redraw/store list
        updateList();
    }
}
// Wipes out the whole list
function clearList(ask) {
    // make sure there are items in the list
    if(selectedPackages.length > 0) {
        // if requested, ask for permission first
        if(!ask || confirm("OK to remove all of the packages you have selected?")) {
            // reset array
            selectedPackages = new Array();
            // redraw/store list
            updateList();
        }
    } else {
        if(gebi) {
            document.getElementById("cart-clear").blur();
            document.focus();
        }
    }
}
// Redraws and stores the list
function updateList() {
    drawList();
    storeList();
}
// Draws the list on the screen, handles any miscellaneous visual updates
// related to changing the list
function drawList() {
    // html is the content to be placed in the list
    var html = "";
    
    var pagePackage = packageManager.getPage(document.currentPage);
    
    // categories is used to keep track of what categories have checked items
    var categories = new Object();
    for(var i=0; i<pagePackage.categories.length; i++) {
        // Reset the update status
        pagePackage.categories[i].didUpdate = false;
    }
    // reset all packages on the page, so that we may uncheck those that have been
    // unchecked after we're through
    for(var pi in pagePackage.packages) {
        var p = pagePackage.packages[pi];
        p.didUpdate = false;
    }
    var prevPage = null;
    // Loop through selected packages, and add them to the cart's html
    for(var i=0; i<selectedPackages.length; i++) {
        // this link will return customers to where they first selected an item
        var link = selectedPackages[i].getURL();
        // add a separator for the different sections
        if(prevPage != selectedPackages[i].category.page.id) {
            if(prevPage != null) {
                html += "</div></div>";
            }
            prevPage = selectedPackages[i].category.page.id;
            html += "<div id='cartPage-" + prevPage + "' class='cartPageGroup";
            if((prevPage == document.currentPage) ||
                isCartListOpen(prevPage) ) {
                html += "Open";
            }
            html += "'><div class='cartPageTitle'><a href='#' class='button' onClick=\"return toggleCartList('";
            html += prevPage + "');\" title='Click to show or hide this group of items.'>From <strong>" + selectedPackages[i].category.page.name
            html += "</strong></a></div><div class='cartPagePackages'>";
        }
        // the html contains the 2 icons and the name
        html += "<div class='selectedPackage'><a href=\"javascript:askToRemove('" +
                    selectedPackages[i].id +
                    "');\" class=\"remove\" title=\"Click to remove this item from the list.\"><img src=\"img/remove.png\"></a>" +
                    "<a href=\"" + link + "\" title=\"Click to view this item's details.\"><div class='iconHolder'>" +
                    "<div class='classIcon'><img src='img/icons/24/" +
                    selectedPackages[i].classIcon + ".png'></div>" +
                    "<div class='categoryIcon'><img src='img/icons/16/" +
                    selectedPackages[i].getCategoryIcon() + ".png'></div>" +
                "</a></div>" +
                "<div class='name'><a href=\"" + link + "\" title=\"Click to view this item's details.\">" +
                    selectedPackages[i].name + "</a></div></div>";
        // update page if possible
        if(gebi) {
            var id = selectedPackages[i].id;
            // if this package is on the page...
            if(pagePackage.packages[id] != null) {
                // store the change
                pagePackage.packages[id].didUpdate = true;
                // get the checkbox and check it
                var checkbox = document.getElementById(id + "Checkbox");
                checkbox.checked = true;
                // update the rendering
                toggleChecked(id, checkbox);
            }
        }
        
        // Start a new category array if needed
        if(!categories[selectedPackages[i].category.id]) {
            categories[selectedPackages[i].category.id] = new Array();
        }
        // add the selected Package to its category array
        // this allows us to create the (Selected: x,y,z) text later
        categories[selectedPackages[i].category.id][categories[selectedPackages[i].category.id].length] = selectedPackages[i];
    }
    if(gebi) {
        if(html == "") {
            // if there are no items, throw in some generic text
            html = "<p>While browsing the website, you can select packages that you are interested in, and they will appear here.</p><p>Once you've selected everything you like, click on \"Request More Information\" below for a personal reponse from one of our helpful staff.</p>";
            // disable buttons
            document.getElementById("cart-request-more").className = "buttondisabled fullwidth";
            document.getElementById("cart-clear").className = "buttondisabled fullwidth";
        } else {
            html += "</div></div><p>When you are finished, click on \"Request More Information\" below for a personal reponse from one of our helpful staff.</p>";
            // otheriwse, enable the buttons
            document.getElementById("cart-request-more").className = "button fullwidth";
            document.getElementById("cart-clear").className = "button fullwidth";
        }
        // set the cart's text
        document.getElementById("cart-contents").innerHTML = html;
        
        // uncheck anyone unselected
        for(var pi in pagePackage.packages) {
            var pack = pagePackage.packages[pi];
            if(!pack.didUpdate) {
                // get the checkbox and uncheck it
                var checkbox = document.getElementById(pack.id + "Checkbox");
                checkbox.checked = false;
                // update the rendering
                toggleChecked(pack.id, checkbox);
            }
        }
    }
    
    for(var pi in pagePackage.packages) {
        var p = pagePackage.packages[pi];
        // reset the categories on the page (in case they have nothing checked)
        p.didUpdate = false;
    }
    // For each of the categories we've found...
    for(categoryName in categories) {
        // category: array of PackageClasses by category
        var category = categories[categoryName];
        // cat: CategoryClass Object
        var cat = packageManager.categories[categoryName];
        // If this category is on the page, update the "Selected" text...
        if(cat != null && cat.page.id == document.currentPage) {
            var html = "(Selected: ";
            for(var i=0; i<category.length; i++) {
                if((html.length + category[i].name.length) > 75) {
                    html += ",...";
                    break;
                }
                if(i!=0) {
                    html += ", ";
                }
                html += category[i].name;
            }
            html += ")";
            // update the message
            cat.updateMessage(html);
            cat.didUpdate = true;
        }
    }
    for(var i=0; i<pagePackage.categories.length; i++) {
    // For all categories on the page we didn't update already
        if(!pagePackage.categories[i].didUpdate) {
        // set to the default message
            pagePackage.categories[i].updateMessage(null);
        }
    }
    
}

// opens or closes a page-section in the cart.
var openPanels = "";
function toggleCartList(id) {
    if(gebi) {
        var div = document.getElementById("cartPage-"+id);
        if(div) {
            if(div.className == "cartPageGroup") {
                openPanels += ";"+id;
                div.className = "cartPageGroupOpen";
            } else {
                var toReplace = "\\;" + id;
                openPanels = openPanels.replace(new RegExp(toReplace, "g"), "");
                div.className = "cartPageGroup";
            }
        }
    }
    return false;
}
function isCartListOpen(id) {
    return openPanels.indexOf(id) > -1;
}

// Sends the user to a page with their selected items
function requestInformation() {
    if(selectedPackages.length > 0) {
        // pass the requested packages to a contact form
        document.location = "contact-email.jsp";
    } else {
        if(gebi) {
            document.getElementById("cart-request-more").blur();
            document.focus();
        }
    }
}

// List of selected packages (from cookie, interaction).
selectedPackages = new Array();

/**************************************************
 *  [load] Load and Store code for packages
 **************************************************/
// Name of cookie to use
var PACKAGE_COOKIE_NAME = "etspackagelist";
var PACKAGE_SEPARATOR = ";";
var didAlert = false;
// This function stores the selected list in a cookie
function storeList() {
    var cookieValue = "";
        // Loop through the selected items, and add them to the cookie.
    for(var i=0; i<selectedPackages.length; i++) {
        if(i != 0) {
            // separate Packages with a character
            cookieValue += PACKAGE_SEPARATOR;
        }
        cookieValue += selectedPackages[i].id;
    }
    if(cookieValue == "") {
        deleteCookie(PACKAGE_COOKIE_NAME);
    } else {
        // Store for 7 days
        var expires = new Date();
        expires.setTime(expires.getTime() + 604800000);
        // Store the cookie
        setCookie(PACKAGE_COOKIE_NAME, cookieValue, expires);
        // DEBUG CODE
        //window.status = cookieValue;
    
        // Here we test to see if the cookie was saved.
        var cookieValue = getCookie(PACKAGE_COOKIE_NAME);
        if(!didAlert && cookieValue == null) {
            // Alert (once only) if the cookie was not stored.
            alert("Warning:\nIf you do not allow the cookie \""+PACKAGE_COOKIE_NAME+"\" to be stored, your selections will disappear after you leave this page.");
            didAlert = true;
        }
    }
}
// Load back in the cookie
function loadList() {
    // Try to find the cookie.
    var cookieValue = getCookie(PACKAGE_COOKIE_NAME);
    if(cookieValue != null) {
        // Reset the array
        selectedPackages = new Array();
        // Split into packages
        var crumbs = cookieValue.split(PACKAGE_SEPARATOR);
        for(var i=0; i<crumbs.length; i++) {
            var crumb = crumbs[i];
            // each "crumb" represents a package id
            var p = packageManager.packages[crumb];
            if(p != null) {
                selectedPackages[selectedPackages.length] = p;
            }
        }
    }
}

/**************************************************
 *  [cookie] Generic Cookie Handling
 **************************************************/
function getCookie(name) {
    var start = document.cookie.indexOf(name + '=');
    var len = start + name.length + 1;
    if((!start) && (name != document.cookie.substring(0,name.length))) {
        return null;
    }
    if(start == -1) {
        return null;
    }
    var end = document.cookie.indexOf(';',len);
    if(end == -1) {
        end = document.cookie.length;
    }
    return unescape(document.cookie.substring(len,end));
}
function setCookie(name,value,expires,path,domain,secure) {
    document.cookie =
        name + '=' + escape(value) +
        ( (expires) ? ';expires=' + expires.toGMTString() : '') +
        ( (path) ? ';path=' + path : '') + 
        ( (domain) ? ';domain=' + domain : '') +
        ( (secure) ? ';secure' : '');
}
function deleteCookie(name,path,domain) {
  if(getCookie(name)) {
    document.cookie =
        name + '=' +
        ( (path) ? ';path=' + path : '') +
        ( (domain) ? ';domain=' + domain : '') +
        ';expires=Thu, 01-Jan-1970 00:00:01 GMT';
    }
}

// sets up the contact form, if requested
function loadContactForm() {
    if(gebi) {
        if(selectedPackages.length == 0) {
            var sel = document.getElementById("form-selectedPackages");
            sel.className = "form hidden";
        } else {
            var sel = document.getElementById("form-selectedPackages");
            sel.className = "form";
            var page = "";
            var html = "<ul class=\"selectedPackages\">";
            var commaReset = true;
            var countStart = 0;
            for(var i=0; i<selectedPackages.length; i++) {
                var pack = selectedPackages[i];
                if(pack.category.page.id != page) {
                    if(page != "") {
                        html = addAnd(html, countStart);
                        html += "</div></li>";
                    }
                    html += "<li class=\"selectedPackagePage\"><div class='title'>";
                    html += "<a href='" + pack.category.page.getURL() + "'>";
                    html += pack.category.page.name;
                    html += ":</a></div><div class='items'>";
                    page = pack.category.page.id;
                    commaReset = true;
                    countStart = html.length;
                }
                if(!commaReset) {
                    html += ", ";
                } else {
                    commaReset = false;
                }
                html += "<a href=\"" + pack.getURL() + "\">" +
                        "<input type=\"hidden\" name=\"selectedPackages\" value=\"" +
                        pack.name + " (" + pack.id
                        + ")\"/>" + pack.name +
                        "</a>";
            }
            html = addAnd(html, countStart);
            html += "</div></li></ul>";
            document.getElementById("form-selectedPackages-description").innerHTML = html;
        }
    }
}
function addAnd(html, start) {
    var loc = html.lastIndexOf("</a>, ");
    if(loc > start) {
        html = html.substring(0, loc) + "</a>, and " + html.substring(loc+6);
    }
    return html;
}
function getStyle(el) {
    var style = el;
    if(style.style) {
        style = style.style;
    }
    return style;
}

/***************
 * Cart Pinning
 ***************/
var cartIsPinned = getCookie("pincart") == "true";
function pinCart() {
    cartIsPinned = !cartIsPinned;
    updateCartPin();
}
function updateCartPin() {
    // Store for 7 days
    var expires = new Date();
    expires.setTime(expires.getTime() + 604800000);
    // Store the cookie
    setCookie("pincart", cartIsPinned ? "true" : "false", expires);
    if(cartIsPinned) {
        if(gebi) {
            document.getElementById("cartPin").className = "pinned";
        }
    } else {
        if(gebi) {
            document.getElementById("cartPin").className = " ";
        }
        scrollTheCart();
    }
}
var oldScrollAmount = 0;
function scrollTheCart() {
    if(!cartIsPinned) {
        var scrollAmount;
        if (self.pageYOffset) {
            // all except Explorer
        	scrollAmount = self.pageYOffset;
        } else if (document.documentElement && document.documentElement.scrollTop) {
           	// Explorer 6 Strict
        	scrollAmount = document.documentElement.scrollTop;
        } else if (document.body) {
            // all other Explorers
        	scrollAmount = document.body.scrollTop;
        }
        if(scrollAmount != oldScrollAmount) {
            oldScrollAmount = scrollAmount;
            var pageHeight;
            var test1 = document.documentElement.scrollHeight;
            var test2 = document.documentElement.offsetHeight
            if (test1 > test2) {
                // all but Explorer Mac
            	pageHeight = test1;
            } else {
                // Explorer Mac;
                 //would also work in Explorer 6 Strict, Mozilla and Safari
            	pageHeight = test2;
            }
            if(pageHeight > 0 && gebi) {
                var el = document.getElementById("cart");
                if(el) {
                    var elHeight = 0;
                    if(el.offsetHeight) {
                        elHeight = el.offsetHeight;
                    } else if(el.document && el.document.height) {
                        elHeight = el.document.height;
                    }
                    if(pageHeight > (78+(scrollAmount+elHeight))) {
                        getStyle(el).top = scrollAmount+"px";
                    } else {
                        var minTest = pageHeight - (elHeight+78);
                        if(minTest < 0) {
                            minTest = 0;
                        }
                        getStyle(el).top = minTest+"px";
                    }
                }
            }
        }
        setTimeout("scrollTheCart();", 20);
    }
}

// Used to make external links open in a new window, in an XHTML-friendly way.
function updateExternalLinks() {
    if(document.getElementsByTagName) {
        var anchors = document.getElementsByTagName("A");
        for(var i=0; i<anchors.length; i++) {
            var a = anchors[i];
            if(a.className.indexOf("external-link") != -1) {
                a.target = "_blank";
                if(a.title) {
                    a.title += "  ";
                }
                a.title += "(Opens in a new window.)";
            }
        }
    }
}


/**************************************************
 *  [init] Initialization Code
 **************************************************/
// Loads in any already selected items (from cookie) and corrects page
function initialize() {
    // use cookie to initialize the page and the "shoppingcart"
    if(gebi) {
        // if the cart doesn't exist, don't do anything.
        if(document.getElementById("cart")) {
            loadList();
            drawList();
            scrollTheCart();
            updateCartPin();
        }
        didAlert = false;
        updateExternalLinks();
    }
}
// Setup (calls initialize on page loading)
if(window && Listener) {
    // add as a higher-than-default priority method.
    Listener.add(window, "onload", initialize, this, 1, 1);
}