/*
 * Copyright 2009,2010 Cleveratom Limited
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 * 
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 * 
 */

(function($) {

$.fn.cleverslide = function(config) {


var t = $(this);

if (config === undefined) config = {};
if (config.delay === undefined) config.delay = 5000;


if (config.horizontal === undefined) config.horizontal = true;

if (config.showarrows === undefined) config.showarrows = false;
if (config.pagination === undefined) config.pagination = false;
if (config.overlaypaging === undefined) config.overlaypaging = false;

if (config.classprefix === undefined) config.classprefix = "cleverslide";

// todo fix slidingbackground + continuous 
if (config.slidingbackground === undefined) config.slidingbackground = false;

if (config.wrap === undefined) config.wrap = $("<div>").insertAfter(t[0]);

if (config.width === undefined) config.width = config.wrap.width();

if (config.height === undefined) config.height = config.wrap.height();

if (config.initalslide === undefined) config.initalslide = 0;

if (config.reverse === undefined) config.reverse = false;

if (config.easing === undefined) config.easing = 'linear';
if (config.duration === undefined) config.duration = 1000;

if (config.continious === undefined) config.continuous = true;

if (config.showarrows === undefined) config.showarrows = false;

if (config.autohidecontrols === undefined) config.autohidecontrols = false;

var position = 0;
var cur_page = 0;

var paging = false;

var last_interaction = 0;

var slidewrap = $("<div>");


var is_animating = false;


function init()
{
	
config.wrap.addClass(config.classprefix+"_wrap");
	
	// just incase we had previously hidden them
	t.show().removeClass("hide");
	
	t.hover(function(){
		t.removeClass(config.classprefix+"_hover");
		$(this).addClass(config.classprefix+"_hover");
	}, function(){
		$(this).removeClass(config.classprefix+"_hover");
	});
	
	// prevent quirkly looking animations
	if (config.duration > config.delay)
		config.delay = config.duration;
	
	slidewrap.append(t);
	
	if (config.continious)
		$(t[0]).clone().appendTo(slidewrap);
	
	if (config.width != "auto")
		config.width = parseInt(config.width);
	
	if (config.height != "auto")
		config.height = parseInt(config.height);
		
	
	slidewrap.children().addClass(config.classprefix+"_page").css({
		width: config.width,
		height: config.height,
		display: 'block',
		float: (config.horizontal) ? 'left' : 'none'

	});
	
	if (config.showarrows)
	{
	
		var previous_button = $('<a href="javascript:void(0)">').addClass(config.classprefix+"_previous").html("<span>Previous</span>").click(previous);
		var next_button = $('<a href="javascript:void(0)">').addClass(config.classprefix+"_next").html("<span>Next</span>").click(next);
		
		config.wrap.append(previous_button);
		config.wrap.append(next_button);
		
		if (config.autohidecontrols){
			
			previous_button.hide();
			next_button.hide();
		
			config.wrap.hover(function(){
				next_button.show();
				previous_button.show();
			}, function(){
				next_button.hide();
				previous_button.hide();
			});
		
		}
			
	}

	config.wrap.css({
		width: config.width,
		height: config.height,
		overflow: 'hidden'
	});

	
	config.wrap.append(slidewrap);
	
	slidewrap.css({
		height: (config.horizontal ? (config.height) : ((t.length + ((config.continious) ? 1 : 0) * config.height))),
		width: (config.horizontal ? (config.width * (t.length + ((config.continious) ? 1 : 0))) : (config.width)),
		'margin-left': 0,
		'margin-top': 0
	});
	
	var pagingwrap = $("<div>").addClass(config.classprefix+"_pagingwrap");
	
	var paging = $("<ol>").addClass(config.classprefix+"_paging");
	
	paging.appendTo(pagingwrap);
	
	t.each(function(i, val){
	
		val = $(val);
	
		var page = $("<li>");
		
		var title = val.attr("title");
		
		if (title.length)
			page.append($("<span>").text(title));
			
		page.click(function(){
			jump(i, this);
		});
		
		paging.append(page);
	});
	
	if (config.overlaypaging)
		config.wrap.prepend(pagingwrap);
	else
		pagingwrap.insertAfter(config.wrap);
	
	jump(config.initalslide);
	
	cur_page = config.initalslide - 1;
	auto();
}


function auto()
{

	if (config.delay > 0)
	{
		setTimeout ( auto, config.delay );
		if (!t.hasClass(config.classprefix+"_hover"))
			next();
	}
}

function next()
{
	jump(cur_page + (config.reverse ? -1 : 1), this);
}

function previous()
{
	if (cur_page == 0)
	{
		var temp_position = (t.length * (config.horizontal ? config.width : config.height)*-1);
		slidewrap.css({
			"margin-left" : (config.horizontal ? temp_position+'px' : 0),
			"margin-top": (config.horizontal ? 0 : temp_position+'px')
		});
	}
	
	jump(cur_page - (config.reverse ? -1 : 1), this);
}


function jump(i, ref)
{

	if (is_animating)
		return;
			
	// Defer auto movement if user recently selected a page
	// ref should be an element in the page
	if (!$(ref).parent().length)
	{
		if ((last_interaction + config.delay) > new Date().getTime())
			return;
	} else
	{
		last_interaction = new Date().getTime();
	}

	// sanitize so we don't get pages that don't exist
	if (i > t.length)
		i = 0;
	else if(i < 0)
		i = (t.length-1);

	cur_page = i;
	position = ((config.horizontal ? config.width : config.height) * i) * -1;	
	
	move();
}


function move()
{
	is_animating = true;
	slidewrap.stop().animate( { 
		"margin-left" : (config.horizontal ? position+'px' : 0),
		"margin-top": (config.horizontal ? 0 : position+'px')
	 }, {
	 	duration: config.duration,
	 	easing: config.easing,
	 	complete: function(){
	 		is_animating = false;
	 		if (config.continious && cur_page == 0)
			 {
			 	slidewrap.css({
			 		"margin-left" : 0,
			 		"margin-top": 0
			 	});
			 	if (config.slidingbackground)
			 		config.wrap[0].style.backgroundPosition = "0px 0px";
			 }
	 	}
	 });
	 
	 if (config.slidingbackground)
	 {
	 
	 	var str = "("+(config.horizontal ? position+'px' : 0)+" "+  (config.horizontal ? 0 : position+"px")+")";
	 
	 	config.wrap.stop().animate({
	 		"backgroundPosition" : str
	 	}, {duration: config.duration, easing: config.easing});
	 }
	 
	 if (config.continious && cur_page == t.length)
	 {
	 	cur_page = 0;
	 }
}

init();

return this;


};

})(jQuery);


