// Javascript functions for Project Jack

// Global variables 
var gCookieName = "comparelist";
var gCompareItemsMax = 3;
var gCompareItemsMaxWord = 'three';
var gSuffixThumbs = "png";
var gUrlIconRemoveItem = "/media/images/cds_delete.gif";
var gUrlImgArrowUp = "/media/images/arrow_up_bendy.gif";
var gUrlArrowDown = "/media/images/arrow_down_bendy.gif";
var gHrefLinkArrowUp = "#main_top";
var gHrefLinkArrowDown = "#main_bottom";
var gUrlCompareItemsFormAction = "main-catalogue-compare";
var gCompareHeaders = [];

// Global variables declared here yet their values are set by html page
// after pages loads.
var gUrlbaseThumbs = "";
var gCnetItemProdcodes = [];
var gCnetItemBlowupProdcodes = [];

// Public functions, ie, event handlers and pseudo-url
// ---------------------------------------------------

// createCompareWidgets()
// Onload handler for:
// 1. Create checkbox and compare-link for items that have CNET data and
//    set status of checkboxes per prodcodes in cookie.
// 2. Create compare-headers and display item icons per prodcodes in cookie.
// 3. Create compare-count widget in dashboard and display count 
//    per prodcodes in cookie. 
// Argument: none
// Return: none
function createCompareWidgets()
{
    createCompareItemCheckboxes();
    createCompareHeaders();
    createDashboardCompareDisplay();
}

// updateCompareList( cb )
// Onclick handler for the item checkboxes on browse/search result page.
// Adds/removes prodcode of the clicked item to/from the comparelist cookie.
// Alerts user if the item is checked and the number of items already picked
// is at limit. Updates dashboard and compare-header afterwards.
// Argument: object reference of the active object
// Return: none
function updateCompareList( cb )
{
    if ( document.cookie.length <= 0 ) 
        return;

    // reject selection when items num greater than limit
    if ( cb.checked ) {
        var prodcodes = getCookieProdcodesAsArray();
        if ( prodcodes.length >= gCompareItemsMax ) {
            alert("Please limit your comparison to a maximum of " + gCompareItemsMaxWord + " products.");
            cb.checked = false;
            return;
        }
    }

    // update status of the 'other' checkbox
    var id = cb.id;
    var prodcode = id.replace(/^[bc]i_/, "");

    // when select is via blowup checkbox
    if ( id.match(/^bi_/) ) {
        // update corresponding checkbox in search-result list
        var ci_cb = document.getElementById( "ci_" + prodcode );
        if ( ci_cb ) ci_cb.checked = cb.checked;
    }
    // when select is via search-result checkbox
    else if ( id.match(/^ci_/)  ) {
        // update corresponding checkbox in blowup
        var bi_cb = document.getElementById( "bi_" + prodcode );
        if ( bi_cb ) bi_cb.checked = cb.checked;
    }
    else { }

    // update cookie
    if ( cb.checked ) 
        appendProdcodeToCookie( prodcode );
    else
        removeProdcodeFromCookie( prodcode );

    // update compare-widgets
    updateCompareHeader(); 
    updateDashboard();
}

// removeItemFromCompareList( elm )
// Onclick handler for the remove-item icons on compare-header.
// Removes the item from the comparelist cookie then updates 
// the compare-header and dashboard.
// Argument: object reference of the remove-item icon
// Return: none
function removeItemFromCompareList( elm )
{
    var prodcode = elm.prodcode;
    if ( ! prodcode ) return;

    // update cookie
    removeProdcodeFromCookie( prodcode );

    // update the associated checkbox if it exists on current page

    // in search-result list
    var cb = document.getElementById( "ci_" + prodcode );
    if ( cb ) cb.checked = false;

    // in blowup
    var cb2 = document.getElementById( "bi_" + prodcode );
    if ( cb2 ) cb2.checked = false;

    // update other compare-widgets
    updateCompareHeader(); 
    updateDashboard();
}

// removeItemFromCompareResultPage( prodcode )
// Function (pseudo-url) for the 'Remove' icon on 'Compare Products' page.
// Removes an item from the comparelist cookie then reloads the current screen.
// Argument: prodcode
// Return: none
function removeItemFromCompareResultPage( prodcode )
{
    // update cookie
    removeProdcodeFromCookie( prodcode )

    // reload page
    // note: do not use window.location.reload as browser usually asks for 
    // confirmation
    var url = window.location;
    window.location = url;
}

