function sha1_hash(msg)
{
    var K = [0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xca62c1d6];
 
    msg += String.fromCharCode(0x80);


    var l = msg.length/4 + 2;
    var N = Math.ceil(l/16);
    var M = new Array(N);
    for (var i=0; i<N; i++) {
        M[i] = new Array(16);
        for (var j=0; j<16; j++) {
            M[i][j] = (msg.charCodeAt(i*64+j*4)<<24) | (msg.charCodeAt(i*64+j*4+1)<<16) | 
                      (msg.charCodeAt(i*64+j*4+2)<<8) | (msg.charCodeAt(i*64+j*4+3));
        }
    }
    M[N-1][14] = ((msg.length-1)*8) / Math.pow(2, 32); M[N-1][14] = Math.floor(M[N-1][14])
    M[N-1][15] = ((msg.length-1)*8) & 0xffffffff;

    var H0 = 0x67452301;
    var H1 = 0xefcdab89;
    var H2 = 0x98badcfe;
    var H3 = 0x10325476;
    var H4 = 0xc3d2e1f0;

    var W = new Array(80); var a, b, c, d, e;
    for (var i=0; i<N; i++) {

        for (var t=0;  t<16; t++) W[t] = M[i][t];
        for (var t=16; t<80; t++) W[t] = ROTL(W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16], 1);

        a = H0; b = H1; c = H2; d = H3; e = H4;

        for (var t=0; t<80; t++) {
            var s = Math.floor(t/20); 
            var T = (ROTL(a,5) + f(s,b,c,d) + e + K[s] + W[t]) & 0xffffffff;
            e = d;
            d = c;
            c = ROTL(b, 30);
            b = a;
            a = T;
        }

        H0 = (H0+a) & 0xffffffff;
        H1 = (H1+b) & 0xffffffff; 
        H2 = (H2+c) & 0xffffffff; 
        H3 = (H3+d) & 0xffffffff; 
        H4 = (H4+e) & 0xffffffff;
    }

    return H0.toHexStr() + H1.toHexStr() + H2.toHexStr() + H3.toHexStr() + H4.toHexStr();
}

function f(s, x, y, z) 
{
    switch (s) {
    case 0: return (x & y) ^ (~x & z);
    case 1: return x ^ y ^ z;
    case 2: return (x & y) ^ (x & z) ^ (y & z);
    case 3: return x ^ y ^ z;
    }
}


function ROTL(x, n)
{
    return (x<<n) | (x>>>(32-n));
}

Number.prototype.toHexStr = function()
{
    var s="", v;
    for (var i=7; i>=0; i--) { v = (this>>>(i*4)) & 0xf; s += v.toString(16); }
    return s;
}

keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";

function base64_encode(input) {
    var output = "";
    var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
    var i = 0;

    input = utf8_encode(input);

    while (i < input.length) {

        chr1 = input.charCodeAt(i++);
        chr2 = input.charCodeAt(i++);
        chr3 = input.charCodeAt(i++);

        enc1 = chr1 >> 2;
        enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
        enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
        enc4 = chr3 & 63;

        if (isNaN(chr2)) {
            enc3 = enc4 = 64;
        } else if (isNaN(chr3)) {
            enc4 = 64;
        }

        output = output +
        keyStr.charAt(enc1) + keyStr.charAt(enc2) +
        keyStr.charAt(enc3) + keyStr.charAt(enc4);

    }

    return output;
}

function utf8_encode(string) {
    string = string.replace(/\r\n/g,"\n");
    var utftext = "";

    for (var n = 0; n < string.length; n++) {

        var c = string.charCodeAt(n);

        if (c < 128) {
            utftext += String.fromCharCode(c);
        }
        else if((c > 127) && (c < 2048)) {
            utftext += String.fromCharCode((c >> 6) | 192);
            utftext += String.fromCharCode((c & 63) | 128);
        }
        else {
            utftext += String.fromCharCode((c >> 12) | 224);
            utftext += String.fromCharCode(((c >> 6) & 63) | 128);
            utftext += String.fromCharCode((c & 63) | 128);
        }

    }

    return utftext;
}


search_cache = [];
jsoncall = false;

function ddo_highlight(findme, subject)
{
	replacewith = '<span class="highlight">#highlight#</span>';
	rest = subject;
	result = '';

	while (rest.toLowerCase().indexOf(findme.toLowerCase()) >= 0) {
		pos = rest.toLowerCase().indexOf(findme.toLowerCase());

		result+= rest.substr(0,pos);
		rest = rest.substr(pos, rest.length-pos);

		result+= replacewith.replace('#highlight#', rest.substr(0, findme.length));
		rest = rest.substr(findme.length, rest.length-findme.length);
	}

	result+= rest;

	return result;
}