/**
 * @author Alexander Farkas
 * v. 1.02
 */
(function($) {
    $.extend($.fx.step,{
        backgroundPosition: function(fx) {
            if (fx.state === 0 && typeof fx.end == 'string') {
                var start = $.curCSS(fx.elem,'backgroundPosition');
                start = toArray(start);
                fx.start = [start[0],start[2]];
                var end = toArray(fx.end);
                fx.end = [end[0],end[2]];
                fx.unit = [end[1],end[3]];
            }
            var nowPosX = [];
            nowPosX[0] = ((fx.end[0] - fx.start[0]) * fx.pos) + fx.start[0] + fx.unit[0];
            nowPosX[1] = ((fx.end[1] - fx.start[1]) * fx.pos) + fx.start[1] + fx.unit[1];
            fx.elem.style.backgroundPosition = nowPosX[0]+' '+nowPosX[1];

           function toArray(strg){
               strg = strg.replace(/left|top/g,'0px');
               strg = strg.replace(/right|bottom/g,'100%');
               strg = strg.replace(/([0-9\.]+)(\s|\)|$)/g,"$1px$2");
               var res = strg.match(/(-?[0-9\.]+)(px|\%|em|pt)\s(-?[0-9\.]+)(px|\%|em|pt)/);
               return [parseFloat(res[1],10),res[2],parseFloat(res[3],10),res[4]];
           }
        }
    });
})(jQuery);