// clearCompareList()
// Function (pseudo-url) for the 'clear' link in dash board.
// Removes all prodcodes in cookie then update compare-header and dashboard.
// Argument: none
// Return: none
function clearCompareList()
{
    var prodcodes = getCookieProdcodesAsArray();

    // clear cookie
    document.cookie = gCookieName + "=_";

    // uncheck compare-item checkbox 
    for ( var i = 0; i < prodcodes.length; i++ ) {

        // in search-result list
        var cb = document.getElementById( "ci_" + prodcodes[i] );
        if ( cb ) cb.checked = false;

        // in blowup
        var cb2 = document.getElementById( "bi_" + prodcodes[i] );
        if ( cb2 ) cb2.checked = false;
    }

    // update compare-items widgets
    updateDashboard();
    updateCompareHeader(); 

    // if current page is 'Compare Products' page, goto home page
    if ( document.getElementById( "compare_results_page" ) ) {
        window.location = "/";
    }
}

// Private functions
// -----------------

// getCookie( cookieName )
// Fetches current value of the named cookie
// Argument: name of cookie
// Return: cookie value as string if cookie exists or an empty string otherwise
function getCookie( cookieName )
{
    if ( document.cookie.length < 1 ) return "";

    var names_values = unescape(document.cookie).split("; ");
    for ( var i = 0; i < names_values.length; i++ ) {
        var name_val = names_values[i].split("=");
        if ( name_val.shift() == cookieName ) 
            return name_val.shift();
    }

    return "";
}

// getCookieProdcodesAsArray()
// Fetches prodcodes in 'comparelist' cookie and store them as array elements.
// Argument: none
// Return: array of prodcodes if cookie exists or an empty array otherwise
function getCookieProdcodesAsArray()
{
    var prodcodes = getCookie(gCookieName).match( /[0-9a-zA-Z]+/g );
    if ( !prodcodes ) prodcodes = [];
    return prodcodes;
}

// updateCompareHeader() 
// Refreshes the compare-header to current cookie value
// Argument: none
// Return: none
function updateCompareHeader() 
{
    // check if any items picked
    var prodcodes = getCookieProdcodesAsArray();
    var hasCompareItem = prodcodes.length > 0 ? true : false;

    // check if page has compareitems headers (the 'ttml' placeholders)
    var hdrsTtml = [];
    var hdrTopTtml = document.getElementById( "ci_hdr_t" );
    var hdrBtmTtml = document.getElementById( "ci_hdr_b" );

    if ( hdrTopTtml ) {
        hdrsTtml.push( hdrTopTtml );
    }

    if ( hdrBtmTtml ) {
        hdrsTtml.push( hdrBtmTtml );
    }

    // no ttml header, ie, non current page is non-search result page, 
    // no update required.
    if ( hdrsTtml.length < 1 ) return;

    // if no comparison item, hide headers
    if ( ! hasCompareItem ) {
        for ( var i = 0; i < hdrsTtml.length; i++ ) {
            hdrsTtml[i].style.visibility = "hidden";
        }
        return;
    }

    // has comparison item, attach header to ttml header if they are not 
    // attached already, then show the ttml header
    for ( var i = 0; i < hdrsTtml.length; i++ ) {
        var hdrTtml = hdrsTtml[i];
        var hdr = gCompareHeaders[i];
        if ( ! getImmediateChildOfElmentByName( hdrTtml, "header" )  ) {
            hdrTtml.appendChild( hdr );
        }
        hdrTtml.style.visibility = "visible";
    }

    // update top and bottom headers
    for ( var v = 0; v < gCompareHeaders.length; v++ ) {

        // header
        var hdr = gCompareHeaders[v];

        // icon container
        var iconContainersHolder = 
            getImmediateChildOfElmentByName( hdr, "icon_containers_holder"  );

        // show the 'item_added' and 'remove_item' icons for each prodcode picked
        for ( var idx = 0; idx < gCompareItemsMax; idx++ ) {
            var iconContainers = iconContainersHolder.childNodes;
            var iconContainer = iconContainers[idx];
            var prodcode = prodcodes[idx];

            var imgAddedItem = 
                getImmediateChildOfElmentByName( iconContainer, "item_added" );
            var imgRemoveItem = 
                getImmediateChildOfElmentByName( iconContainer, "remove_item" );
            var textIconContainer = 
                getImmediateChildOfElmentByName( iconContainer, "icon_container_text" );

            if ( prodcode ) {
                // set 'no-image' background text just in case item don't have thumb
                textIconContainer.innerHTML = "No Image";

                // show 'added_item' icon
                imgAddedItem.src = 
                    gUrlbaseThumbs + "/" + prodcode + "." + gSuffixThumbs;
                imgAddedItem.className = "item_added";
                imgAddedItem.title = "remove " + prodcode;
                imgAddedItem.prodcode = prodcode;
                imgAddedItem.onclick = 
                    function(){ removeItemFromCompareList( this ) };
                imgAddedItem.style.display = "block";

                // show 'remove_item' icon
                imgRemoveItem.src = gUrlIconRemoveItem;
                imgRemoveItem.title = "remove " + prodcode;
                imgRemoveItem.prodcode = prodcode;
                imgRemoveItem.onclick = 
                    function(){ removeItemFromCompareList( this ) };
                imgRemoveItem.style.display = "block";
            }
            else {
                // clear background text
                textIconContainer.innerHTML = "";

                // hide icons
                imgAddedItem.style.display = "none";
                imgRemoveItem.style.display = "none";
            }
        }
    }
}

