/*
 * (c) neofonie Technologieentwicklung und Informationsmanagement GmbH
 *
 * This computer program is the sole property of neofonie GmbH
 * (http://www.neofonie.de) and is protected under the German Copyright Act
 * (paragraph 69a UrhG). All rights are reserved. Making copies,
 * duplicating, modifying, using or distributing this computer program
 * in any form, without prior written consent of neofonie, is
 * prohibited. Violation of copyright is punishable under the
 * German Copyright Act (paragraph 106 UrhG). Removing this copyright
 * statement is also a violation.
 */

/**
 * Library for recipe search.
 *
 * @author tilman.linden@neofonie.de
 */

/**
 * Resets the drilldowns
 *
 * @param form The form.
 */
function resetDrilldowns(form) {
    if (form) {
        var mustsubmit = false;
        // reset sliders
        $(".ui-slider", form).each(function() {
            var value = $(this).slider("value");            
            var minValue = ($(this).find(".excludedElement[name=sliderMin]")[0]).value;
            if (value != minValue) {
                $(this).slider("moveTo", minValue);
                mustsubmit = true;
            }
        });
        // reset checkboxes
        $(":checkbox", form).filter(":not(.excludedElement)").each(function() {
            if (this.checked == true) {
                this.checked = false;
                mustsubmit = true;
            }
        }).end().filter(".excludedElement").each(function() {
            if (this.checked == false) {
                this.checked = true;
                mustsubmit = true;
            }
        });
        if (mustsubmit) {
            return autosubmit(form, true);
        } else {
            return true;
        }
    } else {
        return false;
    }
} 

/**
 * Initializes all sliders in the form with the given id.
 * 
 * @param formId The form id.
 */
function initSliders(formId) {
    $("#" + formId + " .ui-slider").each(function() {
        var valueElement = $(this).find(".sliderValue")[0];
        var value = valueElement.value;
        var min = $(this).find(".excludedElement[name=sliderMin]")[0].value;
        var max = $(this).find(".excludedElement[name=sliderMax]")[0].value;
        var stepping = $(this).find(".excludedElement[name=sliderStepping]")[0].value;
        var jWrapperElement = $(this).parent();
        var ecElement = $(this).find(".expandCollapseElement")[0];
        if (ecElement.value == "true") {
            $(this).slider({
                slide: function(e, ui) {
                    ui.options["jWrapperElement"].css("background-position", ((ui.value * 277 / (ui.options["jMax"] - ui.options["jMin"])) - 271) + "px 2px");
                },
                change: function(e, ui) {
                    ui.options["valueElement"].value = ui.value;
                    pageTracker._trackPageview(location.pathname + location.search + '#/suche/rezeptsuche/verfeinern');
                    autosubmit(ui.options["valueElement"].form);
                },
                axis: "horizontal",
                handle: ".ui-slider-handle",
                max: max,
                min: min,
                startValue: value,
                stepping: stepping,
                valueElement: valueElement,
                jWrapperElement: jWrapperElement,
                jMin : min,
                jMax : max
            });
        }
    });
}

/**
 * Resets all sliders to their initial value.
 * 
 * @param form The form that contains the sliders.
 */
function resetSliders(form) {
    $(".ui-slider", form).each(function() {
        var initialValue = ($(this).find(".excludedElement[name=sliderInitial]")[0]).value;
        $(this).slider("moveTo", initialValue);
    });
}

