var gcs_suggestionFlag;
var originFormSubmit;

$(document).ready(function() {
    init_googleSearch();
});

function isBrand(brandName) {
    var href = window.location.href.toLowerCase();
    if (href.indexOf(brandName) < 0)
        return false;
    else
        return true;
}

var cellHeight = 206;
var cellWidth = 199;
var promotionHeight = 0;

var IMAGE_SIZE = 90;     // workaround the error of google api
var RESULTS_LIMIT = 20;  // less than 250
var lastKey = "";

/**
 * Escapes the given string, so it is HTML safe.
 * @param {string} html The input HTML to escape.
 * @return {string} The escaped HTML.
 */
function escapeHtml(html) {
  var s = '' + html;
  return s.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;')
      .replace(/"/g, '&quot;').replace(/'/g, '&#39;');
}

/**
 * Escapes the given URL.
 * @param {string} url The URL to escape.
 * @return {string} The escaped URL.
 */
function escapeUrl(url) {
  return url.replace(/</g, '%3C').replace(/>/g, '%3E').replace(/"/g, '%22');
}

/**
 * Escape a string, so that we can embed the string in the js code inside
 * another string.
 * @param {string} str The string to escape.
 * @return {string} The escaped string.
 */
function escapeJsString(str) {
    return str.replace(/\\/g, '\\\\').replace(/\"/g, '\\\"')
      .replace(/\'/g, '\\\'').replace(/&/g, '%26');
}

/**
* Adds ellipses to long strings.
* @param {Number} nChars Maximum number of characters in result.
* @param {String} str String to possibly add ellipses to.
* @return {String} a string no longer than nChars.
*/
function truncateAndAddEllipses(nChars, str) {
    return str.length > nChars ? str.substring(0, nChars - 3) + '...' : str;
}

/**
 * Strips off all HTML tags.
 * @param {string} html The input HTML.
 * @return {string} The stripped version of HTML.
 */
function stripOffHtmlTags(html) {
  var s = '' + html;
  return s.replace(/\<[^\>]+\>/g, '');
}

/**
 * Escapes characters that must be escaped for the shopping API.
 * @param {String} name Name to be escaped.
 * @return {String} The escaped name.
 */
function escapeShoppingApiString(name) {
    var reg = '/([,/=:|()])/g';
    return name.replace(reg, '\\$1');
}

function escapeRestrictString(str) {
    return str.replace(/\"/g, '%22').replace(/\'/g, '%27').replace(/&/g, '%26');
}

function unEscapeRestrictString(str) {
    return str.replace(/%22/g, '\"').replace(/%23/g, '\'').replace(/%26/g, '&');
}

function escapeQueryString(str) {
    str = str.replace(/ /g, '+').replace(/&/g, '%26').replace(/#/g, '%23');
    var reg = '/\//g';    
    return str.replace(reg, '%2F');
}

function unEscapeQueryString(str) {
    return str.replace(/\+/g, ' ').replace(/%26/g, '&').replace(/%2F/g, '/').replace(/%23/g, '#');
}

/**
* Returns the html for a single item.
* @param {ProductObject} product Product to generate data for.
* @param {String} view 'list' or 'grid'.
* @return {String} The html for this item.
*/
function getHTMLProduct(index, product, view, promotions) {
    var description = product.Description;
    if (description.length > 200) {
        description = description.substr(0, 200) + '...';
    }
    var thumb = product.ImageLink ? product.ImageLink : undefined;
    var title = product.Title;
    title = title.replace('""', '"');
    if (title[0] == '"' && title[title.length - 1] == '"')
        title = title.substring(1, title.length - 1);

    var domain = window.location.href.match(/^http:\/\/(.+?)\//i)[0];
    var link = product.CseLink;
    var href = domain + link.substring(1);
    href = escapeUrl(href);

    var price = formatPrice(parseFloat(product.Price), product.Currency);
    var priceMin = formatPrice(parseFloat(product.MinPrice), product.Currency);

    var itemId = product.ItemId;

    var customerRating =parseFloat( product.ReviewAverage);
    var reviewCount =parseFloat( product.ReviewCount);

    var html = getHTMLOneEntryGrid(index, thumb, title, href, price, priceMin, itemId, customerRating);
    return html;
}

function getAttributeValue(attrName, attributes) {
  if (attributes && attributes.length > 0){
     for (var i=0;i<attributes.length;i++)
     {
        if (attributes[i].name==attrName)
        return attributes[i].value;
     }
  };
  return "";
};

/**
* Returns the HTML for an array of items.
* @param {ItemObject[]} items Items to generate HTML for.
* @param {String} view 'list' or 'grid'.
* @return {String} The HTML for these items.
*/
function getHTMLItems(items, view, promotions) {
    var html = [];
    if (items) {
        for (var i = 0, len = items.length; i < len; ++i) {
            html[i] = getHTMLProduct(i, items[i], view, promotions);
        }
    }
    return html.join('');
}

function getHTMLFormattedPromotion(name, link, description, image_link) {
    var str = '<div class="cse-commerce-promotion">';
    str += '<table><tr>';
    if (image_link) {
        str +=
        '<td class="cse-commerce-promotion-image" width="' + IMAGE_SIZE + '">';
        str += '<a href="' + escapeUrl(link) + '">';
        str += '<img src="' + escapeUrl(image_link);
        str += '" height="' + IMAGE_SIZE + '" onload="imgOnLoad(this)"></img>';
        str += '</a>';
        str += '</td>';
    }
    str += '<td class="cse-commerce-promotion-title">' +
      '<strong><a href="' + escapeUrl(link) + '\">' +
      escapeHtml(stripOffHtmlTags(name)) + '</a></strong>';
    if (description) {
        str += '<br/><span>' + escapeHtml(description) + '</span>';
    }
    str += '</div></td></tr></table></div>';
    return str;
}

/**
* Returns the html for a single standard promotion.
* @param {PromotionObject} promotion Promotion to generate data for.
* @return {String} The html for this promotion.
*/
function getHTMLStandardPromotion(promotion) {
    return getHTMLFormattedPromotion(promotion.name, promotion.destLink,
                                   promotion.description, promotion.imageLink);
}

/**
* Returns the html for a single product promotion.
* @param {PromotionObject} promotion Promotion to generate data for.
* @return {String} The html for this promotion.
*/
function getHTMLProductPromotion(promotion) {
    var product = promotion.product;
    var image = null;
    if (product.images) {
        image = product.images[0].link;
    }
    return getHTMLFormattedPromotion(product.title, product.link,
                                   product.description, image);
}

/**
* Returns the html for a single custom promotion.
* @param {PromotionObject} promotion Promotion to generate data for.
* @return {String} The html for this promotion.
*/
function getHTMLCustomPromotion(promotion) {
    var promString = "";
    // ie does not allow inline style definitions inside script, we have to add them into the css object
    if ($.browser.msie) { 
        var css = getCssObject();
        var style = fetchStyle(promotion.customHtml);
        promString = promotion.customHtml.replace(style, "");
        
        var rules = splitStyle(style, '}');
        for (var i = 0; i < rules.length; i++) {
            var selector = fetchSelector(rules[i]);
            var ruleDetail = rules[i].replace(selector, "");
            css.addRule(selector, ruleDetail);
        }
    }
    
    var str = '<div id="cse-view-images">';   
    if ($.browser.msie)
        str += promString;
    else
        str += promotion.customHtml;
    
    str += '</div>';
    return str;
}

function fetchSelector(html) {
    var reg = /[^{]*/;
    var match = html.match(reg);
    if (match && match[0]) {
        var result = match[0];
       return result;
    }
    else
        return "";
}

function fetchStyle(html) {
    var reg = /<style>.*<\/style>/;
    var match = html.match(reg);
    if (match && match[0]) {
        var result = match[0];
        result = result.replace("<style>", "");
        result = result.replace("</style>", "");
        return result;
    }
    else
        return "";
}

function splitStyle(styleString, seperators) {
    var results = [];
    var pointer = 0;
    var count = 0;
    while (pointer < styleString.length) {
        var pos = styleString.indexOf(seperators, pointer);
        if (pos > 0) {
            results[count] = styleString.substr(pointer, pos - pointer + seperators.length);
            count++;
            pointer = pos + seperators.length;
        }
        else {
            break;
        }
    }
    return results;
}



/**
* Returns the html for a single promotion.
* @param {PromotionObject} promotion Promotion to generate data for.
* @return {String} The html for this promotion.
*/
function getHTMLPromotion(promotion) {
    switch (promotion.type) {
        case 'standard':
            return getHTMLStandardPromotion(promotion);
        case 'product':
            return getHTMLProductPromotion(promotion);
        case 'custom':
            return getHTMLCustomPromotion(promotion);
        default:
            return '';
    }
}

/**
* Returns the HTML for an array of promotions.
* @param {PromotionObject[]} promotions Promotions to generate HTML for.
* @return {String} The HTML for these promotions.
*/
function getHTMLPromotions(promotions) {
    var html = [];
    if (promotions) {
        for (var i = 0, len = promotions.length; i < len; ++i) {
            html[i] = getHTMLPromotion(promotions[i]);
        }
    }
    return html.join('');
}

/**
* Returns the html for a single redirect.
* @param {RedirectObject} redirect The redirect to generate HTML for.
* @return {String} The html for this redirect.
*/
function getHTMLRedirect(redirect) {
    var str = '<div class="cse-commerce-redirect">';
    str += 'Redirect triggered for ';
    str += '<a href="' + redirect + '\">' + redirect +
      '</a>';
    str += '</div>';
    return str;
}

/**
* Returns the HTML for an array of redirects.
* @param {RedirectsObject[]} redirects Redirects to generate HTML for.
* @return {String} The HTML for these redirects.
*/
function getHTMLRedirects(redirects) {
    var html = [];
    if (redirects && redirects.length > 0) {
        //directly redirect,
        window.location = redirects[0];
        //for (var i = 0, len = redirects.length; i < len; ++i) {
        //    html[i] = getHTMLRedirect(redirects[i]);
        //}
    }
    return html.join('');
}

/**
* Returns the HTML for the promotions and items for either the list or grid
* view.
* @param {ItemObject[]} items The items to display.
* @param {PromotionObject[]} promotions The promotions to display.
* @param {RedirectObject[]} redirects The redirects to display.
* @param {String} view 'grid' or 'list'.
* @return {String} The HTML to render.
*/
function getHTMLSearchResults(items, promotions, redirects, view) {
    var s = getHTMLRedirects(redirects);
    //s += getHTMLPromotions(promotions);  // do it at server side
    s += '<div id=\"catfil_gridview\" style="margin-bottom:10px">';
    s += getHTMLItems(items, view, promotions);
    return s;
}

/**
* Callback when an image is loaded to scale it to fit.
* @param {ImageObject} img The freshly loaded image.
*/
function imgOnLoad(img) {
    var w = img.width;
    var h = img.height;

    if (img.src.indexOf("t.jpg") > 0) {
        img.height = 80;
        img.width = 125;
    }
    else if (w > h) {
        img.width = IMAGE_SIZE;
        img.height = IMAGE_SIZE * h / w;
    } else {
        img.height = IMAGE_SIZE;
        img.width = IMAGE_SIZE * w / h;
    }
}


/**
* Sets the inner html in the given html element or hides the element if the
* supplied html is empty.
* @param {object} panel Html element to add html to.
* @param {String} html Html to add to the panel.
*/
function setInnerHtmlOrHide(panel, html) {
    if (html) {
        panel.innerHTML = html;
        panel.style.display = '';
    } else {
        panel.style.display = 'none';
    }
}

/**
* Returns the name to display for a given facet.
* @param {FacetObject} facet The facet from which to extract the name.
* @return {String} The name to be displayed for the facet.
*/
function getFacetDisplayName(facet) {
    return facet.displayName;
}

/**
* Returns the key for a given facet.  For attributes this simply returns the
* name, while properties have their name returned in all caps.  This is to
* prevent collisions between attributes and properties of the same name.
* @param {FacetObject} facet The facet from which to extract the key.
* @return {String} The key for the facet.
*/
function getFacetKey(facet) {
    return facet.property ? facet.property.toUpperCase() : facet.name;
}

/**
* Returns a restrict string for the given bucket and facet that can be used
* with restrictBy=.
* @param {BucketObject} bucket Bucket for the restrict.
* @param {FacetObject} facet Facet for the restrict.
* @return {String} The restrict string.
*/
function getRestrict(bucket, facet) {
    var restrict;
    if (facet.property) {
        restrict = facet.property;
    }
    else {
        restrict = escapeShoppingApiString(facet.name) + '(' + facet.type + ')';
        if (facet.unit) {
            restrict = restrict + '/' + facet.unit;
        }
    }
    restrict += '=';
    if ('value' in bucket && bucket.value) {
        return restrict + escapeShoppingApiString(bucket.value.toString());
    }
    restrict += bucket.minExclusive ? '(' : '[';
    restrict += bucket.min || '*';
    restrict += ',';
    restrict += bucket.max || '*';
    restrict += bucket.maxExclusive ? ')' : ']';
    return restrict;
}

/**
* Returns the bucket count in the facet that corresponds to the given restrict
* @param {FacetObject} facet Facet object in which to find bucket.
* @param {String} restrict Restrict string to match.
* @return {Number} The count in the matched bucket or 0 if no bucket was
*    matched.
*/
function getBucketCountForRestrict(facet, restrict) {
    for (var j = 0, bucket; bucket = facet.buckets[j]; ++j) {
        if (getRestrict(bucket, facet) == restrict) {
            return bucket.count;
        }
    }
    return 0;
}


function getBucketTitleForRestrict(facets, restrict) {
    for (var i = 0, facet; facet = facets[i]; ++i) {

        for (var j = 0, bucket; bucket = facet.buckets[j]; ++j) {
            if (getRestrict(bucket, facet) == restrict) {
                return getBucketTitle(bucket, facet);
            }
        }
    }
    return "";
}

/**
* Formats a price for display in the given currency.
* @param {Number} priceValue Value to format.
* @param {String} currency The currency code.
* @return {String} Formatted price.
*/
function formatPrice(priceValue, currency) {
    if (currency == 'AUD') {
        return '$' + priceValue.toFixed(2);
    } else if (currency == 'EUR') {
        return '\u20ac' + priceValue.toFixed(2);
    } else if (currency == 'GBP') {
        return 'Â£' + priceValue.toFixed(2);
    } else if (currency == 'JPY') {
        return 'Â¥' + priceValue.toFixed(0);
    } else if (currency == 'USD') {
        return '$' + priceValue.toFixed(2);
    } else {
        return priceValue.toFixed(2) + ' ' + currency;
    }
}

/*
* Formats the value in a bucket of a facet.
* @param {Number} value Value to format.
* @param {FacetObject} facet Facet this value is part of.
* @return {String} The formatted value
*/
function formatBucketValue(value, facet) {
    if (facet.name == 'aslowprice' && facet.type == 'float') {
        return '$' + value.toFixed(2);
    } else {
        return value.toString();
    }
}

/**
* Returns a title to display for the given bucket and facet.
* @param {BucketObject} bucket Bucket to get title for.
* @param {FacetObject} facet Facet that the bucket belongs to.
* @return {String} Title to display for the bucket.
*/
function getBucketTitle(bucket, facet) {
    if ('value' in bucket && bucket.value) {
        return bucket.value.toString();
    }
    var delta = facet.type == 'int' ? 1 : 0.01;
    if ('min' in bucket && bucket.min && 'max' in bucket && bucket.max) {
        var min = bucket.minExclusive ? bucket.min + delta : bucket.min;
        var max = bucket.maxExclusive ? bucket.max - delta : bucket.max;
        return min == max ? min.toString() :
        formatBucketValue(min, facet) + ' - ' + formatBucketValue(max, facet);
    } else if ('max' in bucket && bucket.max) {
        return 'Under ' + formatBucketValue(
        bucket.maxExclusive ? bucket.max : bucket.max + delta, facet);
    } else {
        return 'Over ' + formatBucketValue(
        bucket.minExclusive ? bucket.min : bucket.min - delta, facet);
    }
}

/**
* Returns the HTML text for the found text message.
* @param {String} query The term queried for.
* @param {Number} currentPage The current page.
* @param {Number} totalResults The total number of results.
* @return {String} A text string containing the number found.
*/
function printFoundText(query, currentPage, totalResults) {
    query = escapeHtml(query);
    if (totalResults > 0) {
        var endIndex = Math.min(currentPage * RESULTS_LIMIT, totalResults);
        var startIndex = (currentPage - 1) * RESULTS_LIMIT + 1;
        return ['Results ',
            startIndex.toString(),
            ' - ',
            endIndex.toString(),
            ' of about ',
            totalResults.toString(),
            ' for <string>',
            query,
            '</string>'].join('');
    } else {
        return '0 results for <strong>' + query + '</strong>';
    }
}

/*
* Returns the HTML text for a link to one of the pages
* @param {String} text Text of link.
* @param {Number} page Page number.
* @param {boolean} link Whether to add a link.
* @param {boolean} last Whether this is the last page.
*/
function printPageLink(text, page, link, last) {
    var html = '';
    if (link) {
        var searchKey = document.getElementById('searchText').value;
        html += '<a href="#page='+ page + '" onclick="pageSubmit(\'' + searchKey + '\', null, ' + page + ', null, true);">';
    }
    else {
        html += '<strong>';
    }
    html += text;
    html += link ? '</a>' : '</strong>';
    if (!last) {
        html += '&nbsp;|&nbsp;';
    }
    return html;
}

/**
* Returns the HTML text for the paging bar.
* @param {Number} currentPage Current page number.
* @param {Number} totalPages Total number of pages.
* @return {String} The HTML to display.
*/
function printPageBar(currentPage, totalPages) {
    var PAGES_ONSCREEN = 10;  // We display 10 page links at once.

    if (totalPages <= 0) {
        return '';
    }

    var pagesStart = currentPage - Math.floor((PAGES_ONSCREEN - 1) / 2);
    var pagesEnd = currentPage + Math.floor(PAGES_ONSCREEN / 2);
    var delta;
    if (pagesStart < 1) {
        delta = 1 - pagesStart;
        pagesStart = 1;
        pagesEnd += delta;
        if (pagesEnd > totalPages) {
            pagesEnd = totalPages;
        }
    } else if (pagesEnd > totalPages) {
        delta = pagesEnd - totalPages;
        pagesEnd = totalPages;
        pagesStart -= delta;
        if (pagesStart < 1) {
            pagesStart = 1;
        }
    }

    var str = [];
    if (currentPage > 1) {
        str.push(printPageLink('&lsaquo; Previous', currentPage - 1, true, false));
    }
    for (var i = pagesStart; i <= pagesEnd; ++i) {
        str.push(printPageLink(i, i, i != currentPage,
                           i == totalPages && currentPage == totalPages));
    }
    if (currentPage < totalPages) {
        str.push(printPageLink('Next &rsaquo;', currentPage + 1, true, true));
    }
    return str.join('');
}

function removeEmptyBucket(arr) {
    i = 0;
    while (i < arr.length) {
        if (arr[i].count == 0)
            Array.remove(arr, arr[i]);
        else
            i++;
    }
    return arr;
}


function removeEmptyFacet(arr) {
    i = 0;
    while (i < arr.length) {
        if (arr[i].buckets && arr[i].buckets.length > 0)
            i++;
        else
            Array.remove(arr, arr[i]);
    }
    return arr;
}

function gcsUtilities(resultsPanel, unfilteredFacetsPanel, filteredFacetsPanel) {
    // Global refinement vars.
    var sortOrder = 'match';
    var currentPage = 1;
    var queryString = '';
    var allItems;
    var allFacets;
    var allPromotions;
    var allRedirects;
    var viewPref = 'grid';
    var restrictsMap = {};  // Map which maps an attribute to a restrict.

    var handleShoppingApiResponse = function(response) {
        if (response.error) {
            errorHandler(response.error.message);
            return;
        }

        allItems = response.items;
        allPromotions = response.promotions;
        promotionHeight = (allPromotions && allPromotions.length > 0) ? 185 : 0;

        allRedirects = response.redirects;
        lastKey = response.query;
        var spellingSuggestion = response.suggestion;

        var totalPages = Math.ceil(response.totalItems / RESULTS_LIMIT);
        if (response.startIndex) currentPage = Math.ceil(response.startIndex / RESULTS_LIMIT);

        if (response.restrictsMap) {
            restrictsMap = response.restrictsMap;
            for (var key in restrictsMap) {
                restrictsMap[key].display = unEscapeRestrictString(restrictsMap[key].display);
                restrictsMap[key].value = unEscapeRestrictString(restrictsMap[key].value);
            }
        }
        else
            restrictsMap = {};

        // doneCallback(response, spellingSuggestion, currentPage, totalPages);
        allFacets = response.facets;

        if (allFacets) {
            // remove empty facet/bucket nodes  
            for (var i = 0; i < allFacets.length; i++) {
                if (allFacets[i].buckets) {
                    allFacets[i].buckets = removeEmptyBucket(allFacets[i].buckets);
                }
            }
            allFacets = removeEmptyFacet(allFacets);

            //handleFacets(allFacets); // no need to show facets because it has been created in server side
        }

    };

    var handleFacets = function(facets) {
        allFacets = facets;
        var filteredFacets = '';
        var unfilteredFacets = '';

        for (var i = 0, facet; facet = facets[i]; ++i) {
            var facetName = getFacetDisplayName(facet);
            var facetKey = getFacetKey(facet);

            if (restrictsMap[facetKey]) {
                filteredFacets += '<div><h4>' + facetName + '</h4><div class="cse-commerce-facet">';
                var displayTitle = escapeHtml(restrictsMap[facetKey]['display']);
                filteredFacets += '<ul><li><b title="' + displayTitle + '">' + truncateAndAddEllipses(22, displayTitle);

                var count = getBucketCountForRestrict(facet, restrictsMap[facetKey]['value']);
                if (count > 0) {
                    filteredFacets += ' (' + count + ')';
                }

                filteredFacets += '</b></li>';
                filteredFacets += '<li><a href="javascript:void(0);" ' + 'onClick="javascript:applyFilter(\''
                                + escapeJsString(facetKey) + '\', null, null, true)">View all</a></li>';
                filteredFacets += '</ul></div></div>';

            } else {
                unfilteredFacets += '<div id=attr' + i + '>';
                if (allFacets[i].buckets) unfilteredFacets += showBuckets(i, false);
                unfilteredFacets += '</div>';
            }
        }
        
        setInnerHtmlOrHide(filteredFacetsPanel, filteredFacets);
        setInnerHtmlOrHide(unfilteredFacetsPanel, unfilteredFacets);
    }


    /**
    * Shows the buckets for an unfiltered facet. If all is set to
    * true all facets are shown with a "less" option if there are more than 5
    * facets. If all is set to false only 5 facets are shown with a "more..."
    * option.
    * @param {Number} i Index of facet to show.
    * @param {boolean} all Whether to show all the buckets.
    * @return {String} The html for the buckets.
    */
    var showBuckets = function(i, all) {
        var facet = allFacets[i];
        var facetName = getFacetDisplayName(facet);
        var facetKey = getFacetKey(facet);
        var str = '<h4>' + facetName + '</h4><div class="cse-commerce-facet"><ul>';
        var maxToShow = 5;

        // explicitly included facets that have zero count
        if (!facet.buckets) {
            return;
        }
        for (var j = 0, bucket; bucket = facet.buckets[j]; j++) {
            var displayTitle = getBucketTitle(bucket, facet);

            str += '<li><a href="#' + facetKey + '=' + escapeRestrictString(displayTitle) + '" onClick="javascript:applyFilter(\''; // the anchor can't contain & or quotes

            str += escapeJsString(facetKey) + '\', \'';
            str += escapeRestrictString(getRestrict(bucket, facet)) + '\', \'';
            str += escapeRestrictString(displayTitle) + '\', true)"';

            var shortTitle = truncateAndAddEllipses(22, escapeHtml(displayTitle));
            if (shortTitle == displayTitle) {
                str += '>' + shortTitle + '</a> (';
            }
            else
                str += ' title="' + displayTitle + '">' + shortTitle + '</a> (';

            str += bucket.count + ')</li>';
            if (!all && facet.buckets.length > maxToShow && j == (maxToShow - 1)) {
                str += '<li><a href="javascript:void(0);" ' + 'onClick="javascript:showBucket(' + i + ',true)">More...</a></li>';
                break;
            }
        }
        if (all && facet.buckets.length > maxToShow) {
            str += '<li><a href="javascript:void(0);" ' + ' onClick="javascript:showBucket(' + i + ',false)">Less...</a></li>';
        }
        str += '</ul></div>';
        return str;
    }

    var showBucketsDiv = function(index, all) {
        var div = document.getElementById('attr' + index);
        if (div) {
            div.innerHTML = showBuckets(index, all);
        }
    }

    var clearResults = function() {
        return; //do not clear to avoid flashing
        
        //resultsPanel.innerHTML = '';
        //var elem = $("#cse_commerce_stats");
        //elem.css({ display: "none" });
        //elem = $("#cse-commerce-spell");
        //elem.css({ display: "none" });
        //elem = $("#cse_commerce_stats_bottom");
        //elem.css({ display: "none" });
    }

    var getMyFeed = function(query) {

        var originUrl = window.location.href;
        // first time enter search, change the url to standard search url
        if (originUrl.toLowerCase().indexOf("focusid=search.ascx") <= 0) {
            originUrl = window.location.protocol + "//" + window.location.host + "/default.aspx?FocusId=Search.ascx";
        }

        var startIndex = (currentPage - 1) * RESULTS_LIMIT + 1;
        var newUrl;
        if (startIndex == 1)
            newUrl = updateUrl(originUrl, "startIndex", "");
        else
            newUrl = updateUrl(originUrl, "startIndex", startIndex);

        newUrl = updateUrl(newUrl, "query", escapeQueryString(query));

        var restrictString = "";
        var urlRestrictString = "";
        var restrictCount = 0;
        newUrl = updateUrl(newUrl, "restrict", "");   // initially remove "restrict" param
        if (allFacets) {
            for (var i = 0, facet; facet = allFacets[i]; ++i) {
                var key = getFacetKey(facet);
                var escKey = escapeQueryString(key);
                if (key in restrictsMap) {
                    var display = restrictsMap[key]['display'];
                    var value = restrictsMap[key]['value'];
                    var escDisplay = escapeQueryString(display);
                    var escValue = escapeQueryString(value);

                    // remove $ from restrict string
                    value = value.replace(/\$/g, "");
                    escDisplay = escDisplay.replace(/\$/g, "");
                    escValue = escValue.replace(/\$/g, "");

                    if (restrictCount == 0) {
                        restrictString += escKey + "~" + display + "~" + value;
                        urlRestrictString += escKey + "=" + escDisplay;
                    }
                    else {
                        restrictString += "_`_" + key + "~" + display + "~" + value;
                        urlRestrictString += "&" + escKey + "=" + escDisplay;
                    }
                    restrictCount++;

                    // update restricts in url
                    newUrl = updateUrl(newUrl, "restrict", "y");
                    newUrl = updateUrl(newUrl, escKey, escDisplay);  // do not contain '$' in url
                }
                else
                    newUrl = updateUrl(newUrl, escKey, "");  // not in restrictsMap, remove the facet from url
            };
        }

        jQuery.ajax({
            url: "/Search.axd",
            data: { "cmd": "storerstrings", "RestrictString": restrictString }, // restrictString is not escaped
            async: false,
            dataType: "json",
            success: function(data, textStatus) {
                if (textStatus == "success") {
                    newUrl = newUrl.replace(" ", "+");
                    window.location.assign(newUrl);
                }
            }
        })

    };

    
    var updateUrl = function(url, paramKey, value) {
        var escParamKey = paramKey.replace("+", "\\+").replace("(", "\\(").replace(")", "\\)");  // escape special chars in regex
        var reg = new RegExp('[?&]' + escParamKey + '=[^&]+');
        var match = url.match(reg);
        var newUrl;
        if (match && match.length > 0) {
            var param = match[0];
            if (param.charAt(param.length - 1) == '&') str = param.substr(0, param.length - 1);
            var oldValue = param.match(/=.+$/);
            if (value != "")
                newUrl = url.replace(oldValue, "=" + value);
            else
                newUrl = url.replace(param, "");  // remove this param
        }
        else {
            if (value != "") {
                if (url.match(/\?/))
                    newUrl = url + "&" + paramKey + "=" + value;
                else
                    newUrl = url + "?" + paramKey + "=" + value;
            }
            else
                newUrl = url;
        }
        return newUrl;
    }
    
    // Called when we submit a new search term.
    var formSubmit = function(query, order) {
        currentPage = 1;

        if (order) {
            sortOrder = order;
        } else {
            sortOrder = 'match';
            restrictsMap = {};
        }

        clearResults();        
        getMyFeed(query);
    };

    // Called when we submit a new spelling correction.
    var spellSubmit = function(query) {
        currentPage = 1;
        clearResults();
        getMyFeed(query);
    }

    // Called when we navigate to the given page.
    var pageSubmit = function(searchKey, facetFilter, page, hisPosition, byClick) {  //byClick =true : users click a page number, false means called by history

        currentPage = page;

        clearResults();
        getMyFeed(google_search_textbox.value);
    }


    // Called when a filter is applied.
    // applyFilter is still needed because it will be called when "More..." or "Less..." links are clicked
    var applyFilter = function(query, key, value, display, byClick) {

        currentPage = 1;
        if (value) {
            restrictsMap[key] = { 'value': value, 'display': display };
        } else {
            delete restrictsMap[key];
        }
        clearResults();
        getMyFeed(query);
    }

    return {
        'formSubmit': formSubmit,
        'spellSubmit': spellSubmit,
        'pageSubmit': pageSubmit,
        'applyFilter': applyFilter,
        'showBucketsDiv': showBucketsDiv,
        "handleShoppingApiResponse": handleShoppingApiResponse
    };

}




// get the css object from the page header
function getCssObject() {
    var css = null;
    try {
        css = document.styleSheets[0];
        if (!css) {
            var head = document.getElementsByTagName("head").item(0);
            head.appendChild(document.createElement("style"));
            css = document.styleSheets[0];
        }
    } catch (ex) {
        css = document.createStyleSheet("styles.css");
    }
    return css;
}

function init_googleSearch() {
    document.getElementById('searchButton').disabled = false;
    google_search_textbox = document.getElementById('searchText');
    if (google_search_textbox.style.visibility == "visible")
        google_search_textbox.focus();

    gcs = gcsUtilities(
        document.getElementById('resultsPanel'),
        document.getElementById('cse_commerce_unfiltered_attributes'),
        document.getElementById('cse_commerce_filtered_attributes'));

    // trigger the search once users click on a suggested word
    window.setInterval(
        function() {
            var autoCompleteTable = $(".gsc-completion-container");
            if (autoCompleteTable.length > 0) {
                if ($.browser.msie) {
                    var rows = autoCompleteTable[0].rows;
                    for (var i = 0; i < rows.length; i++) {
                        var td = rows[i].cells[0];

                        $(td).unbind("click");
                        $(td).click(function() {
                            formSubmit();
                        });
                    }
                }
                else {
                    gcs_suggestionFlag = true; // tell non-IE browsers that search suggestion table is open
                }
            }
            else
                gcs_suggestionFlag = false; // tell non-IE browsers that search suggestion table is closed

        },
        1000);


    if (!$.browser.msie) {  // for non-IE browsers, form will be submit before td.click event occurs
        var netForm = document.getElementsByTagName("form");
        if (netForm && netForm.length > 0) {
            originFormSubmit = netForm[0].submit;
            netForm[0].submit = function() {
                if (gcs_suggestionFlag)
                    formSubmit();   // google search 
                else
                    originFormSubmit.call(this);  // normal submit
            }
        }
    }

    if (typeof gcsResponse == "undefined") return;

    if (gcsUtilities && gcs.handleShoppingApiResponse) {
        gcs.handleShoppingApiResponse(gcsResponse);
    }
}


function setClassName(elem, className) {
    elem.className = className;
    elem.setAttribute('class', className);
};

function getElementsByClassName(className, tagName) {
    if (document.getElementsByClassName) {
        return document.getElementsByClassName(className);
    } else {
        var elems = document.getElementsByTagName(tagName);
        var filteredElems = [];
        for (var i = 0, elem; elem = elems[i++]; ) {
            if (elem.className == className) {
                filteredElems[filteredElems.length] = elem;
            }
        }
        return filteredElems;
    }
};
function selectElement(id, className) {
    var elems = getElementsByClassName(className, 'li');
    for (var i = 0; i < elems.length; ++i) {
        setClassName(elems[i], '');
    }
    if (id) {
        var elem = document.getElementById(id);
        if (elem) {
            setClassName(elem, className);
        }
    }
};
function clearFilters() {
    return;   // do not clear to avoid flash    
    //selectElement('', 'cse-commerce-sort-selected');
    //selectElement('', 'cse-commerce-facet-selected');
};

function spellSubmit(suggest) {
    if (gcs && gcs.spellSubmit) {
        google_search_textbox.value = suggest;
        gcs.spellSubmit(suggest);
    }
};
function pageSubmit(searchKey, filters, page, hisPosition, byClick) {
    if (gcs && gcs.pageSubmit) {
        gcs.pageSubmit(searchKey, filters, page, hisPosition, byClick);
    }
};
function changeView(view) {
    if (gcs && gcs.changeView) {
        gcs.changeView(view, document.getElementById('resultsPanel'));
    }
};
function applyFilter(key, value, display, byClick) {
    if (gcs && gcs.applyFilter) {
        gcs.applyFilter(google_search_textbox.value, key, value, display, byClick);
    }
};
function showBucket(index, all) {
    if (gcs && gcs.showBucketsDiv) {
        gcs.showBucketsDiv(index, all);
    }
};

function formSubmit(order, id) {
    if (jQuery != undefined) {
        if (jQuery.getJSON != undefined) {

            if (!gcs || !google_search_textbox)
                init_googleSearch();  // call init_googleSearch again if not initialized

            if (gcs && google_search_textbox) {
                var key = google_search_textbox.value;
                key = key.replace("'", ""); // remove quote to prevent errors Searchhandler when generating SQL script
                key = $.trim(key);

                if (key == "" || key == "Enter Keyword or Item #") {
                    google_search_textbox.value = "";
                    var input = window.jQuery("#searchText");
                    input.focus();
                    return;
                }

                jQuery.ajax({
                    url: "/Search.axd",
                    data: { "cmd": "checkSearchKey", "searchkey": key },
                    async: false,
                    dataType: "json",
                    success: function(data, textStatus) {
                        if (textStatus == "success") {
                            var rtnString = data.content;
                            if (rtnString == "coupon") {
                                window.location.assign("/Default.aspx?FocusId=SearchbyCode.ascx&Code=" + key);
                            }
                            else if (rtnString == "itemno") {
                                window.location.assign("/Default.aspx?FocusId=Search.ascx&keyword=" + key);
                            }
                            else {
                                // submit to get feed from google
                                if (!id) {
                                    id = 's1';
                                }
                                selectElement(id, 'cse-commerce-sort-selected');
                                gcs.formSubmit(key, order);
                            }
                        }
                    }
                });
            }
        }
    }
}