// appendProdcodeToCookie( prodcode )
// Append prodcode of the target item to value of the comparelist cookie.
// Argument: target prodcode
// Return: none
function appendProdcodeToCookie( prodcode )
{
    var prodcodesStr = getCookie( gCookieName );
    prodcodesStr = prodcodesStr + "_" + prodcode;
    document.cookie = gCookieName + "=" + prodcodesStr;
}

// removeProdcodeFromCookie( prodcode )
// Removes prodcode of the target item from the value of the comparelist cookie.
// Argument: target prodcode
// Return: none
function removeProdcodeFromCookie( prodcode )
{
    var re = new RegExp();
    re.compile( "_" + prodcode );
    var prodcodesStr = getCookie( gCookieName );
    prodcodesStr = prodcodesStr.replace( re, "" );
    document.cookie = gCookieName + "=" + prodcodesStr;
}

// updateDashboard()
// Updates compare-items count in dashboard to current value in comparelist cookie.
// Argument: none
// Return: none
function updateDashboard()
{
    // Retrieve the dashboard widget placeholder.
    // Note: dashboard won't show up when server retunrs an error page.
    var wgtDshbdCompare = document.getElementById( "dashboard_compare" );
    if ( ! wgtDshbdCompare ) return;

    var prodcodes = getCookieProdcodesAsArray();
    var hasCompareItem = prodcodes.length > 0 ? true : false;

    var compareLabel 
        = getImmediateChildOfElmentByName( wgtDshbdCompare, "div_left" );
    var compareQuan 
        = getImmediateChildOfElmentByName( wgtDshbdCompare, "div_right" );
    var quanTxt 
        = getImmediateChildOfElmentByName( compareQuan, "div_right_span" );

    // update widgets
    if ( hasCompareItem ) {
        compareLabel.style.visibility = "visible";
        compareQuan.style.visibility = "visible";
        quanTxt.innerHTML = prodcodes.length;
    }
    else {
        compareLabel.style.visibility = "hidden";
        compareQuan.style.visibility = "hidden";
    }
}

// updateItemCheckboxes()
// Updates the status of compare-checkboxes based on the current value of 
// the comparelist cookie.
// Argument: none
// Return: none
function updateItemCheckboxes()
{
    var prodcodes = getCookieProdcodesAsArray();
    for ( var i = 0; i < prodcodes.length; i++ ) {

        // in search-result list
        var cb = document.getElementById( "ci_" + prodcodes[i] );
        if ( cb ) cb.checked = true;

        // in blowup
        var cb2 = document.getElementById( "bi_" + prodcodes[i] );
        if ( cb2 ) cb2.checked = true;
    }
}

