var localfn = {};

Function.prototype.method = function (name, func) {
    this.prototype[name] = func;
    return this;
};

String
	.method('trim',function() {
		return $.trim(this);
	});

$.fn.near = function(selector) {
    var $found;
    this.each( function() {
        var $parent = $(this);
        do {
            $parent = $($parent.get(0).parentNode);
            $found = $(selector, $parent);
        } while($parent.get(0)!==document && $found && $found.length===0);
    });
    return $found || this;
};

$.extend(localfn,{
	'isArray': function(value) {
        return value &&
            typeof value === 'object' &&
            value.constructor === Array;
    },
	'isChar': function(keyCode) {
		if (keyCode <= 47 && keyCode != 32 && keyCode != 0) {
			return false;
		}
		else {
			return true;
		} 
	},
	'toPostArray': function(name, data) {
		var ret = {};
		var i = 0;
		$.each(data, function(key, item) {
			ret[name+'['+i+']'] = item;
			i++;
		});
		return ret;
	}
});

$.fn.clearForm = function() {
	return this.each(function() {
	var type = this.type, tag = this.tagName.toLowerCase();
	if (tag == 'form')
		return $(':input',this).clearForm();
	if (type == 'text' || type == 'password' || tag == 'textarea')
		this.value = '';
	else if (type == 'checkbox' || type == 'radio')
		this.checked = false;
	else if (tag == 'select')
		this.selectedIndex = -1;
	});
};

var processServerResult = function(res, settings, target, erroraction, msgaction) {
	
	switch (res.action) {
		case 'error':
			erroraction(res.error, res.target);
			break;
		case 'errormsg':
			alert(res.error);
			break;
		case 'message':
			msgaction(res.message, res.target)
			if (settings.complete && res.data) {
				settings.complete.apply(target,[res.data]);
			}
			break;
		case 'location':
			window.location = res.location;
			break;
		case 'complete':
			settings.complete.apply(target,[res.data]);
			break;
	}
	
}

$.fn.makeTabs = function(settings) {
	var self = $(this);
	if (typeof settings.initial !== 'undefined') {
		settings.initial = settings.tabs[0];
	}
	
	var showTab = function(show_tab) {
		$.each(settings.tabs, function(index, tab) {
			var link = $('li.'+tab,self);
			var form = $('#'+tab,self);
			if (tab === show_tab) {
				link.addClass('selected');
				form.show();
			}
			else {
				link.removeClass('selected');
				form.hide();
			}
		});
	}
	
	$.each(settings.tabs, function(index, tab) {
		var link = $('li.'+tab,self);
		link.children('a').click(function(e) {
			showTab(tab);
			e.preventDefault();
		})
	})
	showTab(settings.initial);
	
	return self;
};

$.fn.makeAjaxForm = function(options) {
	var settings = $.extend({
		complete: function() {},
		reset: true
	}, options);
	
	$(this).each(function() {
		var self = $(this);
		
		var prepend = function(item) {
			var legend = self.find('legend');
			if (legend.length > 0) {
				legend.eq(0).after(item);
			}
			else {
				self.prepend(item);
			}
		}
		
		var errordiv = $('.errors',self);
		if (errordiv.length == 0) {
			errordiv = $('<div></div>').addClass('errors');
			prepend(errordiv);
		}
		var msgdiv = $('.message',self);
		if (msgdiv.length == 0) {
			msgdiv = $('<div></div>').addClass('message');
			prepend(msgdiv);
		}
		
		var collectData = function() {
			var data = new Object();
			
			$('input,textarea,select',self).each(function(index, elm) {
				if ($(elm).attr('name')) {
					if (($(elm).attr('type') != 'checkbox' && $(elm).attr('type') != 'radio') || $(elm).is(':checked')) {
						data[$(elm).attr('name')] = $(elm).val().trim();
					}
				}
			});
			
			return data;
		}
		
		var setError = function(text) {
			if ($.isArray(text)) {
				var errors = text;
				text = '';
				for (var i=0; i < errors.length; i++) {
					text += errors[i] + '<br />';
				}
			}
			errordiv.html(text);
			errordiv.show();
		}
		
		var setMessage = function(text) {
			msgdiv.html(text);
			var returnlink = $('<div></div>');
			returnlink.html($('<a href="">&lt;&lt; back</a>').click(function(e) {
				e.preventDefault();
				$('.fields',self).show();
				msgdiv.hide();
				return false;
			}));
			msgdiv.append(returnlink).show();
			$('.fields',self).hide();
			if (settings.reset) self.clearForm();
		}
		
		var enableElements = function(val) {
			$('input,textarea,select',self).each(function() {
				if (!val) $(this).attr('disabled','true');
				else $(this).removeAttr('disabled');
			})
		}
		
		$(self).submit(function(e) {
			e.preventDefault();
			var action = self.attr('action');
			var method = self.attr('method');
			errordiv.hide();
			enableElements(false);
			$.ajax({
				type: method,
				url: action,
				dataType: 'json',
				data: collectData(),
				success: function(res, status) {
					enableElements(true);
					processServerResult(res, settings, self, setError, setMessage);
					settings.complete();
				},
				error: function(req, error) {
					enableElements(true);
					setError('An error has occurred');
				}
			})
			
			return false;
		});
		
		if (errordiv.text() === '') errordiv.hide();
	});
}