function do_highlight(findme, subject)
{
	words = findme.split(' ');
	for (id in words) {
		rest = subject;
		result = '';
		findme = words[id];

		if ($.trim(findme)>'') {
			while (typeof(rest)=='string' && rest.toLowerCase().indexOf(findme.toLowerCase()) >= 0) {
				pos = rest.toLowerCase().indexOf(findme.toLowerCase());
		
				result+= rest.substr(0,pos);
				rest = rest.substr(pos, rest.length-pos);
		
				result+= '[|'+rest.substr(0, findme.length)+'|]';	
				rest = rest.substr(findme.length, rest.length-findme.length);
			}
		}
	
		if (rest)
			result+= rest;
			
		subject = result;
	}

	result = result.split('[|').join('<span class="highlight">').split('|]').join('</span>');
	return result;
}

function process_searchover(item) {
	$('div#searchsuggest ul li').removeClass('active');
	$(item).addClass('active');
	$('form#search input[name=search]').val($(item).find('a').text());
	
	if ($(item).parents('ul.product').length>0) {
		if ($('form#search input[name=nocache]').length==0)
			$('form#search').append($('<input>').attr('type', 'hidden').attr('name', 'nocache').val('on'));
	}
	else {
		if ($('form#search input[name=nocache]').length==1)
			$('form#search input[name=nocache]').remove();
	}
}

function dosuggest(onlycache) {
	if (typeof(onlycache)=='undefined')
		onlycache=false;
		
	if ($('form#search input[name=nocache]').length==1)
		$('form#search input[name=nocache]').remove();
		
	$('form#search input[name=search]').data('search', $('form#search input[name=search]').val());
	if ($('form#search input[name=search]').val().length>=2) {
		if ($('div#searchsuggest').length==0)
			$('body').append($('<div>').attr('id', 'searchsuggest'));
			
		if ($('div#searchsuggest:visible').length==0) {
			posi = $('form#search input[name=search]').offset();
			$('div#searchsuggest').css({'left': posi.left, 'top': posi.top+$('form#search input[name=search]').outerHeight()-1}).show();
			
			$('div#searchsuggest').text('wait...');
		}
		
		searchvalue = $('form#search input[name=search]').val();
		searchvalue = searchvalue.split('\'').join(' ');
		searchvalue = searchvalue.split('"').join(' ');
		searchvalue = searchvalue.split('*').join(' ');
		suggesthtml = false;
		
		if (search_cache[searchvalue]) {
			suggesthtml = search_cache[searchvalue];
			
			if (suggesthtml)
				$('div#searchsuggest').html(suggesthtml);
			else
				$('div#searchsuggest').text('no suggestions');
		}
		else {
			if (onlycache==true)
				return false;

			hashkey = sha1_hash(searchvalue).substring(0,3);
							
			if (jsoncall !== false)
				jsoncall.abort();

			jsoncall = $.getJSON('../cache/suggest/'+hashkey[0]+'/'+hashkey[1]+'/'+hashkey[2]+'/'+escape(base64_encode(searchvalue))+'.txt', function(data) {
				suggestcontent = $('<div>');
				has_content = false;
											
				for (group in data) {					
					if (group!='search')
						suggestcontent.append($('<h4>').text(headline[group]));
						
					innercontent = $('<ul>').addClass(group);
					
					firstelement=true;
					for (data_id in data[group]) {
						switch(group) {
							case 'search':
							case 'suggest':
								innercontent.append($('<li>').addClass(firstelement ? 'first' : '').html($('<a>').attr('href', 'javascript:;').append(do_highlight(searchvalue, data[group][data_id]))));
								break;

							case 'category':
							case 'manufacturer':
								dataparts = data[group][data_id];
								innercontent.append($('<li>').attr('id', data_id).html($('<a>').attr('href', dataparts['link']).append(do_highlight(searchvalue, dataparts['caption']))));
								break;
								
							case 'product':
								dataparts = data[group][data_id];
								licontent = $('<li>').addClass(firstelement ? 'first' : '').attr('id', data_id);
								licontent.append($('<div>').addClass('imagedata').append($('<img>').attr('src', dataparts['image'])));
								lidata = $('<div>').addClass('suggestdata');
								lidata.append($('<a>').attr('href', dataparts['link']).append(do_highlight(searchvalue, dataparts['caption'])));
								lidata.append($('<span>').addClass('category').text(dataparts['category']));
								lidata.append($('<span>').addClass('price').html(dataparts['amount']));
								licontent.append(lidata);
								licontent.append($('<div>').addClass('clear'));
								innercontent.append(licontent);	
								break;
								
							default:
								innercontent.append($('<li>').attr('id', data_id).html($('<a>').attr('href', 'javascript:;').append(do_highlight(searchvalue, data[group][data_id]))));
								break;
						}
						firstelement=false;
					}

					suggestcontent.append(innercontent);
					has_content=true;
				}

				if (has_content) {
					suggesthtml = suggestcontent.html();
					search_cache[searchvalue] = suggesthtml;
					$('div#searchsuggest').html(suggesthtml);
				}
				else {
					search_cache[searchvalue] = false;
					$('div#searchsuggest').text('no suggestions');
				}
			});
		}
	}
	else
		$('div#searchsuggest').hide();
}

