/*
Parameters:
	box: dom element | required
	items: dom collection | required
	size: int | item size (px) | default: 240
	mode: string | 'horizontal', 'vertical' | default: 'horizontal'
	addButtons:{
		previous: single dom element OR dom collection| default: null
		next:  single dom element OR dom collection | default: null
		play:  single dom element OR dom collection | default: null
		playback:  single dom element OR dom collection | default: null
		stop:  single dom element OR dom collection | default: null
	}
	button_event: string | event type | default: 'click'
	handles: dom collection | default: null
	handle_event: string | event type| default: 'click'
	fxOptions: object | Fx.Tween options | default: {duration:500,wait:false}
	interval: int | seconds for periodical | default: 1
	autoPlay: boolean | default: false
	onWalk: event | pass arguments: currentItem, currentHandle | default: null
	startItem: int | default: 0

Properties:
	box: dom element
	items: dom collection
	size: int
	mode: string
	buttons: object
	button_event: string
	handles: dom collection
	handle_event: string
	previousIndex: int
	nextIndex: int
	fx: Fx.Tween instance
	interval: int
	autoPlay: boolean
	onWalk: function

Methods:
	previous(manual): walk to previous item
		manual: bolean | default:false
	next(manual): walk to next item
		manual: bolean | default:false
	play (interval,direction,wait): auto walk items
		interval: int | required
		direction: string | "previous" or "next" | required
		wait: boolean | required
	stop(): stop auto walk
	walk(item,manual,noFx): walk to item
		item: int | required
		manual: bolean | default:false
		noFx: boolean | default:false
	addHandleButtons(handles):
		handles: dom collection | required
	addActionButtons(action,buttons):
		action: string | "previous", "next", "play", "playback", "stop" | required
		buttons: dom collection | required

Requires:
	prototype
*/
var ProtoSlide = Class.create();

