/**
 * Ticker class
 * 
 * The ticker starts with a predefined number of elements. Every x seconds a request is made to a server for more elements
 * the returned elements are added to the ticker.
 * In the event that there are not enough ticks to keep ticking the ticker takes elements from the front of the ticker
 * and places them at the end of the ticker to create a carousel.
 * 
 * @todo See if we can keep the number of elements in the ticker static by creating a different queue of new elements. This
 * 		 means we will not have to recalculate the width of the inner container.
 * @todo see what we will do if there are too many elements to show
 */
var Ticker = new Class({

	Implements: [Options, Events],
    
	/**
	 * Default objects
	 */
	options: {
		id					: '001',
		container			: 'ticker_container',
		height 				: 100,
		width				: 400,
		elementWidth		: 100,
		animation			: {
			duration		: 4
		},
		request				: {
			url				: 'http://spoxx.tests2m.nl/ajax/getTickerUserVotes',
			interval		: 30
		},
		debug				: false
    },

    /**
     * Animation object
     */
    _animation			: null,
    
    /**
     * Animation configuration object
     */
    _fxConfig			: {
    	transition		: 'linear'
    },
    
    /**
     * Initial constructor for the class
     */
    initialize: function(options){
    	this.setOptions(options);
    	window.addEvent('load', this.setupTicker.bind(this));
    },
    
    /**
     * When everything is loaded call the setupTicker to actually build the ticker
     */
    setupTicker : function() {
    	$(this.options.container).appendChild(this._setInnerContainer());

    	/*
    	 * Initial fill
    	 */
    	this._getNewTicks(15);
    	
    	/*
    	 * Fill on timer
    	 */
    	this._getNewTicks.periodical(this.options.request.interval * 1000, this, 11);
    	
    	/*
    	 * Define animation and start the animation
    	 */
    	this._fxConfig.duration		= (this.options.animation.duration.toInt() * 1000);
    	
    	this._animation 	= new Fx.Morph('ticker_container_inner-' + this.options.id, this._fxConfig);
    	this._doAnimation();
    },
    
    /**
     * Make an ajax call to get new elements from the server
     */
    _getNewTicks : function(amount) {
    	var requestOptions	= {
    		url		: this.options.request.url,
    		method	: 'post',
    		noCache: true,
			onSuccess: function(jsonObj) {
//    			console.log('count: ' + jsonObj.length);
    		
				if (jsonObj != null){	
					for (var x=0; x< jsonObj.length; x++){
//						console.log(jsonObj[x]);
    					var val		= '';
    					for (var item in jsonObj[x]){
//							console.log(item + " :: " + jsonObj[x][item]);
    						val	+= "<span class=\"" + item + "\">" + jsonObj[x][item] + "</span>";
     					}

     				var tickOptions = {
    					value	: val
    				};

    	    			$('ticker_container_inner-' + this.options.id).appendChild(this._createTick(tickOptions));
    	    			$('ticker_container_inner-' + this.options.id).setStyle('width', $('ticker_container_inner-' + this.options.id).getChildren().length * this.options.elementWidth.toInt());
					}
				}
    		}.bind(this)
		};
    	var myJSONRemote 	= new Request.JSON(requestOptions).send();
    		
    },
    
    /**
     * Setup the scroll
     * @todo what if the end is reached
     */
    _doAnimation : function(){
    	var dimensions		= $('ticker_container_inner-' + this.options.id).getCoordinates();
    	var containerLeft	= $(this.options.container).getPosition().x;
    	var innerLeft		= $('ticker_container_inner-' + this.options.id).getPosition().x;
    	
		/*
    	 * See if we should move ticks to the back of the ticker
    	 */
    	if (dimensions.left < containerLeft - (2 * this.options.elementWidth)){

    		if ((innerLeft + dimensions.width) < (containerLeft + this.options.width + (5 * this.options.elementWidth))){

				if ($('ticker_container_inner-' + this.options.id).getFirst() != null) {
	    			var element	= $('ticker_container_inner-' + this.options.id).getFirst().clone();
    				$('ticker_container_inner-' + this.options.id).grab(element, 'bottom');
    				$('ticker_container_inner-' + this.options.id).getFirst().dispose();
    				$('ticker_container_inner-' + this.options.id).setStyle('left', ((innerLeft - containerLeft)+this.options.elementWidth) + "px");
				}
    			if (this.options.debug){
//    				console.log("Setting left: " + (innerLeft+this.options.elementWidth));
    			}
    			
    		}else{

    			$('ticker_container_inner-' + this.options.id).getFirst().dispose();
    			$('ticker_container_inner-' + this.options.id).setStyle('left', ((innerLeft - containerLeft)+this.options.elementWidth) + "px");
    			if (this.options.debug){
    				console.log("Setting left 2: " + (innerLeft+this.options.elementWidth));
    			}
    			var width	= $('ticker_container_inner-' + this.options.id).getChildren().length * this.options.elementWidth;
    			$('ticker_container_inner-' + this.options.id).setStyle('width', width + 'px');
//    			console.log('enough elements, dispose of first');
    			
    		}

    	}else{

//    		if (this.options.debug){
//	    		console.log('within margins, don\'t change a thing');
//  	  		console.log($(this.options.container).getPosition().x - (5 * this.options.elementWidth) + " :: " + dimensions.left);
//    		}

    	}

    	var dimensions	= $('ticker_container_inner-' + this.options.id).getPosition().x - containerLeft;

		var to			= dimensions - this.options.elementWidth;
		if (this.options.debug){
			//console.log("to: " + to + " Left: " + dimensions + " Container left: " + containerLeft);
		}
		this._animation.start({'left' : to}).chain(this._doAnimation.bind(this));
    	
    },
    
    /**
     * Create the inner container for the ticker
     */
    _setInnerContainer : function(){
    	var myInnerContainer = new Element('div', {
    		'id'			: 'ticker_container_inner-' + this.options.id,
    	    'class'			: 'ticker_container_inner',
    	    'html'			: '',
    	    'styles'		: {
    	        'display'	: 'block',
    	        'position'	: 'absolute',
    	        'left'		: 0,
    	        'top'		: 0,
//    	        'border'	: '1px solid black',
    	        'width'		: this.options.width,
    	        'height'	: this.options.height
    	    }    	    
    	});
    	return myInnerContainer;
    },
    
    /**
     * create a new element for in the ticker
     */
    _createTick : function(tickOptions) {
    	var myTick = new Element('div', {
//    		'id'			: 'tick-' + tickOptions.id,
    	    'class'			: 'tick',
    	    'html'			: tickOptions.value,
    	    'styles'		: {
    	        'display'	: 'block',
    	        'width'		: this.options.elementWidth,
    	        'height'	: this.options.height,
    	        'float'		: 'left'
    	    }    	    
    	});
    	return myTick;
    }
    
});

