/*
 * Copyright: Emposha.com <http://www.emposha.com/> - Distributed under MIT - Keep this message! */
/*
 * elem - input element id or object
 * list - preadded elements
 * complete - autocomplete div id or object
 * ajax - object with two parametrs a) url to fetch json object b) use cache
 * height - maximum number of element shown before scroll will apear
 * filter - object with two parameters a) case sensitive b) show/hide filtered items
 * show_typed - show typed text as an item in results
 * input_options - 1=usernames, 2=emails, 3=both
 */

//jQuery.facebooklist = function(lightbox, elem, list, complete, ajax, height, filter, show_typed, input_options, autocomplete){
jQuery.facebooklist = function(lightbox,elem, list, complete, ajax, height, filter, show_typed, input_options, autocomplete){
	var resultcount;

    var addHiddenInput = function(value,type){
        var input = document.createElement('input');
        jQuery(input).attr({
            'type': 'hidden',
            'name': type+'[]',
            'id': (elem.attr('id') + '[]'),
            'value': value
        });
        return input;
    }


    var getChar = function(e){
        if (window.event) {
            keynum = e.keyCode;
        }
        else 
            if (e.which) {
                keynum = e.which;
            }
        if (keynum == 8) 
            return '';
        return String.fromCharCode(keynum);
    }
    
    var addItem = function(item, preadded){
		var text_input = jQuery('.maininput').val();
		var title = (item.text() ? item.text() : text_input);
        var value = (item.attr('rel') != undefined ? item.attr('rel') : text_input);
        var li = document.createElement('li');
        var txt = document.createTextNode(title);
        var aclose = document.createElement('a');
		var type = "uids";
		
		// Trim leading / trailing spaces
		value = jQuery.trim(value);
		
		// Check if user entered an email address
		if(text_input.search(/.+@.+\..+/) != -1){ 
			if(input_options != 1){
				type = 'emails';
			}else{
				alert('Email addresses are not supported. Please enter a Playlist.com username.');
				jQuery('.maininput').val(''); 
				return;
			}
		}else
		if (input_options == 2) { // if emails only and they did not enter a email
			alert('Please enter a valid email address');
			jQuery('.maininput').val(''); 
			return;
		}else
		if (item.attr('id') == 'typedtext' || item.attr('id') == undefined){
			txt = value;
			type = 'usernames';
		}

		if (value.search(/^\s+$/) != -1) { // If user just entered spaces
		 	jQuery('.maininput').val('');
			return false;
		}
		
		// Check if user has already been entered
		if(jQuery(holder).children('li.bit-box[id="'+value+'"]').attr("id")){
			jQuery('.maininput').val(''); 
			return;
		}
		
		var input = addHiddenInput(value,type);

        jQuery(li).attr({
            'class': 'bit-box',
			'id': value
        });
        jQuery(li).prepend(txt);
        jQuery(aclose).attr({
            'class': 'closebutton',
            'href': '#'
        });
        li.appendChild(aclose);
        li.appendChild(input);
        jQuery('#annoninput').before(li);
        jQuery(aclose).click(function(){
            removeItem(jQuery(this).parent('li'));
            return false;
        });
        if (!preadded) {
            resetInput();
        }
    }

	var removeItem = function(item){
		jQuery(item).fadeOut('fast', function(){
            jQuery(item).remove();
        });
	}
    
    var defaultFilter = function(input){
        if (filter.userfilter) {
            var flag;
            feed.children('li').removeClass('hidden');
            jQuery.each(feed.children('li:not(#typedtext)'), function(i, val){
                var item = jQuery(val);
                if (filter.casesensitive) {
                    flag = item.text().indexOf(input);
                    item.html(item.text().replace(input, '<em>' + input + '</em>'));
                }
                else {
                    flag = item.text().toLowerCase().indexOf(input.toLowerCase());
					var regex = new RegExp('((^| )('+input+'))','i'); // case insensitive, only matches beginning of words
                    item.html(item.text().replace(regex, '<em>$1</em>'));
                }
                if (flag == -1) {
                    item.addClass('hidden');
                }
  
            });
        }

    }
    
    var feedFilter = function(item, caption, input){
        if (filter.userfilter) {
            if (filter.casesensitive) {
                if (caption.indexOf(input) != -1) {
                    item.html(caption.replace(input, '<em>' + input + '</em>'));
                    return true;
                }
            }
            else {
                if (caption.toLowerCase().indexOf(input) != -1) {
                    item.html(caption.replace(input, '<em>' + input + '</em>'));
                    return true;
                }
            }
        }
        else {
            item.html(caption.replace(input, '<em>' + input + '</em>'));
            return true;
        }
    }

	// For better performace we wait 500ms after they stop typing to filter the list
	var addItemFeedDelay = function(data,str) {
		clearTimeout(window.timeout);
	    window.timeout = setTimeout(
			function(){
				if (window.search_string) str = window.search_string; window.search_string = '';
				addItemFeed(data,str);
			},500);
	}


	var addItemFeed = function(data,str) {
		
		var rels = data;
		var result = "";
		var counter = 1;
		
		// clear results - TODO: use show/hide instead of remove/append
		feed.children('li:not(#typedtext)').remove(); 
		
		jQuery.each(data, function(i, val){
			var name = val.name;
			var value = val.uid;
			var regex = new RegExp('(^| )'+str);
			// append results that match the input string AND that haven't already been added
			if(name.toLowerCase().match(regex) && !jQuery(holder).children('li.bit-box[id="'+value+'"]').attr("id")) {
				var li = document.createElement('li');
				jQuery(li).attr({'rel': value});
				jQuery(li).html(name);
				feed.append(li);
				counter++;
			}
		});
		
		if(counter > 1){
			jQuery('.default').hide();
		}else{
			jQuery('.default').show();
		}
		
		if (counter > height) {
			feed.css({'height':(height*24)+'px', 'overflow':'auto'});
		} else {
			feed.css('height','auto');
		}
		
		this.resultcount = counter;
		defaultFilter(str);
		bindEvents();
	}
    
    var addTextItemFeed = function(value){
        if (show_typed) {
            feed.children('li[id=typedtext]').remove();
            var li = document.createElement('li');
            jQuery(li).attr({
                'rel': value,
				'id': 'typedtext'
            });
            jQuery(li).html(value);
            feed.prepend(li);
			counter++;
        }
    }
	
	var removeFeedEvent = function () {
		feed.children('li').unbind('mouseover');	
		feed.children('li').unbind('mouseout');
		feed.mousemove(function () {
			bindFeedEvent();
			feed.unbind('mousemove');
		})	
	}
	
	var bindFeedEvent = function () {
		feed.children('li').mouseover(function(){
			feed.children('li').removeClass("auto-focus");
            jQuery(this).addClass("auto-focus");
            nowFocusOn = jQuery(this);
        });
	}
    
    var bindEvents = function(){
        var maininput = jQuery('.maininput'); 
		var autoselect;
		
       	bindFeedEvent();
	
		// auto-select the first item
		feed.children('li').removeClass("auto-focus");
		if (this.resultcount > 1){
			autoselect = feed.children('li:not(#typedtext):visible:first:');
		}else{
			autoselect = feed.children('li:visible:first')
		}
		autoselect.addClass("auto-focus");
		nowFocusOn = autoselect;
		
        feed.children('li').unbind('click');
        feed.children('li').click(function(){
            addItem(jQuery(this));
            //complete.hide();
        });
        maininput.unbind('keydown');
        maininput.keydown(function(event){
			
			if (jQuery(this).val() == "") {
				if (event.keyCode == 8){
					var lastitem = jQuery(holder).children('li.bit-box:last');
					if(jQuery(lastitem).attr("class")=="bit-box selected"){
						removeItem(lastitem);
					}else{
						jQuery(lastitem).addClass("selected");
					}
				}
				return;
			}
			
			// if user hits return or comma
            if ((event.keyCode == 13 || event.keyCode == 188)) {
                addItem(jQuery(nowFocusOn));
                event.preventDefault();
            }else
            if (event.keyCode == 40) {
				removeFeedEvent();
                if (typeof(nowFocusOn) == 'undefined' || nowFocusOn.length == 0) {
                    nowFocusOn = jQuery(feed.children('li:visible:first'));
					feed.get(0).scrollTop = 0;
                }else {
                    nowFocusOn.removeClass("auto-focus");
                    nowFocusOn = nowFocusOn.nextAll('li:visible:first');
					var prev = parseInt(nowFocusOn.prevAll('li:visible').length,10);
					var next = parseInt(nowFocusOn.nextAll('li:visible').length,10);
					if ((prev > Math.round(height /2) || next <= Math.round(height /2)) && typeof(nowFocusOn.get(0)) != 'undefined') {
						feed.get(0).scrollTop = parseInt(nowFocusOn.get(0).scrollHeight,10) * (prev - Math.round(height /2));
					}
                }
				feed.children('li').removeClass("auto-focus");
                nowFocusOn.addClass("auto-focus");
            }
            if (event.keyCode == 38) {
				removeFeedEvent();
                if (typeof(nowFocusOn) == 'undefined' || nowFocusOn.length == 0) {
                    nowFocusOn = jQuery(feed.children('li:visible:last'));
					feed.get(0).scrollTop = parseInt(nowFocusOn.get(0).scrollHeight,10) * (parseInt(feed.children('li:visible').length,10) - Math.round(height /2));
                }
                else {
                    nowFocusOn.removeClass("auto-focus");
                    nowFocusOn = nowFocusOn.prevAll('li:visible:first');
					var prev = parseInt(nowFocusOn.prevAll('li:visible').length,10);
					var next = parseInt(nowFocusOn.nextAll('li:visible').length,10);
					if ((next > Math.round(height /2) || prev <= Math.round(height /2)) && typeof(nowFocusOn.get(0)) != 'undefined') {
						feed.get(0).scrollTop = parseInt(nowFocusOn.get(0).scrollHeight,10) * (prev - Math.round(height /2));
					}
                }
				feed.children('li').removeClass("auto-focus");
                nowFocusOn.addClass("auto-focus");
            }
        });
    }

	var resetInput = function(){
		var input = jQuery('.maininput');
		input.css('width', '20px');
		input.attr('value','');
		input.focus();
	}
    
    var addInput = function(){
		var li = document.createElement('li');
        var input = document.createElement('input');
        jQuery(li).attr({
            'class': 'bit-input',
            'id': 'annoninput'
        });
        jQuery(input).attr({
            'type': 'text',
            'class': 'maininput'
        });
        li.appendChild(input);
        holder.appendChild(li);
	
        jQuery(input).focus(function(){
			bindEvents();
            complete.css('display','block');
			if (feed.length && jQuery(input).val().length) {
				feed.show();
			}
			else {
				feed.children('li').remove();
				feed.children('li').addClass('hidden');
				feed.css('height','0px');
				jQuery('.default').show();
			}
        });
		

		jQuery(input).click(function(e){
		   	e.stopPropagation(); // stop click event from propagating to next trigger
		});
        jQuery(holder).click(function(){
            jQuery(input).focus();
        });
        jQuery(input).keyup(function(event){
			
			resizeTextInput();
			
			if (jQuery(this).val() == "") {
				jQuery('.default').show();
				jQuery(feed).hide();
				return;
			}else{
				// if text is entered then no items should be focused (selected for deletion)
				jQuery(holder).children('li.bit-box').removeClass("selected");
			}

            if (event.keyCode != 40 && event.keyCode != 38 && input_options !=2 && autocomplete == true) {
                counter = 0;
                var etext = jQuery(input).val();
                addTextItemFeed(etext);
				
                if (ajax.url) {
                    if (ajax.cache && items_cached == true) {
						if(window.items_loading){
							window.search_string = etext; // if still loading results just update the search string
							return;
						}
                        addItemFeedDelay(cache,etext);
                    }else {
						jQuery('.search_message').show();
						//jQuery('.default').hide();
						items_cached = true;
						window.items_loading = true;
                        jQuery.getJSON(ajax.url, null, function(data){
							jQuery('.search_message').hide();
							if(data == null){ // if user is not following anyone
								if(input_options == 1){ // if were only accepting usernames then show a message to the users
									noResultsMessage();
								}
								jQuery('.default').show();
								return;	
							}
							window.items_loading = false;
                            addItemFeedDelay(data,etext);
                            cache = data;
                        });
                    }
                }
                else {
                    bindEvents();
                }
                feed.show();
            }
        });

    }


	var noResultsMessage = function(){
		jQuery('.noresults').show();
		jQuery('#shareForm').hide();
	}
	
	// Change text input width to fit contents
	var resizeTextInput = function(){
		jQuery('.maininput').css('width',jQuery('.maininput').val().length*7+30+'px');
		// Fixes a bug where if user pastes in a string of text the text does not move to the right to the fill the wider input field
		// Facebook's autocomplete also has this problem, so assuming it's not a bug in our code
		// THIS WORKAROUND CAUSES IE ISSUES: makes it impossible to select the input text, very slow
		// jQuery('.maininput').val(jQuery('.maininput').val());
	}
	
	var lookupByUsername = function(){
		
	}	
    
    if (typeof(elem) != 'object') {
		elem = jQuery(elem);
	}
    if (typeof(list) != 'object') {
		list = jQuery(list);
	}
    if (typeof(complete) != 'object') {
		complete = jQuery(complete);
	}
    var feed = jQuery('#feed');
    var cache = {};
	var items_cached = false;
    var counter = 0;
	var nowFocusOn;
    var holder = document.createElement('ul');
    elem.css('display', 'none');
    jQuery(holder).attr('class', 'holder');
    
	// We can specify options that should always appear in results list
    /*if (list && list.children('li').length) {
        jQuery.each(list.children('li'), function(i, val){
            addItem(jQuery(list.children('li')[i]), 1);
        });
    }*/
	
	elem.before(holder);
    addInput();
    
	jQuery('.maininput').focus();
	
	jQuery(document).click(function (event) {
		if (jQuery(event.target).attr('class') != 'holder' && jQuery(event.target).attr('class') != 'maininput') {
			jQuery(feed).hide();
		}
	});
	
	jQuery('#shareForm').submit(function() {
    	var inputs = [];
		var users_selected = false;
		var invalid_users;
		
		if(jQuery('.maininput').val()){
			addItem(jQuery(nowFocusOn));
		}
		
   		jQuery(':input[type="hidden"]', '#shareForm').each(function() {
        	if (this.name == "uids[]" || this.name == "emails[]" || this.name == "usernames[]") {
                users_selected = true;
            }
			inputs.push(this.name + '=' + escape(this.value));
        });

        if (!users_selected) return false; // do nothing if no users were added

		// Disable submit until we get a response
		$('#invite_submit').attr("disabled", "disabled");

        jQuery.ajax({
       		type: "POST",
       		url: "/async/share/process",
       		data: inputs.join('&'),
			timeout:30000,
			dataType: 'json',
       		success: function(data){
				if(data.invalid_usernames.length){ // returns any usernames that were invalid
					invalid_users = data.invalid_usernames.join(', ');
					$('.invalid_users').css('display','block');
					$('.invalid_users').html('We could not invite these users because they are not valid Playlist.com usernames: '+invalid_users);
					
					if(data.invites_sent){
						$('.success_inline').css('display','block');
						var plural = (data.invites_sent > 1?'users':'user');
						$('.success_inline').html('Success, you invited '+data.invites_sent+' '+plural+' to your group playlist!');
					}
					
					jQuery('li.bit-box').each(function() {
						removeItem(this);
					});
					
					$('#invite_submit').removeAttr("disabled");
			
					return false;
				}
            	jQuery('.boxy-wrapper .close').hide();
               	lightbox.setContent('<div class="success">'+success+'</div>');
                lightbox.center();
                setTimeout(function(){lightbox.hideAndUnload();},1000);
          	}
    	});
        return false;
    });
}