// createDashboardCompareDisplay()
// Creates the dashboard compare label quantity widgets after page loads.
// Then updates the compare items count as per prodcodes in cookie
// Argument: none
// Return: object reference of the widget
function createDashboardCompareDisplay()
{
    // Retrieve the dashboard widget placeholder.
    // Note: dashboard won't show up when server retunrs an error page.
    var wgtDshbdCompare = document.getElementById( "dashboard_compare" );
    if ( ! wgtDshbdCompare ) return;

    // create "label" widget

    // create container
    var wgtLabel = document.createElement( "div" );
    wgtLabel.name = "div_left";
    wgtLabel.className = "left dashboard_compare_label";

    // create link
    var aLabel = document.createElement( "a" );
    aLabel.href = "main-catalogue-compare";
    aLabel.innerHTML = "Compare";
    aLabel.setAttribute( "title", "Click to compare products.");
    wgtLabel.appendChild( aLabel );

    // create colon
    var txtLabel = document.createTextNode( ":" );
    wgtLabel.appendChild( txtLabel );

    // attache wgt to container
    wgtDshbdCompare.appendChild( wgtLabel );


    // create "quan" widget

    // create container
    var wgtQuan = document.createElement( "div" );
    wgtQuan.name = "div_right";
    wgtQuan.className = "right";

    // create text node
    var spanQuan = document.createElement( "span" );
    spanQuan.name = "div_right_span";
    spanQuan.className = "right dashboard_compare_quan";
    spanQuan.innerHTML = "";

    wgtQuan.appendChild( spanQuan );
    
    // create 'clear' link
    var spanClear = document.createElement( "span" );

    var txt = document.createTextNode( " (" );
    spanClear.appendChild( txt );

    var aQuan = document.createElement( "a" );
    aQuan.href = "javascript:clearCompareList()";
    aQuan.innerHTML = "clear";
    aQuan.setAttribute( 'title', 'Remove all products from comparison.');
    spanClear.appendChild( aQuan );

    txt = document.createTextNode( ") " );
    spanClear.appendChild( txt );

    wgtQuan.appendChild( spanClear );

    // attach widget to container
    wgtDshbdCompare.appendChild( wgtQuan );

    // update number of compare items per prodcodes in cookie
    updateDashboard();
}

// getImmediateChildOfElmentByName( elm, childName )
// Find the first immediate child of the specified name in element 
// Argument: 
//  1. object reference of the concerned element.
//  2. name of the target child.
// Return: object reference of the first named child found and null otherwise
function getImmediateChildOfElmentByName( elm, childName )
{
    if ( ! elm.lastChild ) return;
    var elms = elm.childNodes;
    for ( var i = 0; i < elms.length; i++ ) {
        var elm = elms[i];
        if ( elm.nodeType != 1 ) continue;
        if ( ! elm.name ) continue;
        if ( elm.name != childName ) continue;
        return elm;
    }
    return null;
}

// createCompareHeaders()
// Create the compare-item headers and their children icon widgets after page loads.
// Then update the icons as per prodcodes in cookie.
// Argument: none
// Return: array of the headers with all required widgets in them.
function createCompareHeaders()
{
    var verticalPositions = [ "t", "b" ];

    for ( var v = 0; v < verticalPositions.length; v++ ) {
        var vp = verticalPositions[v];

        // header
        var hdr = document.createElement( "div" );
        hdr.name = "header";
        hdr.className = "compareitems_header_js";
        gCompareHeaders[v] = hdr;

        // to-top and to-bottom arrow links
        var arrowHolder = document.createElement( "div" );
        arrowHolder.name = "arrow_holder";
        hdr.appendChild( arrowHolder );

        var arrow = document.createElement( "a" );
        arrow.name = "arrow";
        arrowHolder.appendChild( arrow );

        var arrowImg = document.createElement( "img" );
        arrowImg.name = "arrow_img";

        if ( vp == "t" ) {
            arrowHolder.className = "compareitems_arrow_top";
            arrow.href = gHrefLinkArrowDown
            arrowImg.src = gUrlArrowDown;
            arrowImg.title = "to page bottom";
        }
        else {
            arrowHolder.className = "compareitems_arrow_btm";
            arrow.href = gHrefLinkArrowUp;
            arrowImg.src = gUrlImgArrowUp;
            arrowImg.title = "to page top";
        }
        arrow.appendChild( arrowImg );

        // holder for compareitems form
        var formHolder = document.createElement( "div" );
        formHolder.name = "form_holder";
        formHolder.className = "compareitems_form_holder";
        hdr.appendChild( formHolder );

        // compareitems form 
        var form = document.createElement( "form" );
        form.name = "form";
        form.method = "post"; 
        form.action = gUrlCompareItemsFormAction;
        formHolder.appendChild( form );

        // compareitems form button
        var button = document.createElement( "input" );
        button.name = "form_button";
        button.type = "submit";
        button.value = "Compare";
        button.className = "compareitems_button";
        form.appendChild( button );

        // holder for icon containers 
        var iconContainersHolder = document.createElement( "div" );
        iconContainersHolder.name = "icon_containers_holder";
        iconContainersHolder.className = "icons_container";
        hdr.appendChild( iconContainersHolder );

        // icon container
        for ( var idx = 0; idx < gCompareItemsMax; idx++ ) {

            // icon container
            var iconContainer = document.createElement( "div" );
            iconContainer.name = "icon_container";
            iconContainer.className = "icon_container";
            iconContainersHolder.appendChild( iconContainer );

            // no-image text 
            var textBox = document.createElement( "div" );
            textBox.name = "icon_container_text";
            textBox.className = "icon_container_text";
            iconContainer.appendChild( textBox );

            // item_added icon
            var iconAdded = document.createElement( "img" );
            iconAdded.name = "item_added";
            iconAdded.className = "item_added";
            iconContainer.appendChild( iconAdded );

            // remove_item icon
            var iconRemove = document.createElement( "img" );
            iconRemove.name = "remove_item";
            iconRemove.src = gUrlIconRemoveItem;
            iconRemove.className = "remove_item";
            iconContainer.appendChild( iconRemove );
        }

        // holder for compare item max quantity descp
        var descp = document.createElement( "div" );
        descp.name = "compareitems_descp";
        descp.className = "compareitems_descp";

        hdr.appendChild( descp );

        // holder for 'clear' css rule
        var clear = document.createElement( "div" );
        clear.className = "clear";
        hdr.appendChild( clear );
    }

    // update icons based on prodcodes in cookie
    updateCompareHeader(); 
}

