(function ($, undefined) {
	var methods = {
		'init': function (options) {
			$.extend (settings, options);

			surface = $('<div />').addClass ('slider-surface').appendTo ('body');

			if (settings['repeat'] === 'circular')
			{
				$.error ('this is not implemented properly.');
				var pnodes = [];
				var nnodes = [];
				var length = $(this).find (settings['selector']).length;

				if ( settings['steps'] > 1)
				{
					for (var i = 0; i < settings['steps']; i ++)
					{
						pnodes.push ($($(this).find (settings['selector']).get (i)).clone (true));

						nnodes.push ($($(this).find (settings['selector']).get (length - (settings['steps'] - i))).clone (true));
					}
				}

				$.each (nnodes, function (i, v) {
					$(this).appendTo (surface);
				});
				$(this).find (settings['selector']).each (function (i, v) {
					$(this).appendTo (surface);
				});
				$.each (pnodes, function (i, v) {
					$(this).appendTo (surface);
				});
			}
			else
			{
				$(this).find (settings['selector']).each (function (i, v) {
					$(this).appendTo (surface);
				});
			}

			var p = 0;
			$(surface).children (settings['selector']).each (function () {
				if (settings['axis'] == 'x')
				{
					p += $(this).outerWidth (true);
				}
				else
				{
					p += $(this).outerHeight (true);
				}

				$(this).css ({ 'float': 'left' });
			});

			var properties = { position: 'relative' };
			properties[settings['axis'] == 'x' ? 'width' : 'height'] = p;
			properties[settings['axis'] == 'x' ? 'height' : 'width'] = settings['axis'] == 'x' ? $(this).outerHeight (true) : $(this).outerWidth (true);

			$(surface).css (properties).appendTo (this).show ();

			$(this).css ({ 'overflow': 'hidden', 'position': 'relative' });

			count = $(surface).find (settings['selector']).length;

			if (settings['repeat'] === 'circular' && settings['steps'] > 1)
			{
				methods['focus'] (settings['steps'], 0);
			}

			if (settings['auto'] === true)
			{
				interval_id = setInterval (function () { methods[settings['action']] (); }, settings['interval']);
			}

			return this;
		},
		'options': function (option, value) {
			if (typeof value === 'undefined')
			{
				return settings[options];
			}

			switch (option)
			{
				// requires reinit
				case 'steps':
				case 'repeat':
				case 'axis':
					$.error ('jQuery.slider does not implement changing these options yet.');
					settings[option] = value;
					methods['reinit'] ();
					break;

				// regular
				case 'auto':
				case 'active':
				case 'interval':
				case 'duration':
				case 'callback':
				case 'easing':
					settings[option] = value;
					break;

				// protected
				case 'width':
				case 'height':
				default:
					$.error ('jQuery.slider does not allow modification of `' + option + '`.');
					break;
			}

			return this;
		},
		'toggle': function () {
			settings['active'] = settings['active'] ? false : true;

			return this;
		},

		'increase': function () {
			return methods['focus'] (position + settings['steps']);
		},
		'decrease': function () {
			return methods['focus'] (position - settings['steps']);
		},

		'focus': function (index, duration, easing, callback) {
			if (typeof index === 'undefined')
			{
				return position;
			}

			if (typeof duration === 'undefined')
			{
				duration = settings['duration'];
			}
			if (typeof easing === 'undefined')
			{
				easing = settings['easing'];
			}
			if (typeof callback === 'undefined')
			{
				callback = settings['callback'];
			}

			if ( ! settings['active'])
			{
				return this;
			}

			if (index >= 0 &&
				(index + settings['steps']) <= count)
			{
				var p = 0;

				var i = 0;
				$(surface).children (settings['selector']).each (function () {
					if (i >= index)
					{
						return false;
					}

					if (settings['axis'] == 'x')
					{
						p += $(this).outerWidth (true);
					}
					else
					{
						p += $(this).outerHeight (true);
					}

					i ++;

					return true;
				});

				var properties = {};
				properties[(settings['axis'] == 'x' ? 'left' : 'top')] = -p;

				$(surface).animate (properties, duration, easing, callback);

				position = index;
			}
			else if (settings['repeat'] === 'circular')
			{
				if (index < 0)
				{
					var p = 0;
					var i = 0;
					$(surface).children (settings['selector']).each (function () {
						if (i >= count - (settings['steps'] * 2))
						{
							return false;
						}

						if (settings['axis'] == 'x')
						{
							p += $(this).outerWidth (true);
						}
						else
						{
							p += $(this).outerHeight (true);
						}

						i ++;
					});

					var properties = {};
					properties[(settings['axis'] == 'x' ? 'left' : 'top')] = -p;
					$(surface).css (properties);

					position = count - (settings['steps'] * 2);

					methods['focus'] (position - settings['steps']);
				}
				else
				{
					var p = 0;
					var i = 0;

					$(surface).children (settings['selector']).each (function () {
						if (i >= settings['steps'])
						{
							return false;
						}

						if (settings['axis'] == 'x')
						{
							p += $(this).outerWidth (true);
						}
						else
						{
							p += $(this).outerHeight (true);
						}

						i ++;
					});

					var properties = {};
					properties[(settings['axis'] == 'x' ? 'left' : 'top')] = -p;
					$(surface).css (properties);

					position = settings['steps'];

					methods['focus'] (position + (settings['steps'] + ((index + settings['steps']) - (count + settings['steps']))));
				}
			}
			else if (settings['repeat'] === 'rewind')
			{
				if (index > -settings['steps'] && index < 0)
				{
					methods['focus'] (0);
				}
				else if (index > count - settings['steps'] && index < count)
				{
					methods['focus'] (count - settings['steps']);
				}
				else if (index < 0)
				{
					methods['focus'] (count - settings['steps']);
				}
				else
				{
					methods['focus'] (0);
				}
			}

			return this;
		}
	};

	var settings = {
		active: true,
		auto: true,
		steps: 1,
		repeat: 'circular',
		interval: 2000,
		duration: 1000,
		callback: undefined,
		axis: 'x',
		action: 'increase',
		easing: 'swing',
		width: undefined,
		height: undefined,
		instant: false,
		selector: 'a'
	};

	var surface = undefined;

	var position = 0;
	var count = 0;

	var interval_id = undefined;

	$.fn.myslider = function (method) {
		if (methods[method])
		{
			return methods[method].apply (this, Array.prototype.slice.call (arguments, 1));
		}
		else if (typeof method === 'object' || ! method)
		{
			return methods['init'].apply (this, arguments);
		}
		else
		{
			$.error ('Method ' + method + 'does not exist on object jQuery.slider.');
			return false;
		}
	};
}) (jQuery);