/**
* Initialized the more/less behaviour of drilldowns.
*
* @param formId The id of the form containing the drilldowns.
* @param moreString The title of the "more" link.
* @param lessString The title of the "less" link.
*/
function initMoreLess(formId, moreString, lessString) {
    $("#" + formId).find("a.moreless").css("outline", "none").each(function(i,a) {
        a.jLessLIs = $(this).siblings('table').find('li').filter(':not(.moreless)');
        a.jRelatedLIs = $(this).siblings('table').find('li.moreless');
        a.valueElem = $(this).siblings('.moreLessElement')[0];
        a.jFilter = $(this).siblings('.filterElement');
 
        a.relatedVisible = (a.valueElem.value != "false");
        
        $(a).bind('click', function() {
        	pageTracker._trackPageview(location.pathname + location.search + '#/suche/rezeptsuche/verfeinern');
            var mustSubmit = false;
            if (this.relatedVisible = !this.relatedVisible) {
                // show more
                this.jRelatedLIs.fadeIn(200);
                this.innerHTML = lessString;
                this.valueElem.value = "true";
                this.className = this.className.replace('rightArrow','leftArrow');

                // check if the "more" operation has an impact on the search result.
                // if so submit
                // NOTE: This is for Drilldowns with invertAllLogic == true

                var checked = this.jRelatedLIs.find(":checkbox").filter(":checked").filter(":not(.excludedElement)");
                if (checked.length > 0) {
                    mustSubmit = true;
                }
            } else {
                // show less
                this.jRelatedLIs.fadeOut(200);
                this.innerHTML = moreString;
                this.valueElem.value = "false";
                this.className = this.className.replace('leftArrow','rightArrow');

                // check if the "less" operation has an impact on the search result.
                // if so submit
                // NOTE: This is for Drilldowns with invertAllLogic == true
                
                var checked = this.jRelatedLIs.find(":checkbox").filter(":checked").filter(":not(.excludedElement)");
                if (checked.length > 0) {
                    mustSubmit = true;
                }
            }

            if (mustSubmit) {
                this.jFilter.remove();
                autosubmit(this.valueElem.form, true);
            }
            
            return false;
        });
    });
}

/**
* Initalizes the expand/collapse behaviour of drilldowns and sliders.
*
* @param formId The id of the form containing the drilldowns / sliders.
*/
function initExpandCollapse(formId) {
    $("#" + formId + " h5").each(function(i,h5) {
	var jH = $(h5),
	    jNext = $(h5).next('div'),
            jValue = $(h5).next('div').find(':hidden.expandCollapseElement'),
            jFilter = $(h5).next('div').find(':hidden.filterElement');

	h5.refElem = jNext[0];
        h5.valueElem = jValue[0];
        h5.jFilterElem = jFilter;
        
        // Bind click function
	jH.bind('click', function() {
		pageTracker._trackPageview(location.pathname + location.search + '#/suche/rezeptsuche/verfeinern');
	    var me = this;
	    $(this.refElem).slideToggle('fast', function() {
		$(me).toggleClass('toggleArrowClosed');
                me.valueElem.value = me.valueElem.value == "true" ? "false" : "true";
                // check if the expand/collapse operation has an impact on the search-result
                // if so, submit the form
                if ($(me.refElem).children('div').hasClass("ui-slider")) {
                    // slider
                    var sliderVal = parseInt($(me.refElem).find(":hidden.sliderValue")[0].value);
                    var sliderMax = parseInt($(me.refElem).find(":hidden[name=sliderMax]")[0].value);
                    var sliderMin = parseInt($(me.refElem).find(":hidden[name=sliderMin]")[0].value);
                    if ((sliderVal > sliderMin) && (sliderVal < sliderMax)) {
                        autosubmit(me.valueElem.form, true);
                    }
                } else {
                    // drilldown
                    // NOTE: This is for drilldowns with invertAllLogic == true
                    me.jFilterElem.remove();
                    var checked = $(me.refElem).find(":checkbox").filter(":checked").filter(":not(.excludedElement)").filter(":visible");
                    if (checked.length > 0) {
                        autosubmit(me.valueElem.form, true);
                    }                    
                }
	    });
	    return false;
	});
    });
}

/** 
 * Submit a form via GET by building the query string via queryString(form).
 *
 * @param form The form.
 */
function customSubmit(form) {
    if (form) {
        var uri = form.action + "?" + queryStringNew(form);
        location.href = uri;
        return true;
    } else {
        return false;
    }
}

// --------------------------------------------------------------------------------
// Sorting
//

/**
 * Changes the sorting and updates the hitlist.
 * 
 * @param formId The id of the form.
 * @param select The <select ...> element for selection of sorting.
 */
function sort(formId, select) {
    var form = document.forms[formId];
    if (form && select && select.options) {
        for (var i = 0; i < select.options.length; i++) {
            if (select.options[i].selected == true) {
                $("#" + formId).find(".sortingElement").each(function() {
                    this.value = select.options[i].value;
                });
            }
        }
        autosubmit(form, true);
    }
    return true;
}

// --------------------------------------------------------------------------------
// Faceted search
//

/**
 * Submits drilldown form via ajax and updates divs.
 *
 * @param drilldowns The form of the drilldowns
 */
