var content_slider = new Class({
    Implements: [Options, Events],
    options: {
        slide_holder: '',		// Holder element which holds the content to slide
        content_elements: [],	// Content elements to slide
        slider_width: 0,		// Holder element width
        slider_h: 0,			// Holder element height
        content_width: 0,		// Total width of the content in the holder
        content_elements_w: 0,	// width of a content element
        wrap_div: '',			// Div wrapped around the holder content
        next_but: '',			// Slide to left button
        prev_but: '',			// Slide to right button
        slide_per_item: false,	// slide per item, or slide per viewport width
        slidespeed: 500,		// Animation speed,
        active_class: 'active',	// class of the content item which is active i.e. should be visible in the holder viewport
        shadow_size: 4			// size of IE filter.shadow (needs to be compensated in elements width...) fuck IE.
    },
    initialize: function(options){
        this.setOptions(options);
		this.sliding_content = false;
        this.get_holder_dims(this.options.slide_holder);
    },
	// Get the width of the Holder element
	get_holder_dims: function(content_holder) {
		var cur_holder_w = content_holder.getStyle('width').toInt();
		this.options.slider_width = cur_holder_w; 
        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 width 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_w = 0;
		var content_slider = this;
		var slider_options = this.options;
		var element_width;
		var element_heights = [];
		var ie_shadow_filter_compensation = 0; // if items have a shadow_filter
		if(in_ie_hell==true) {
			ie_shadow_filter_compensation = -1*(this.options.shadow_size);
		}
		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 + ie_shadow_filter_compensation;
			element_heights[index] = element_dims.y.toInt() + content_element.getStyle('margin-bottom').toInt();
			// Store the left position of each element, in case it needs to be wrapped
			content_element.store('pos_left', total_content_w);
			total_content_w = total_content_w + element_width;
			// active element ?
			if(content_element.hasClass(slider_options.active_class)) {
				content_slider.active_element = content_element;
			}
		});
		this.options.content_elements_w = element_width;
		if(this.options.slide_per_item==false) {
			this.slide_increment = this.options.slider_width;
		} else {
			this.slide_increment = this.options.content_elements_w;
		}
		this.options.content_width = total_content_w;
		if(this.options.content_width>this.options.slider_width) {
			this.wrap_slide_content();
		} else {
			this.options.slide_holder.addClass('NO_sliding_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('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('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.options.slide_holder.addClass('sliding_content');
		this.slider_parent = this.options.slide_holder.getParent();
		this.options.slide_holder.setStyle('width', this.options.slider_width-1); // compensate drop shadow left-overs..
	
		var wrapper_div = new Element('div', {
		    'class': 'slide_content_wrapper',
		    styles: {
		        position: 'absolute',
		        top: 0,
		        left: 0,
		        width: this.options.content_width
		    }
		});
		this.wrap_div = wrapper_div;
		wrapper_div.inject(this.options.slide_holder);
		this.options.content_elements.inject(wrapper_div);
		
		this.position_slides();
		this.set_prev_next_buttons();
	},
	// 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: 0,
				left: content_element.retrieve('pos_left')
			});
		});
	},
	// 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.options.slide_holder.getCoordinates(this.slider_parent); 
		// CHECK PARENT POSITION, if static set to relative
		if(this.slider_parent.getStyle('position')=='static') {
			this.slider_parent.setStyle('position', 'relative');
		}
		
		// 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: slider_position.top + 10,
		        left: slider_position.left + this.options.slider_width + 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: slider_position.top + 10,
		        left: 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.slider_parent);
		prev_button.inject(this.slider_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) {
		if(this.sliding_content==false) {
			this.sliding_content = true;
			var cur_content_pos = this.wrap_div.getStyle('left').toInt();
			var next_pos = cur_content_pos - this.slide_increment; // this.options.slider_width;
			if((typeof event!='undefined') && (event.target.hasClass('prev'))) {
				next_pos = cur_content_pos + this.slide_increment; // this.options.slider_width;		
			}
			var content_slide_FX = new Fx.Tween(this.wrap_div, {property: 'left', duration: this.options.slidespeed});
			// Start the slide animation and update the visibility of the prev/next buttons
			content_slide_FX.start(cur_content_pos,next_pos).chain(function(){ this.update_controls(next_pos); }.bind(this));
		}
	},
	// Set the visibility of the prev/next buttons
	update_controls: function(cur_content_pos) {
		this.sliding_content = false;
		// 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_width))>=this.options.content_width) {
			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.content_width>(-1*(cur_content_pos - this.options.slider_width))) {
			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_width) {
			output('active_item_pos = '+active_item_pos+' | slider_width = '+this.options.slider_width)
			var num_steps = Math.floor(active_item_pos / this.options.slider_width);
			var position_to_set =  -1*(num_steps * this.options.slider_width);
			this.wrap_div.setStyle('left', position_to_set);
			this.update_controls(position_to_set);
		}
	}
});
