var Slyder = Class.create({
	initialize: function(element, options) {
		// options
		this.options = {
			autoPageBreaks: true,
			autoCenter:     false,
			showArrows:     true,
			showNav:        true,
			continuous:     false
		};
		if (options) Object.extend(this.options, options);

		// dom
		this.element = $(element);
		if (!this.element) return false;

		this.mask = this.element.down('.mask');
		this.container = this.element.down('.container');
		this.pageWidth = this.mask.getWidth();
		this.pages = $A();
		this.page = 0;
		this.nav = new Slyder.Nav(this);

		// setup pages and items
		var itemElements = this.container.childElements(),
			currentPage;

		itemElements.each(function(element) {
			var item = new Slyder.Item(this, element);

			// new page?
			if (!currentPage || item.pagebreak || !currentPage.willFit(item)) {
				if (currentPage && (this.options.autoPageBreaks || item.pagebreak)) {
					if (this.options.autoCenter) currentPage.center();
					else currentPage.addPageBreak();
				}

				var pos = currentPage ? (currentPage.pos + currentPage.width) : 0;
				currentPage = new Slyder.Page(this, pos);
				this.pages.push(currentPage);
			}
			currentPage.addItem(item);
		}.bind(this));

		// center the last page?
		if (this.options.autoCenter) currentPage.center();
		else currentPage.addPageBreak();

		// set container width
		this.container.setStyle({width: (this.pages.length * this.pageWidth)+'px'});

		// render nav?
		if (this.pages.length > 1) {
			this.nav.render();
		}

		var current = this.container.down('.active');
		if (current) this.slideTo(this.belongsToPage(current));
		else this.slideTo(0);
	},
	pos: function() {
		return parseInt(this.container.getStyle('left'));
	},
	slideTo: function(page, num) {
		if (page < 0) {
			this.page = this.pages.length-1;
		}
		else if (page > this.pages.length-1) {
			this.page = 0;
		}
		else {
			this.page = page;
		}

		// activate nav item
		this.pages[this.page].navItem.activate();

		// stop previous effect
		if (this.effect && this.effect.state == 'running') {
			this.effect.cancel();
		}

		// slide item container
		this.effect = new Effect.Move(this.container, {
			duration: .5,
			x: -this.pages[this.page].pos,
			mode: 'absolute'
		});

		// deactivate an arrow?
		if (!this.options.continuous) {
			if (this.page > 0) {
				this.nav.leftArrow.enable();
			} else {
				this.nav.leftArrow.disable();
			}
			if (this.page < this.pages.length-1) {
				this.nav.rightArrow.enable();
			} else {
				this.nav.rightArrow.disable();
			}
		}
	},
	belongsToPage: function(element) {
		return Math.floor(element.offsetLeft/this.pageWidth);
	}
});

Slyder.Page = Class.create({
	initialize: function(slider, pos) {
		this.slider = slider;
		this.pos = pos;
		this.num = this.slider.pages.length;
		this.width = 0;
		this.navItem = this.slider.nav.addItem(this);
		this.items = $A();
	},
	willFit: function(item) {
		return ((this.width + item.elementWidth) <= this.slider.pageWidth);
	},
	addItem: function(item) {
		this.items.push(item);
		this.width += item.width;
	},
	center: function() {
		var firstItem = this.items[0],
			lastItem = this.items.last(),
			width = this.width - firstItem.getMargin('Left') - lastItem.getMargin('Right'),
			margin = (this.slider.pageWidth - width) / 2;
		firstItem.setMargin('Left', margin)
		lastItem.setMargin('Right', margin);
		this.width = this.slider.pageWidth;
	},
	addPageBreak: function() {
		var lastItem = this.items.last(),
			width = this.width - lastItem.getMargin('Right');
		lastItem.setMargin('Right', this.slider.pageWidth - width);
		this.width = this.slider.pageWidth;
	}
})

Slyder.Item = Class.create({
	initialize: function(slider, element) {
		this.slider = slider;
		this.element = $(element);

		this.pagebreak = this.element.hasClassName('pagebreak');

		this.elementWidth = parseInt(this.element.getWidth());
		this.width = this.elementWidth
		           + ((marginLeft  = this.element.getStyle('marginLeft'))  ? parseInt(marginLeft)  : 0)
		           + ((marginRight = this.element.getStyle('marginRight')) ? parseInt(marginRight) : 0);
	},
	getMargin: function(which) {
		return (margin = this.element.getStyle('margin'+which)) ? parseInt(margin) : 0;
	},
	setMargin: function(which, margin) {
		this.element.style['margin'+which] = margin+'px';
	}
});

Slyder.Nav = Class.create({
	initialize: function(slider) {
		this.slider = slider;
		this.items = $A(0);
	},
	addItem: function(page) {
		var item = new Slyder.Nav.Item(this, page);
		this.items.push(item);
		return item;
	},
	render: function() {
		if (this.slider.options.showNav) {
			this.element = new Element('div', {'class': 'nav'});
			this.slider.element.insert(this.element);
			this.items.invoke('render');
		}

		if (this.slider.options.showArrows) {
			this.leftArrow = new Slyder.Nav.Arrow(this, -1);
			this.rightArrow = new Slyder.Nav.Arrow(this, 1);
		}
	}
});

Slyder.Nav.Item = Class.create({
	initialize: function(nav, page) {
		this.nav = nav;
		this.slider = this.nav.slider;
		this.page = page;
		this.num = this.page.num;
	},
	render: function() {
		this.element = new Element('a', {title: 'Scroll to page '+(this.num+1)});
		this.nav.element.insert(this.element);
		this.element.observe('click', this.onClick.bind(this));
		if (this.nav.activeItem == this) this.activate();
	},
	onClick: function() {
		this.slider.slideTo(this.page.num, this.num);
	},
	activate: function() {
		if (this.nav.activeItem) {
			this.nav.activeItem.deactivate();
		}
		this.nav.activeItem = this;
		if (this.element) this.element.addClassName('active');
	},
	deactivate: function() {
		if (this.element) this.element.removeClassName('active');
	}
});

Slyder.Nav.Arrow = Class.create({
	initialize: function(nav, dir) {
		this.nav = nav;
		this.slider = this.nav.slider;
		this.dir = dir;
		this.enabled = true;

		var c = (dir == 1) ? 'right' : 'left';
		this.element = new Element('a', {'class': 'arrow '+c, title: 'Scroll '+c});
		this.slider.element.insert(this.element);
		this.element.observe('click', this.onClick.bind(this));
	},
	onClick: function() {
		if (this.enabled) {
			this.slider.slideTo(this.slider.page + this.dir);
		}
	},
	enable: function() {
		if (!this.enabled) {
			this.enabled = true;
			this.element.removeClassName('disabled')
		};
	},
	disable: function() {
		if (this.enabled) {
			this.enabled = false;
			this.element.addClassName('disabled');
		}
	}
});