function rssd(drilldowns) {
    if (drilldowns) {
    	qStr = queryStringNew(drilldowns);
    	//the dummy-parameter below is a IE-hack to enforce getting a new response object
    	//which the IE with its stupid caching-feature won't otherwise do.
        var uri = drilldowns.action + "?" + qStr + "&dummy=" + new Date().getTime();
        createCookie('rsoq',encodeURIComponent(qStr),365);
        window.open('#' + qStr, '_self');
        $.get(uri, function(data) {
            var responses = data.split("(:------------------------------------------------------- SNIP -:)");
            var hitlist = responses[0];
            var drilldowns = responses[1];
            var jHits = $("#hitlist");
            //alert(jHits.html());
            var jDrill = $("#drilldowns");
            //alert(jDrill.html());
            jHits.html(hitlist);
            jDrill.html(drilldowns);
            window.blocksubmitOn = false;
            // initialize sliders
            //initSliders('recipeSearchDrilldowns');
            // initialize more/less
            //initMoreLess('recipeSearchDrilldowns', 'mehr', 'weniger');
            // add toggle open/close functionality.. 
            //initExpandCollapse('recipeSearchDrilldowns');
        }, "text");
        return true; 
    } else {
        return false;
    }
}

function rssd4hash(hash){
	$(".clickBlocker").each(function() {
        var w = $(this).next("div").outerWidth() + "px";
        var h = $(this).next("div").outerHeight() + "px";
        $(this).css({ width: w, height: h });
    }).fadeIn(1, function() {
        if (!window.blocksubmitOn) {
            window.blocksubmitOn = true;
        }
    });
	var uri = $("#recipeSearchDrilldowns").attr("action") + "?" + hash;
	$.get(uri, function(data) {
        var responses = data.split("(:------------------------------------------------------- SNIP -:)");
        var hitlist = responses[0];
        var drilldowns = responses[1];
        var jHits = $("#hitlist");
        var jDrill = $("#drilldowns");
        jHits.html(hitlist);
        jDrill.html(drilldowns);
        window.blocksubmitOn = false;
    }, "text");
    return true; 
}

// --------------------------------------------------------------------------------
// Util
//


/**
 * Pushes value to array with name arrayName which is
 * property of map if value != null.
 */
function push(value, arrayName, map) {
    if (value != null) {
        var array = map[arrayName];
        if (!array) {
            array = new Array();
            map[arrayName] = array;
        }
        array.push(value);
    }
}

/**
 * Build query string for a form with special handling
 * for checkbox groups and hidden elements with equal name.
 *
 * @param The form.
 * @return The query string.
 */
function queryString(form) {
    var parts = new Object();
    $(":input", form).filter(":not(.excludedElement, :submit, :reset, #resetAllDrilldowns)").filter(":checkbox").filter(".numericFieldValue").each(function() {
        if (this.checked) {
            push(this.value + "y", this.name, parts);
        } else {
        	if(form.name == "recipeSearchDrilldowns"){
        		push(this.value + "n", this.name, parts);
        	}
        }
    }).end().filter(":not(.numericFieldValue)").each(function() {
        if (this.checked) {
            push("true", this.name, parts);
        } else {
            push("false", this.name, parts);
        }
    }).end().end().filter(":radio").each(function() {
        if (this.checked) {
            push(this.value, this.name, parts);
        }
    }).end().filter(":not(:radio, :checkbox)").each(function() {
    	if(form.name == "recipeSearchDrilldowns"){
    		push(this.value, this.name, parts);
    	}
    }).end().filter("#recipeSearchQueryString").each(function(){
    	push(this.value, this.name, parts);
    });
    var queryParts = new Array();
    for (var key in parts) {
        var vals = parts[key];
        var valString = encodeURIComponent(vals.join("_"));
        queryParts.push(key + "=" + valString);
    }
    var queryString = queryParts.join("&");
    return queryString;
}

/**
 * Build query string for a form with special handling
 * for checkbox groups and hidden elements with equal name.
 * Attention: new method (see HBVB-585)
 *
 * @param The form.
 * @return The query string.
 */