// createCompareItemCheckboxes()
// Create checkbox and compare-link for items that have cnet data after page loads. 
// The list of items is populated in an associative array in ttml. 
// Status of the checkboxes are then updated using the prodcodes in cookie.
// Argument: none
// Return: none.
function createCompareItemCheckboxes()
{
    // create checkboxes and links below the thumbnail of items that
    // have cnet data, based on the prodcodes populated in the associative
    // array in ttml.

    // For checkboxes in search-result list
    for ( var prodcode in gCnetItemProdcodes ) {
        var cbHolderId = gCnetItemProdcodes[prodcode];
        if ( !cbHolderId ) continue;

        var cbHolder = document.getElementById( cbHolderId );
        if ( !cbHolder ) continue;

        cbHolder.className = "compareitems_checkbox";
        createCheckbox( cbHolder, "ci_", prodcode )
    }

    // For checkbox in blowup
    if ( gCnetItemBlowupProdcodes.length > 0 ) {
        for ( var prodcode in gCnetItemBlowupProdcodes ) {
            var cbHolderId = gCnetItemBlowupProdcodes[prodcode];
            if ( !cbHolderId ) continue;

            var cbHolder = document.getElementById( cbHolderId );
            if ( !cbHolder ) continue;

            cbHolder.className = "compareitems_checkbox";
            createCheckbox( cbHolder, "bi_", prodcode )
        }
    }

    // set checkbox status based on prodcodes in cookie
    var prodcodes = getCookieProdcodesAsArray();
    for ( var i = 0; i < prodcodes.length; i++ ) {

        // in search-result list
        var cb = document.getElementById( "ci_" + prodcodes[i] );
        if ( cb ) cb.checked = true;

        // in blowup
        var cb2 = document.getElementById( "bi_" + prodcodes[i] );
        if ( cb2 ) cb2.checked = true;
    }
}

// createCheckbox( cbHolder, idprefix, prodcode ) 
// Create checkbox and compare-link for the supplied item.
// Argument:
//   1. cbHolder: object reference of checkbox container. 
//   2. idprefix: prefix of element-id of the container. 
//   3. prodcode: item prodcode.
// Return: none.
function createCheckbox( cbHolder, idprefix, prodcode )
{
        var cb = document.createElement( "input" );
        cb.type = "checkbox";
        cb.id = idprefix + prodcode;
        cb.name = cb.id;
        cb.onclick = function(){ updateCompareList( this ); };
        cbHolder.appendChild( cb );

        var a = document.createElement( "a" );
        a.href = "main-catalogue-compare";
        a.innerHTML = "Compare";
        a.setAttribute( "title", "Click to compare products." );
        cbHolder.appendChild( a );
}