function doclick(listelement) {
	dolink = $(listelement).find('a').attr('href');
	if (dolink!='javascript:;')
		document.location.href = dolink;
	else {
		switch($(listelement).parents('ul').attr('class')) {
			case 'search':
				process_searchover(listelement);
				$('form#search input[name=search]').data('search', false);
				$('div#searchsuggest').hide();
				$('form#search input[name=search]').focus();
				$('form#search').submit();
				break;
			
			case 'manufacturer':
				document.location.href='../category.php?manufacturers='+$(listelement).attr('id');
				break;
		}
	}
}

function submit_search()
{
	$search = $('#search').val();
	if (search.length > 2)
	{
		$('#search').submit();
	}
};

$(document).ready(function() {
	
	$('form #search input[name=search]').bind('keydown', 'return', submit_search);		// for IE < 8
	
	headline = { 'search': 'Suchvorschl�ge', 'category': 'Kategorien' , 'manufacturer': 'Hersteller', 'product': 'Produkte' }
	
	$('div#searchsuggest ul li').live('click', function() {
		doclick(this);
	});
		
	$('div#searchsuggest ul li').live('mouseover', function() {
		process_searchover(this);
	});

	$('div#searchsuggest ul li').live('mouseout', function() {
		$(this).parent('li').removeClass('active');
		if ($('form#search input[name=search]').data('search')!==false)
			$('form#search input[name=search]').val($('form#search input[name=search]').data('search'));
	});

	$('form#search input[name=search]').keydown(function() {
		if ($('form#search input[name=search]').data('search')>'')
			$('form#search input[name=search]').data('beforekey', $('form#search input[name=search]').val());
	});

	$('form#search input[name=search]').keyup(function(event) {
		if ($('form#search input[name=search]').val() != $('form#search input[name=search]').data('beforekey')) {
			dosuggest(true);
			if (typeof(suggesttimer)!='undefined')
				window.clearTimeout(suggesttimer);
			suggesttimer = window.setTimeout('dosuggest()', 50);
			$('div#searchsuggest ul li').removeClass('active');
			$('form#search input[name=search]').data('beforekey', $('form#search input[name=search]').val());
		}
		else {
			switch(event.keyCode) {
				case 38:
					if ($('div#searchsuggest:visible').length>0) {
						activeitem = $('div#searchsuggest ul li.active').index('div#searchsuggest li');
						if (activeitem < 0)
							activeitem = $('div#searchsuggest ul li').length-1;
						else
							activeitem--;
						
						if (activeitem>=0)
							process_searchover($('div#searchsuggest ul li').eq(activeitem));
						else {
							$('div#searchsuggest ul li').removeClass('active');
							$('form#search input[name=search]').val($('form#search input[name=search]').data('search'));
							if ($('form#search input[name=nocache]').length==1)
								$('form#search input[name=nocache]').remove();
						}
					}
					break;
					
				case 40:
					if ($('div#searchsuggest:visible').length>0) {
						activeitem = $('div#searchsuggest ul li.active').index('div#searchsuggest li');
						if (activeitem == $('div#searchsuggest ul li').length-1)
							activeitem = -1;
						else
							activeitem++;
	
						if (activeitem>=0)
							process_searchover($('div#searchsuggest ul li').eq(activeitem));
						else {
							$('div#searchsuggest ul li').removeClass('active');
							$('form#search input[name=search]').val($('form#search input[name=search]').data('search'));
							if ($('form#search input[name=nocache]').length==1)
								$('form#search input[name=nocache]').remove();
						}
					}
					break;
				
				case 39:
					if ($('div#searchsuggest:visible').length>0) {
						activeitem = $('div#searchsuggest ul li.active').index('div#searchsuggest li');
						if (activeitem>=0) {
							$('form#search input[name=search]').val($('div#searchsuggest ul li').eq(activeitem).find('a').text());
							$('form#search input[name=search]').keyup();
						}
					}
					break;
					
				case 27:
					$('form#search input[name=search]').val($('form#search input[name=search]').data('search'));
					$('div#searchsuggest').hide();
					break;
					
				case 13:
					activeitem = $('div#searchsuggest ul li.active').index('div#searchsuggest li');
					
					if (activeitem>0)
						doclick($('div#searchsuggest ul li').eq(activeitem));
					else
						$('form#search').submit();
					break;
			}
		}
	});

	$(document).click(function() {
		if ($('div#searchsuggest:visible').length>0) {
			$('div#searchsuggest').hide()
			return false;
		}
	});
});