function queryStringNew(form) {
    var parts = new Object();
    $(":input", form).filter(":not(.excludedElement, :submit, :reset, #resetAllDrilldowns)").filter(":checkbox").filter(".numericFieldValue").each(function() {
        if (this.checked) {
            push(this.value + "y", this.name, parts);
        } else {
        	if(form.name == "recipeSearchDrilldowns"){
        		push(this.value + "n", this.name, parts);
        	}
        }
    }).end().filter(":not(.numericFieldValue)").each(function() {
        if (this.checked) {
            push("y", this.name, parts);
        } else {
            push("n", this.name, parts);
        }
    }).end().end().filter(":radio").each(function() {
        if (this.checked) {
            push(this.value, this.name, parts);
        }
    }).end().filter(":not(:radio, :checkbox)").each(function() {
    	if(form.name == "recipeSearchDrilldowns"){
    		push(this.value, this.name, parts);
    	}
    }).end().filter("#recipeSearchQueryString").each(function(){
    	push(this.value, this.name, parts);
    });
    var queryParts = new Array();
    for (var key in parts) {
        var vals = parts[key];
        var valString = encodeURIComponent(vals.join("_"));
        
        if (valString.indexOf("n_") > 0 || valString.indexOf("y_") > 0) {
        	valString = encodeSearchParams(valString);
        }
        queryParts.push(key + "=" + valString);
    }
    var queryString = queryParts.join("&");
    return queryString;
}

function encodeSearchParams(searchParams) {
	var digits = new Array ( '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
	        'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
	        'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
	        'U', 'V', 'W', 'X', 'Y', 'Z' );
	
	var result = "";
	var dc = digits.length;
	tokens = searchParams.split('_');
	
	for (var i = 0; i < tokens.length; i++) {
		var id = tokens[i].substring(0, tokens[i].length - 1);
		var yesno = tokens[i].charAt(tokens[i].length -1);
		var encodedId = "";
		while (id > 0) {
			var digit = id % dc;
			id = Math.floor(id / dc);
			encodedId = digits[digit] + encodedId;
		}
		if (yesno == 'y') {
			result += '_' + encodedId;
		} else {
			result += '-' + encodedId;
		}
	}
	
	return result;
	
}

/**
 * Checks if a form should be submitted
 * automatically on each change of an element
 * and does the submit with according delay.
 *
 * @param form The form.
 * @param now If the form should be submitted immediately.
 */
function autosubmit(form, now) {
    if (form) {
        $(":hidden[name=autoSubmit]", form).each(function() {
            if (form.submitTimeout && form.submitTimeout != null) {
                window.clearTimeout(form.submitTimeout);
                form.submitTimeout = null;
            }
            var delay = this.value;
            if (now || delay == 0) {
                blocksubmit(form.id);
            } else {
                form.submitTimeout = window.setTimeout("blocksubmit('" + form.id + "')", delay);
            }
            
        });
        return true;
    } else {
        return false;
    }
}

/**
 * Fades in the blockers and submits the form.
 *
 * @param formId The id of the form.
 */
function blocksubmit(formId) {
    $(".clickBlocker").each(function() {
        var w = $(this).next("div").outerWidth() + "px";
        var h = $(this).next("div").outerHeight() + "px";
        $(this).css({ width: w, height: h });
    }).fadeIn(200, function() {
        if (!window.blocksubmitOn) {
            window.blocksubmitOn = true;
            submit(formId);
        }
    });
}

function plainSubmit(form) {
    if (form.onsubmit()) {
        form.submit();
    }
}

/**
 * Supports switching between simple and extended recipe search.
 *
 * @param formId The id of the form to submit.
 * @param url The URL to submit to.
 */
function submit(formId, url) {
    $("form[id=" + formId + "]").each(function() {
        if (this.submitTimeout && this.submitTimeout != null) {
            window.clearTimeout(this.submitTimeout);
            this.submitTimeout = null;
        }
        if (url) {
            this.action = url;
        }
        if (this.onsubmit()) {
            this.submit();
        }
    });
}

/**
 * Behaviour of a "select all" checkbox in a drilldown checkbox group.
 *
 * @param checkbox The checkbox.
 * @param invertAllLogic If the "all" logic of the drilldown is inverted.
 */