ProtoSlide.prototype = {
	initialize: function(params){
		this.items = params.items;
		this.mode = params.mode || 'horizontal';
		this.modes = {horizontal:['left','width'], vertical:['top','height']};
		this.size = params.size || 240;
		this.partialWalk = params.partialWalk || false;
		this.box = params.box;
		this.mask = params.mask;

		if (this.mode == 'horizontal') {
			this.box.setStyle({
				width: (this.size * this.items.length) + 'px'
			});
		} else {
			this.box.setStyle({
				height: (this.size * this.items.length) + 'px'
			});
		}

		this.button_event = params.button_event || 'click';
		this.handle_event = params.handle_event || 'click';
		this.onWalk = params.onWalk || null;
		this.walkLimit = params.walkLimit || 99;
		this.currentIndex = null;
		this.previousIndex = null;
		this.nextIndex = null;
		this.interval = params.interval || 1;
		this.autoPlay = params.autoPlay || false;
		this.playDirection = null;
		this.stopOnFirstItem = params.stopOnFirstItem || false;
		this.stopOnLastItem = params.stopOnLastItem || false;
		this._play = null;
		this.handles = params.handles || null;
		if (this.handles){
			this.addHandleButtons(this.handles);
		}
		this.buttons = {
			previous: [],
			next: [],
			play: [],
			playback: [],
			stop: []
		};
		if (params.addButtons){
			for (var action in params.addButtons){
				this.addActionButtons(action, $type(params.addButtons[action]) == 'array' ? params.addButtons[action] : [params.addButtons[action]]);
			}
		}
		this.walk((params.startItem || 0), true, true);
	},

	addHandleButtons: function(handles) {
		for (var i = 0; i < handles.length; i++) {
			handles[i].observe(this.handle_event, this.handler.bind(this, [i]));
		}
	},

	addActionButtons: function(action, buttons) {
		for (var i = 0; i < buttons.length; i++) {
			switch (action){
				case 'previous': buttons[i].observe(this.button_event,this.previous.bind(this,[true])); break;
				case 'next': buttons[i].observe(this.button_event,this.next.bind(this,[true])); break;
				case 'play': buttons[i].observe(this.button_event,this.play.bind(this,[this.interval,'next',false])); break;
				case 'playback': buttons[i].observe(this.button_event,this.play.bind(this,[this.interval,'previous',false])); break;
				case 'stop': buttons[i].observe(this.button_event,this.stop.bind(this)); break;
			}
			this.buttons[action].push(buttons[i]);
		}
	},

	previous: function(manual){
		if (this.stopOnFirstItem) {
			var boxOffset = this.box.cumulativeOffset();
			var maskOffset = this.mask.cumulativeOffset();
			
			if (this.mode == 'horizontal') {
				// TODO
			} else {
				var boxTop = boxOffset.top;
				var maskTop = maskOffset.top;
				
				if (maskTop > boxTop) {
					this.walk((this.currentIndex > 0 ? this.currentIndex - 1 : this.items.length - 1), manual, false, 'previous');
				}
			}
			
		} else {
			this.walk((this.currentIndex > 0 ? this.currentIndex - 1 : this.items.length - 1), manual, false, 'previous');
		}
	},

	next: function(manual) {
		if (this.stopOnLastItem) {
			var boxOffset = this.box.cumulativeOffset();
			var maskOffset = this.mask.cumulativeOffset();
			
			if (this.mode == 'horizontal') {
				// TODO
			} else {
				var boxBottom = this.box.getHeight() + boxOffset.top;
				var maskBottom = this.mask.getHeight() + maskOffset.top;
				
				if (maskBottom < boxBottom) {
					if (this.partialWalk) {
						this.walk((this.currentIndex <= this.items.length - 1 ? this.currentIndex + 1 : 0), manual, false, 'next');
					} else {
						this.walk((this.currentIndex < this.items.length - 1 ? this.currentIndex + 1 : 0), manual, false, 'next');
					}
				}
			}
			
		} else if (this.partialWalk) {
			this.walk((this.currentIndex <= this.items.length - 1 ? this.currentIndex + 1 : 0), manual, false, 'next');
		} else {
			this.walk((this.currentIndex < this.items.length - 1 ? this.currentIndex + 1 : 0), manual, false, 'next');
		}
	},

	handler: function(index) {
		this.walk(index, true, false, 'handler');
	},

	play: function(context) {
		var interval = context[0];
		var direction = context[1];
		var wait = context[2];

		if (this.playDirection == null) {

			// console.debug('play ' + this.playDirection + " " + direction);

			this.playDirection = direction;
			this.stop();
			if (!wait) {
				this[direction](false);
			}

			this._play = new PeriodicalExecuter(this[direction].bind(this), 1.5);
		} else {
			// console.debug('skip');
		}
	},

	stop: function() {
		if (this._play) {
			this._play.stop();
			this.playDirection = null;
			// console.debug('set null');
		}
	},

	getCurrentIndex: function() {
		return this.currentIndex;
	},

	getItemsSize: function(){
		return this.items.length;
	},

	getNextIndex: function(){
		var currentIndex = this.currentIndex;
		return currentIndex < (parseInt(this.items.length) - 1) ? (parseInt(currentIndex) + 1) : 0;
	},

	getPreviousIndex: function(){
		var currentIndex = this.currentIndex;
		return currentIndex > 0 ? (parseInt(currentIndex) - 1) : this.items.length - 1;
	},
	
	afterUpdate: function(direction) {
	},

	walk: function(item, manual, noFx, direction) {
		var currentIndexOld = this.currentIndex;
		if (item != this.currentIndex && Effect.Queues.get('ticker').size() == 0) {
			this.currentIndex = item;
			this.previousIndex = this.currentIndex + (this.currentIndex > 0 ? -1 : this.items.length - 1);
			this.nextIndex = this.currentIndex + (this.currentIndex < this.items.length - 1 ? 1 : 1 - this.items.length);
			if (manual) {
				// this.stop();
			}
			if (noFx) {
				// this.fx.cancel().set((this.size *- this.currentIndex) + 'px');
			} else {
				// alert('prev: ' + this.previousIndex + ' current: ' + this.currentIndex + ' next: ' + this.nextIndex);

				var deltaMove = 0;

				if (direction == 'next') {
					if (this.currentIndex == 0 && this.previousIndex > this.currentIndex) {
						deltaMove = (this.size * this.previousIndex);
					} else {
						deltaMove = -this.size;
					}
				} else if (direction == 'previous') {
					if (this.currentIndex == this.items.length - 1 && this.currentIndex > this.nextIndex) {
						deltaMove = - (this.size * this.currentIndex);
					} else {
						deltaMove = this.size;
					}
				} else if (direction = 'handler') {
					deltaMove = this.size * (currentIndexOld - this.currentIndex);
				}

				if (this.mode == 'horizontal') {
					new Effect.Move(this.box, {
						x: deltaMove,
						y: 0,
						queue: {
							position: 'end',
							limit: this.walkLimit,
							scope: 'ticker'
						}
					});
				} else if (this.mode == 'vertical') {
					new Effect.Move(this.box, {
						x: 0,
						y: deltaMove,
						queue: {
							position: 'end',
							limit: this.walkLimit,
							scope: 'ticker'
						}
					});
				}
				
				if (this.onWalk) {
					this.onWalk.bind(this);
					this.onWalk(this.currentIndex, this.items.length, direction);
				}	

			}
			
			if (manual && this.autoPlay) {
				this.play(this.interval, 'next', true);
			}
			
		}
	}

};