$.fn.lengthLimiter = function(options) {
	var settings = $.extend({
		length: 500,
		feedback: null,
		preventEnter: true
	}, options);
	
	$(this).each(function() {
		var self = $(this);
		var previoustext = '';
		
		var getLength = function() {
			return self.val().length;
		}
		
		self.keydown(function(e) {
			if ((localfn.isChar(e.keyCode) && getLength() >= settings.length)
				|| (settings.preventEnter && e.keyCode == 13)) {
				e.preventDefault();
				return false;
			}
		})
		
		self.keyup(function(e) {
			if (settings.feedback) {
				$(settings.feedback).text(getLength());
			}
			if (getLength() > settings.length) {
				self.val(previoustext);
			}
			else previoustext = self.val();
		}).keyup();
	});
}

$.fn.popupform = function(options) {
	var settings = $.extend({
		confirm_text: 'OK',
		complete: function() {},
		live: false
	}, options);
	
	$(this).each(function() {
		var self = $(this);
		var location = self.attr('href');
		var popup = null;

		var completeAction = function(popup, data) {
			$.each(data, function(key, val){
				if (key.substr(0,1) == '.' || key.substr(0,1) == '#') {
					if ($(key).hasAttr('value')) $(key).val(val);
					else $(key).html(val);
				}
			})
			settings.complete.apply(self, [data]);
			popup.dialog('close');
			popup = null;
		}

		var doForm = function(e) {
			e.preventDefault();
			if (popup) return false;
			popup = true;
			$.get(location,null,function(data) {
				popup = $(data);
				popup.find('.submitter').remove();
				popup.bind('complete',function(e, data){
					completeAction(popup, data)
				})
				popup.makeAjaxForm({
					complete: function(data){
						completeAction(popup, data);
					}
				});
				var buttons = {};
				buttons['Cancel'] = function() { $(this).dialog('close');};
				if (settings.confirm_text) {
					buttons[settings.confirm_text] = function() {
						popup.submit();
					};	
				}
				
				popup.dialog({
					bgiframe:true,
					autoOpen: true,
					modal: true,
					width:460,
					buttons: buttons,
					close: function() {
						popup.remove();
						popup = null;
						$('.ui_dialog').remove();
					}
				});
			})
			
			return false;
		}
		if (settings.live) $('#'+self.attr('id')).live('click',doForm)
		else self.click(doForm);
	})
}

$.fn.showmsg = function(options) {
	var settings = $.extend({
		confirm_text: 'OK',
		complete: function() {},
		live: false
	}, options);
	
	$(this).each(function() {
		var self = $(this);
		var location = self.attr('href');
		var popup = null;

		var completeAction = function(popup, data) {
			settings.complete.apply(self, [data]);
			popup.dialog('close');
			popup = null;
		}

		var doForm = function(e) {
			e.preventDefault();
			if (popup) return false;
			popup = true;
			$.get(location,null,function(data) {
				popup = $(data);
				var buttons = {};
				buttons[settings.confirm_text] = function() { $(this).dialog('close');};
				
				popup.dialog({
					bgiframe:true,
					autoOpen: true,
					modal: true,
					width:460,
					buttons: buttons,
					close: function() {
						popup.remove();
						popup = null;
						$('.ui_dialog').remove();
					}
				});
			})
			
			return false;
		}
		if (settings.live) $('#'+self.attr('id')).live('click',doForm)
		else self.click(doForm);
	})
}