function allx(checkbox, invertAllLogic) {
    if (checkbox && checkbox.form) {
    	pageTracker._trackPageview(location.pathname + location.search + '#/suche/rezeptsuche/verfeinern');
        if (!checkbox.checked) {
            checkbox.checked = true;
            return false;
        } else {
            var identifier = checkbox.name.substring(0, checkbox.name.lastIndexOf(".all"));
            var otherOption = identifier + ".o";
            var option = identifier + ".c";
            var filter = identifier + ".f";
            $(":checkbox[name=" + otherOption + "], :checkbox[name=" + option + "]", checkbox.form).each(function() {
                this.checked = !invertAllLogic;
            });
            $(":hidden[name=" + filter + "]", checkbox.form).remove();
            autosubmit(checkbox.form);
            return true;
        }
    } else {
        return false;
    }
}

/**
 * Behaviour of a option checkbox in a drilldown checkbox group.
 *
 * @param checkbox The checkbox.
 * @param invertAllLogic If the "all" logic of the drilldown is inverted.
 */
function option(checkbox, invertAllLogic) {
    if (checkbox && checkbox.form) {
    	pageTracker._trackPageview(location.pathname + location.search + '#/suche/rezeptsuche/verfeinern');
        return optionOrOther(checkbox, checkbox.name.substring(0, checkbox.name.lastIndexOf(".c")), invertAllLogic);
    } else {
        return false;
    }
}

/**
 * Behaviour of a "other" checkbox in a drilldown checkbox group.
 *
 * @param checkbox The checkbox.
 * @param invertAllLogic If the "all" logic of the drilldown is inverted.
 */
function other(checkbox, invertAllLogic) {
    if (checkbox && checkbox.form) {
        return optionOrOther(checkbox, checkbox.name.substring(0, checkbox.name.lastIndexOf(".o")), invertAllLogic);
    } else {
        return false;
    }
}

/**
 * Behaviour of a "other" or option checkbox in a drilldown checkbox group.
 *
 * @param checkbox The checkbox.
 * @param identifier The identifier of the drilldown.
 * @param invertAllLogic If the "all" logic of the drilldown is inverted.
 */
function optionOrOther(checkbox, identifier, invertAllLogic) {
    if (checkbox && checkbox.form) {
        var allOption = identifier + ".all";
        var otherOption = identifier + ".o";
        var option = identifier + ".c";
        var filter = identifier + ".f";
        var group = $(":checkbox[name=" + option + "], :checkbox[name=" + otherOption + "]", checkbox.form);
        var allCheckbox = $(":checkbox[name=" + allOption + "]", checkbox.form);
        var checkedCount = group.filter(":checked").length;
        var changed = true;
        if ((checkedCount == 0 && !invertAllLogic) || (allCheckbox.length == 0)) {
            checkbox.checked = true;
            checkedCount = 1;
            changed = false;
        } 
        allCheckbox.each(function() {
            this.checked = (!invertAllLogic && (group.length == checkedCount)) || (invertAllLogic && (checkedCount == 0));
        });
        $(":hidden[name=" + filter + "]", checkbox.form).remove();
        if (changed) {
            autosubmit(checkbox.form);
        }
        return true;
    } else {
        return false;
    }
}

/**
 * Get the current inner dimensions of the window.
 *
 * @return A dimensions object with properties width and height.
 */
function windowSize() {
    var dim = {width: 0, height: 0};
    if( typeof( window.innerWidth ) == 'number' ) {
        //Non-IE
        dim.width = window.innerWidth;
        dim.height = window.innerHeight;
    } else if( document.documentElement && ( document.documentElement.clientWidth || document.documentElement.clientHeight ) ) {
        //IE 6+ in 'standards compliant mode'
        dim.width = document.documentElement.clientWidth;
        dim.height = document.documentElement.clientHeight;
    } else if( document.body && ( document.body.clientWidth || document.body.clientHeight ) ) {
        //IE 4 compatible
        dim.width = document.body.clientWidth;
        dim.height = document.body.clientHeight;
    }
    return dim;
}

// no ivw call, because page refrehes
hbv.trackrefresh = function(id) {
    if (!id) return;

    // WEBTREKK
    if (typeof(wt_sendinfo) != "undefined") {
        var wt_be_basic = wt_be;
        wt_be += id;
        wt_sendinfo();
        wt_be = wt_be_basic;
    }
}


$('form#recipeSearchDrilldowns input').bind('mousedown', function() {
hbv.trackrefresh('.suche_verfeinern_checkbox');
});
$('form#recipeSearchDrilldowns div.ui-slider-handle').bind('mousedown', function() {
hbv.trackrefresh('.suche_verfeinern_slider');
}); 
