Effect.SmoothSliderSetValue = Class.create(Effect.Base, {
	initialize: function(element) {
		this.element = element;
		if (!this.element) throw(Effect._elementDoesNotExistError);
		var options = Object.extend({
			from: 0,
			to: 0,
			duration: 1.0
		}, arguments[1] || { });
		this.factor = 1/(options.to-options.from);
		this.start(options);
	},
	update: function(position) {
		this.element.setValue(position);
	}
});

var ProductOverviewThumbSlider = Class.create({

	log: function(str) {
		if (!Object.isUndefined(site)) { site.log("ProductOverviewThumbSlider: "+str); }
	},
	
	initialize: function(options) {
		this.options = Object.extend({
			horizontalSwitchElement:		'gohorizontal',
			verticalSwitchElement:			'govertical',
			containerElement:				'productoverview',
			windowContainerElement:			'productblockcontainer',
			windowWidthSlack:				undefined,			// Width of right-most visible window margin that should be skipped
			sourceContainerElement:			'productblocks_source',
			destinationContainerElement:	'productblocks',
			horizontalRows:					3,
			sliderButtonLeft:				'sliderbuttonleft',
			sliderButtonRight:				'sliderbuttonright',
			slidertrackElement:				'slidertrack',
			columnWidths:					{
												'wide':	232+39,
												'tall':	120+11
											},
			minSliderWidth:					63
		}, options || {});

		this.columnWidthsHash = new Hash(this.options.columnWidths);

		this.mousedown = false;

		this.leftElement = $(this.options.sliderButtonLeft);
		this.rightElement = $(this.options.sliderButtonRight);

		this.source = $(this.options.sourceContainerElement);
		this.destination = $(this.options.destinationContainerElement);
		this.destinationClassName = this.destination.className;

		this.containerElement = $(this.options.containerElement);
		this.window = $(this.options.windowContainerElement);
		this.windowWidth = this.window.getWidth();

		this.windowWidthSlack = this.options.windowWidthSlack;
		if (this.windowWidthSlack===undefined) {
			if (this.containerElement.hasClassName('wide_only')) { this.windowWidthSlack = 39; }
			else if (this.containerElement.hasClassName('tall_only')) { this.windowWidthSlack = 11; }
			else { this.windowWidthSlack = 0; }
			this.log('Window Width Slack: '+this.windowWidthSlack);
		}

		this.slidertrack = $(this.options.slidertrackElement);
		this.slidertrackWidth = this.slidertrack.getStyle('width').gsub(/px$/,'');

		// Set options
		this.options.sliderStepWidth = this.windowWidth + this.windowWidthSlack;

		this.log('Slider Step Width: '+this.options.sliderStepWidth);

		this.sliderBlock = ($$('.sliderblock')).first();
		this.sliderhandle = $('sliderhandle');

		this.leftElement.observe('click',this.sliderButtonLeft.bindAsEventListener(this));
		this.rightElement.observe('click',this.sliderButtonRight.bindAsEventListener(this));
		this.updateButtons();

		this.onePageOnly = this.getOnePageOnly();

		// Enough elements to require a slider?
		if (this.onePageOnly) {
			this.log('One page only.');
			
			// Hide mode text + icons
			$$('.modetext').each( function(element){ element.hide(); } );
			$('gohorizontal').hide();
			$('govertical').hide();
			
			// Go Vertical - but without changing cookie
			this.selectMode('vertical',false);
		} else {

			// Mode buttons
			this.log("Observing buttons..");
			$(this.options.horizontalSwitchElement).observe('click',this.modeClick.bindAsEventListener(this,'horizontal'));
			$(this.options.verticalSwitchElement).observe('click',this.modeClick.bindAsEventListener(this,'vertical'));
			this.selectMode(CodeCompany.Cookie.read('productoverview_mode'),false);
		}


		this.log("Initialized.");
	},

	getOnePageOnly: function() {
		var result = this.buildMode('horizontal');
		return (result.width <= (this.windowWidth+this.windowWidthSlack+10)); // Allow 10 pixels error margin
	},

	setSliderValue: function(value) {
		if (value<0) { value=0; }
		if (value>1) { value=1; }
		var oldvalue = this.sliderControl.value;
		if (value==oldvalue) { return; }

		this.updateButtons(value);
		
		if (this.smoothEffect) {
			this.smoothEffect.cancel();
		}
		this.moveWindow(oldvalue);
		this.smoothEffect = new Effect.SmoothSliderSetValue(this.sliderControl,{
			from: oldvalue,
			to: value
		});
	},

	setEnabledClass: function(element,enabled) {
		if (enabled) {
			element.removeClassName('disabled').addClassName('enabled');
		} else {
			element.removeClassName('enabled').addClassName('disabled');
		}
	},

	updateButtons: function(value) {
		if (value===undefined) { value=this.sliderLastValue; }
		this.setEnabledClass(this.leftElement, value>0);
		this.setEnabledClass(this.rightElement, value<1);
	},

	sliderButtonLeft: function() {
		this.setSliderValue((this.sliderLastOffset - this.options.sliderStepWidth)/this.sliderFactor);
	},

	sliderButtonRight: function() {
		this.setSliderValue((this.sliderLastOffset + this.options.sliderStepWidth)/this.sliderFactor);
	},

	sliderChange: function(value) {
		this.moveWindow(value);
	},

	sliderScroll: function(value) {
		this.moveWindow(value);
		this.updateButtons(value);
	},

	moveWindow: function(value) {
		var offset = Math.floor(value*this.sliderFactor);
		if (offset==this.sliderLastOffset) { return; }
		this.sliderLastOffset = offset;
		this.sliderLastValue = value;
		this.destination.style.left = '-'+offset+'px';
	},

	modeClick: function(event,mode) {
		this.log('Mode Click: '+mode);
		this.selectMode(mode,true);
	},

	getElementWidthName: function(element) {
		var childElement = element.down('div').down('div');
		if (childElement.hasClassName('productblock_wide')) { return 'wide'; }
		if (childElement.hasClassName('productblock_tall')) { return 'tall'; }
	},

	getColumnWidth: function(widthName) {
		var width = this.columnWidthsHash.get(widthName);
		return width;
	},

	buildMode: function(mode) {
		var result = {
			'html': '',
			'width': 0
		};

		if (mode=='vertical') {
			this.source.childElements().each(function(element){
				result.html += element.innerHTML;
			},this);
			result.width = this.windowWidth + this.windowWidthSlack;
		}
		else {
			var rows = 0;
			var columnTemplate = '<div class="column column_#{width}">#{html}</div>'; // Not a real template
			var columnWidthName = 'unknown';
			var columnHtml = '';

			this.source.childElements().each(function(element){
				if (rows===0) {
					columnWidth = 'unknown';
					columnHtml = '';
				}

				var elementWidthName = this.getElementWidthName(element);
				if ((columnWidthName=='unknown') || (columnWidthName=='tall')) {
					columnWidthName = elementWidthName;
				}

				columnHtml += element.innerHTML;
				rows++;

				if (rows==this.options.horizontalRows) {
					rows = 0;
					result.html += columnTemplate.replace('#{width}',columnWidthName).replace('#{html}',columnHtml);
					result.width += this.getColumnWidth(columnWidthName);
				}
			},this);

			if (rows) {
				result.html += columnTemplate.replace('#{width}',columnWidthName).replace('#{html}',columnHtml);
				result.width += this.getColumnWidth(columnWidthName);
			}
		}

		return result;
	},

	selectMode: function(mode,saveCookie) {
		this.log("Selecting mode: "+mode);

		if (saveCookie===true) { CodeCompany.Cookie.write('productoverview_mode',mode); }

		result = this.buildMode(mode);
		
		// Vertical mode
		if (mode=="vertical") {
			// Set class
			this.containerElement.removeClassName('horizontal');
			this.containerElement.addClassName('vertical');

			// No slider, thanks
			this.sliderBlock.hide();

			// Make sure we haven't moved the sliding window
			this.destination.setStyle({
				'left': '',
				'width': ''
			});

		}
		// Horizontal Mode
		else {
			// Set class
			this.containerElement.removeClassName('vertical');
			this.containerElement.addClassName('horizontal');
			// Slider visible?
			if (!this.onePageOnly) {

				// Do some calculation on slider width
				var sliderWidth = Math.max(
					this.options.minSliderWidth,
					Math.min(
						this.slidertrackWidth,
						Math.floor(
							this.slidertrackWidth * (this.windowWidth / result.width)
						)
					)
				);
				this.sliderhandle.setStyle({
					'width':	''+sliderWidth+'px'
				});
				
				this.sliderLastOffset = 0;
				this.sliderLastValue = 0;

				this.sliderFactor = result.width - this.windowWidthSlack - this.windowWidth;
				if (this.sliderFactor<0) { this.sliderFactor = 0; }

				this.log('slidertrackWidth='+this.slidertrackWidth+', sliderWidth='+sliderWidth+', sliderFactor='+this.sliderFactor);

				this.sliderhandle.observe('mousedown',this.onSliderMouseDown.bindAsEventListener(this));
				document.observe('mouseup',this.onSliderMouseUp.bindAsEventListener(this));

				this.sliderBlock.show();

				(function(){
					this.log('Showing slider..');
					// Set up slider
					this.sliderControl = new Control.Slider(this.sliderhandle,this.slidertrack,{
						axis: 'horizontal',
						onSlide: this.sliderScroll.bind(this),
						onChange: this.sliderChange.bind(this)
					});
					this.sliderControl.setValue(0);
					this.updateButtons();
					this.log('Showing slider done..');
					// Set up slider
				}).bind(this).defer();

			}
		}

		this.destination.style.width = (result.width+100)+'px'; // Make sure there's plenty of room
		this.destination.update(result.html);

		new HoverSiblings([this.destination.id],{siblingElementSelector:".productblock"});

		if (Prototype.Browser.IE && (navigator.userAgent.match(/MSIE 7/)!==null)) {
			this.log("IE7 requires manual triggering of windowResizer.resize()");
			(function(){
				if ((undefined===windowResizer) || (Object.isUndefined(windowResizer))) {
					this.log("Unable to call windowResizer.resize() - object not initialized");
					return;
				}
				windowResizer.resize();
			}).bind(this).defer();
		}


	},

	onSliderMouseDown: function(e) {
		if (this.mousedown) { return; }
		if (this.slidertrack!==undefined) { this.slidertrack.addClassName('mousedown'); }
		this.mousedown = true;
	},

	onSliderMouseUp: function(e) {
		if (!this.mousedown) { return; }
		if (this.slidertrack!==undefined) { this.slidertrack.removeClassName('mousedown'); }
		this.mousedown = false;
	}
		
});	