$.fn.confirmpopup = function(options) {
	var settings = $.extend({
		confirm_text: 'Are you sure?',
		complete: function() {}
	}, options);

	$(this).each(function() {
		var self = $(this);
		var location = self.attr('href');
		var popup = null;

		self.click(function(e) {
			e.preventDefault();
			popup = $('<div></div>');
			popup.html(settings.confirm_text);
			var buttons = {
				'Cancel': function() { 
					$(this).dialog('close');
				},
				'OK': function() {
					$.get(location,null,function(data) {
						if (!data) data = {};
						$.each(data, function(key, val){
							if (key.substr(0,1) == '.' || key.substr(0,1) == '#') {
								if ($(key).hasAttr('value')) $(key).val(val);
								else $(key).html(val);
							}
						})
						settings.complete.apply(self, [data]);
						popup.dialog('close');
					}, 'json');
				}
			};
			
			
			popup.dialog({
				bgiframe:true,
				autoOpen: true,
				modal: true,
				width:300,
				buttons: buttons,
				close: function() {
					popup.remove();
					popup = null;
					$('.ui_dialog').remove();
				}
			});
		})
		
	});
}

$.fn.ajaxlink = function(options) {
	var settings = $.extend({
		complete: function() {},
		data: function() {},
		live: false
	}, options);
	
	$(this).each(function() {
		var self = $(this);

		var doAction = function(e) {
			var location = self.attr('href');
			e.preventDefault();
			var data = settings.data.apply(self);
			$.get(location,null,function(data) {
				processServerResult(data, settings, self);
			}, 'json');
			return false;
		};
		
		if (settings.live) $(settings.live).live('click',doAction);
		else self.click(doAction)
		
	});
}

$.fn.ajaxloader = function(options) {
	var settings = $.extend({
		complete: function() {},
		data: function() {},
		live: false,
		target: null
	}, options);
	
	$(this).each(function() {
		var self = $(this);

		var doAction = function(e) {
			var location = self.attr('href');
			e.preventDefault();
			var data = settings.data.apply(self);
			$.get(location,null,function(data) {
				if (settings.target) $(settings.target).html(data);
				settings.complete.apply(self,[data])
			}, 'html');
			return false;
		};
		
		if (settings.live) $(settings.live).live('click',doAction);
		else self.click(doAction)
		
	});
}

$.fn.countdown = function(options) {
	var settings = $.extend({
	}, options);
	
	$(this).each(function() {
		var self = $(this);
		var offset = ((new Date).getTime() / 1000) - settings.server_now;
		var updateClock = function() {
			var remaining = Math.round(settings.deadline - ((new Date).getTime() / 1000) + offset);
			if (remaining >= 0) {
				var days = Math.floor(remaining / (3600 * 24));
				remaining -= days * 3600 * 24;
				var hours = Math.floor(remaining / 3600);
				remaining -= hours * 3600;
				var minutes = Math.floor(remaining / 60);
				var seconds = Math.round(remaining - minutes * 60);
				
				if ((hours + '').length == 1) 
					hours = '0' + hours;
				if ((minutes + '').length == 1) 
					minutes = '0' + minutes;
				if ((seconds + '').length == 1) 
					seconds = '0' + seconds;
				
				var str = '<strong>' + days + '</strong>d <strong>' + hours + '</strong>h <strong>' + minutes + '</strong>m <strong>' + seconds + '</strong>s until deadline';
				setTimeout(updateClock, 1000);
			}
			else var str = '';
			self.html(str);
		}
		updateClock();
	});
}

$.fn.selectsubmit = function(options){
	var settings = $.extend({}, options);
	
	return $(this).each(function() {
		var self = $(this);
		self.change(function() {
			self.closest('form').submit();
		})
	})
}

$.fn.blurinput = function(options){
	var settings = $.extend({
		blurtext: 'Enter text here...',
		blurclass: 'blur'
	}, options);
	
	return $(this).each(function() {
		var self = $(this);
		self.val(settings.blurtext);
		self.addClass(settings.blurclass);
		self.focus(function() {
			if (self.val() == settings.blurtext) {
				self.val('');
				self.removeClass(settings.blurclass);
			}
		})
		self.blur(function() {
			if (self.val() == '') {
				self.val(settings.blurtext);
				self.addClass(settings.blurclass);
			}
		})
	})
}

$.fn.inputenabler = function(options) {
	var settings = $.extend({}, options);
	
	return $(this).each(function() {
		var self = $(this);
		var button = self.near('input[type=submit]');
		var updateSubmit = function() {
			if (self.val().trim() == '' || self.hasClass('blur')) {
				button.attr('disabled','disabled');
			}
			else {
				button.removeAttr('disabled');
			}
		}
		updateSubmit();
		self.keyup(updateSubmit);
		self.blur(updateSubmit);
	})
}

var checkFbPublish = function(data) {
    if (!data) return false;
    if (data.data) data.fb = data.data.fb;
    if (data.fb) {
        FB.Connect.streamPublish('', data.fb.attachment, data.fb.action_links, data.fb.target_id, '', null, false);
    }
}
