var vertical_scroller = new Class({
    Implements: [Options, Events],
    options: {
        slide_holder: '',		// Holder element which holds the content to slide
        slide_holder_parent: '',// parent element holding the slider (to inject controls into)
        content_elements: [],	// Content elements to slide
        slider_w: 0,		// Holder element width
        slider_h: 0,			// Holder element height
        total_content_h: 0,		// Total width of the content in the holder
        content_elements_h: 0,	// width of a content element
        wrap_div: '',			// Div wrapped around the holder content
        controls: false,		// PREV EN NEXT BUTTONS ?
        next_but: '',			// Slide to left button
        prev_but: '',			// Slide to right button
        slide_per_item: true,	// slide per item, or slide per viewport width
        slidespeed: 500,		// Animation speed,
        scroll_next_speed: 2000,	// Show next items speed,
        active_class: 'active',	// class of the content item which is active i.e. should be visible in the holder viewport
        cover_div_class: 'cover_div'
    },
    initialize: function(options){
        this.setOptions(options);
        this.get_holder_dims(this.options.slide_holder);
    },
	// Get the width of the Holder element
	get_holder_dims: function(content_holder) {
		this.options.slider_w =  content_holder.getStyle('width').toInt();
		this.options.slider_h =  content_holder.getStyle('height').toInt();
		this.options.slide_holder_parent = this.options.slide_holder.getParent()
        this.get_content_slides(this.options.slide_holder, this.options.content_elements);
	},
	// Get the Holder element's children i.e. the content_elements
	// Calculate total height of his content
	get_content_slides: function(content_holder, content_elements) {
		if(content_elements.length==0) {
			this.options.content_elements = content_holder.getChildren();
		}
		var total_content_h = 0;
		var content_slider = this;
		var slider_options = this.options;
		var element_width;
		var element_heights = [];
		this.options.content_elements.each(function(content_element, index) {
			var element_dims = content_element.getSize();
			var element_margin_left = content_element.getStyle('margin-left').toInt();
			var element_margin_right = content_element.getStyle('margin-right').toInt();
			element_width = element_dims.x.toInt() + element_margin_left +element_margin_right;
			element_height = element_dims.y.toInt() + content_element.getStyle('margin-bottom').toInt()+ content_element.getStyle('margin-top').toInt();
			element_heights[index] = element_height;
			// Store the left position of each element, in case it needs to be wrapped
			content_element.store('pos_top', total_content_h);
			total_content_h = total_content_h + element_height;
			// active element ?
			if(content_element.hasClass(slider_options.active_class)) {
				content_slider.active_element = content_element;
			}
		});
		this.options.content_elements_h = element_height;
		if(this.options.slide_per_item==false) {
			this.slide_increment = this.options.slider_h;
		} else {
			this.slide_increment = this.options.content_elements_h;
		}
		this.options.total_content_h = total_content_h;
		if(this.options.total_content_h>this.options.slider_h) {
			this.wrap_slide_content();
		}
		// this.set_slider_height(element_heights);
	},
	// SET SLIDER HEIGHT
	/*
	set_slider_height: function(element_heights) {
		var max_h = 0;
		element_heights.each(function(element_height) {
			if(element_height>max_h) { max_h = element_height; }
		});
		this.options.slider_h = max_h;
		this.options.slide_holder.setStyle('min-height', max_h);
	},
	reset_slider_height: function(new_height) {
		var height_to_set = this.options.slider_h;
		this.options.content_elements.each(function(content_element, index) {
			var element_dims = content_element.getSize();
			var this_el_h = element_dims.y.toInt() + content_element.getStyle('margin-bottom').toInt();
			if(this_el_h>height_to_set) {
				height_to_set = this_el_h;
			}
		});
		this.options.slide_holder.setStyle('min-height', height_to_set);
		//alert('new_height = '+new_height);
	},
	*/
	// The content is larger than the holder, 
	// so it needs to be wrapped by an element with the size of the total content width
	wrap_slide_content: function () {
		this.slider_position = this.options.slide_holder.getCoordinates(this.options.slide_holder_parent); 
	
		// this.options.slide_holder.setStyle('width', this.options.slider_h-1); // compensate drop shadow left-overs..
		var wrapper_div = new Element('div', {
		    'class': 'slide_content_wrapper',
		    styles: {
		        position: 'absolute',
		        top: 0,
		        left: 0,
		        height: this.options.total_content_h
		    }
		});
		this.options.wrap_div = wrapper_div;
		wrapper_div.inject(this.options.slide_holder);
		this.options.content_elements.inject(wrapper_div);
		
		// MAKE PARENT DIV RELATIVE
		if(this.options.slide_holder_parent.getStyle('position')=='static') {
			this.options.slide_holder_parent.setStyle('position', 'relative');
		}
		
		this.insert_cover_div();
		this.position_slides();
		if(this.options.controls==true) {
			this.set_prev_next_buttons();
		} else {
			this.set_scroll_timer();
		}
	},
	insert_cover_div: function() {
		var top_cover_div = new Element('div', {
		    'class': this.options.cover_div_class+' top_cover',
		    styles: {
		        position: 'absolute',
		        top: this.slider_position.top,
		        left: this.slider_position.left
		    }
		});
		var bottom_cover_div = new Element('div', {
		    'class': this.options.cover_div_class+' bottom_cover',
		    styles: {
		        position: 'absolute',
		        top: this.slider_position.top + this.options.slider_h - 5,
		        left: this.slider_position.left
		    }
		});
		top_cover_div.inject(this.options.slide_holder_parent);		
		bottom_cover_div.inject(this.options.slide_holder_parent);		
	},
	// Take all content elements and position them absolute, with the right left value, stored earlier
	position_slides: function() {
		this.options.content_elements.each(function(content_element) {
			content_element.setStyles({
				position: 'absolute',
				top: content_element.retrieve('pos_top'),
				left: 0
			});
		});
	},
	// Insert previous and next slide buttons
	set_prev_next_buttons: function() {
		// These buttons need to be outside the holder div, since it's overflow is hidden
		// Get the position of the holder div, to position the buttons relative to the holder
		var slider_position = this.slider_position; 
		// Create the next button, this will be visible 
		var next_button = new Element('a', {
		    href: '#slide_right',
		    'class': 'item_slider_control next',
		    html: '&gt;',
		    styles: {
		        display: 'block',
		        top: this.slider_position.top + 10,
		        left: this.slider_position.left + this.options.slider_h + 0
		    },
		    events: {
		        click: function(){
		            return false;
		        }
		    }
		});
        next_button.addEvent('click', this.slide_content.bind(this));
		// Create the prev button, this will be invisible, because the slider starts at 0
		var prev_button = new Element('a', {
		    href: '#slide_left',
		    'class': 'item_slider_control prev',
		    html: '&lt;',
		    styles: {
		        display: 'none',
		        top: this.slider_position.top + 10,
		        left: this.slider_position.left - 50
		    },
		    events: {
		        click: function(){
		            return false;
		        }
		    }
		});
        prev_button.addEvent('click', this.slide_content.bind(this));
		// INJECT the prev/next buttons to the holder's parent element
		next_button.inject(this.options.slide_holder_parent);
		prev_button.inject(this.options.slide_holder_parent);
		this.options.next_but = next_button;
		this.options.prev_but = prev_button;
		if(typeof this.active_element!='undefined') {
			this.set_active_position();
		}
	},
	// Slide the content inside the holder, get the direction by the class of the button
	slide_content: function(event) {
		var cur_content_pos = this.options.wrap_div.getStyle('top').toInt();
		var next_pos = cur_content_pos - this.slide_increment; // this.options.slider_h;
		if((typeof event!='undefined') && (event.target.hasClass('prev'))) {
			next_pos = cur_content_pos + this.slide_increment; // this.options.slider_h;		
		}
		// output('next_pos = '+Math.abs(next_pos)+' en total_height = '+this.options.total_content_h);
		if(Math.abs(next_pos) >= this.options.total_content_h) { next_pos = 0; } 
		
		var content_slide_FX = new Fx.Tween(this.options.wrap_div, {property: 'top', duration: this.options.slidespeed});
		// Start the slide animation and update the visibility of the prev/next buttons
		if(this.options.controls==true) {
			content_slide_FX.start(cur_content_pos,next_pos).chain(function(){ 
				this.update_controls(next_pos); 
				}.bind(this)
			);		
		} else {
			content_slide_FX.start(cur_content_pos,next_pos).chain(function(){ 
				this.set_scroll_timer(); 
				}.bind(this)
			);		
		}
	},
	set_scroll_timer: function() {
		if(typeof this.scroll_delay=='undefined') {
			this.scroll_delay = '';
		} else {
			clearTimeout(this.scroll_delay);
		}
		this.scroll_delay = this.slide_content.delay(this.options.scroll_next_speed, this);
	},
	// Set the visibility of the prev/next buttons
	update_controls: function(cur_content_pos) {
		// SHOW PREV -> is visible when the wrap div position is negative
		if(cur_content_pos<0) {
			this.options.prev_but.setStyle('display', 'block');
		}
		// HIDE PREV -> is invisible when the wrap div position is 0
		if(cur_content_pos==0) {
			this.options.prev_but.setStyle('display', 'none');
		}
		// HIDE NEXT -> is invisible when the last content element is visible in the holder's viewport
		if((-1*(cur_content_pos - this.options.slider_h))>=this.options.total_content_h) {
			this.options.next_but.setStyle('display', 'none');
		}
		// SHOW NEXT -> is visible when the last content element is not visible in the holder's viewport
		if(this.options.total_content_h>(-1*(cur_content_pos - this.options.slider_h))) {
			this.options.next_but.setStyle('display', 'block');
		}
	},
	// When one of the content slides is an active item and must be visible onload, 
	// set the slider to the position in which the active item is visible
	set_active_position: function() {
		var active_item_pos = this.active_element.getStyle('left').toInt();
		if(active_item_pos>=this.options.slider_h) {
			var num_steps = Math.floor(active_item_pos / this.options.slider_h);
			var position_to_set =  -1*(num_steps * this.options.slider_h);
			this.options.wrap_div.setStyle('left', position_to_set);
			this.update_controls(position_to_set);
		}
	}
});
