/* Add rounded corners */
var RoundedCorners = {
	topCorners: [ '#pregnancy-timeline div.week h2' ],
	bottomCorners: [ '#pregnancy-timeline div.week div.panel.you' ],
	fourCorners: [ '#pregnancy-timeline div.week div.panel.baby', '#pregnancy-timeline div.week div.panel.screening' ],
	
	init: function() {
		this.insertTopCorners();
		this.insertBottomCorners();
		this.insertFourCorners();
	},
	
	insertTopCorners: function() {
		this.topCorners.each(function(selector) {
			$$(selector).each(function(elm) {
				elm.insert('<span class="corner tl"></span><span class="corner tr"></span>');
			});
		});
	},
	
	insertBottomCorners: function() {
		this.bottomCorners.each(function(selector) {
			$$(selector).each(function(elm) {
				elm.insert('<span class="corner bl"></span><span class="corner br"></span>');
			});
		});
	},
	
	insertFourCorners: function() {
		this.fourCorners.each(function(selector) {
			$$(selector).each(function(elm) {
				elm.insert('<span class="corner tl"></span><span class="corner tr"></span><span class="corner bl"></span><span class="corner br"></span>');
			});
		});
	}
};

/*  */
var Timeline = {
	MAX_INNER_HEIGHT: null,
		
	timelineId: 'pregnancy-timeline',
	timelineContainerSel: '#pregnancy-timeline div.container',
	innerContainerSel: '#pregnancy-timeline div.container div.inner-container',
	weekHolderSel: '#pregnancy-timeline div.weeks-holder',
	innerInnerId: 'inner-inner',
	navLinkSel: '#pregnancy-timeline div.navigation ul li a',
	selectedNavLinkSel: '#pregnancy-timeline div.navigation ul li a.selected',
	sliderId: 'slider',
	scrollerId: 'scroll-handle',
	inputWeeksId: 'input-weeks',
	inputErrorId: 'input-error',
	
	scroller: null,
	currentWeeks: null,
		
	swapping: false, // mutex
		
	init: function() {
		$(this.timelineId).addClassName('js');
		this.MAX_INNER_HEIGHT = $(this.innerInnerId).getHeight();
		this.hideAllWeeks();
		this.showFirstWeek();
		this.createNavLinkEvents();
		this.createScroller();
		this.resetScroller();
		this.createForm();
	},
	
	hideAllWeeks: function() {
		$$(this.weekHolderSel).each(function(elm) {
			elm.hide();
		});
	},
	
	showFirstWeek: function() {
		this.currentWeeks = $$(this.weekHolderSel)[0];
		this.currentWeeks.show();
		$$(this.navLinkSel)[0].addClassName('selected');
	},
		
	createNavLinkEvents: function() {
		$$(this.navLinkSel).each(function(elm) {
			elm.observe('click', Timeline.handleNavLinkClick);
		});
	},
	
	handleNavLinkClick: function(e) {
		e.stop();
		if (Timeline.swapping) {
			return;
		}
		Timeline.swapping = true;
		
		var link = e.element();
		var href = link.href.substring(link.href.indexOf('#') + 1);
		Timeline.swapSelectedLinks(link);
		Timeline.swapWeeks($(href));
	},
	
	swapSelectedLinks: function(linkIn) {
		$$(Timeline.selectedNavLinkSel)[0].removeClassName('selected');
		linkIn.addClassName('selected');
	},
	
	swapWeeks: function(weekIn, week) {
		var container = $$(this.timelineContainerSel)[0];
		container.setStyle('height:' + container.getHeight() + 'px;');
		this.currentWeeks.fade({
			duration: 0.3,
			afterFinish: function() {
				Timeline.currentWeeks = weekIn;
				Effect.Appear(weekIn, {
					duration: 0.3,
					afterFinish: function() {
						container.setStyle('height:auto;');
						Timeline.swapping = false;
						if (week) {
							Timeline.findWeek(weekIn, week);
						}
					}
				});
				Timeline.resetScroller();
			}
		});
	},
	
	createScroller: function() {
		var innerContainer = $$(this.innerContainerSel)[0];
		var slider = new Element('div', {
			'id': this.sliderId
		});
		var scrollHandle = new Element('a', {
			'href': '#',
			'id': this.scrollerId
		});
		slider.insert(scrollHandle);
		innerContainer.insert(slider);
		
		scrollHandle.observe('click', function(e) { e.stop(); });
		scrollHandle.observe('keypress', this.handleScrollKeyPress);
		
		var scrollableHeight = $(this.sliderId).getHeight() - $(this.scrollerId).getHeight();
		var innerInner = $(this.innerInnerId);
		var innerHeight = innerInner.getHeight();
		Timeline.scroller = new Control.Slider('scroll-handle', 'slider', {
			axis: 'vertical',				
			onSlide: function(v) {
				var h = Timeline.currentWeeks.getHeight() - innerHeight;
				var scrollTop = v * h;
				innerInner.scrollTop = scrollTop;
			},
			onChange: function(v) {
				var h = Timeline.currentWeeks.getHeight() - innerHeight;
				var scrollTop = v * h;
				innerInner.scrollTop = scrollTop;				
			}
		});
	},
		
	resetScroller: function() {
		Timeline.scroller.setValue(0);
		if (Timeline.currentWeeks.getHeight() > this.MAX_INNER_HEIGHT) {
			this.showScroller();
		} else {
			this.hideScroller();
		}
	},
	
	showScroller: function() {
		var scroller = $(this.sliderId);
		if (!scroller.visible()) {
			scroller.appear({ duration: 0.3,
				afterFinish: function() {
					$(Timeline.scrollerId).focus();
				}
			});
		} else {
			$(Timeline.scrollerId).focus();
		}
	},
		
	hideScroller: function() {
		var scroller = $(this.sliderId);
		if (scroller.visible()) {
			scroller.fade({ duration: 0.3 });
		}
	},
	
	handleScrollKeyPress: function(e) {
		var key = e.which || e.keyCode;
		if (key == 38) {
			e.stop();
			Timeline.scrollUp();
		} else if (key == 40) {
			e.stop();
			Timeline.scrollDown();
		} else if (key == 9) {
			e.stop();
			$$(Timeline.navLinkSel)[0].focus();
		}
	},
	
	createForm: function() {
		var form = new Element('form', {
			'id': 'goto-form'
		});
		form.insert('<label for="input-weeks">How many weeks pregnant are you?</label>');
		var textInput = new Element('input', {
			'type': 'text',
			'name': 'weeks',
			'id': 'input-weeks',
			'maxlength': '2'
		});
		textInput.observe('click', textInput.activate);
		textInput.observe('keypress', this.checkInputKeyPress);
		form.insert(textInput);
		form.insert('<input type="submit" name="submit-submit" value="Go!" class="hide" />');
		var submitLink = new Element('a', {
			'href': '#',
			'id': 'go-button'
		});
		submitLink.insert('Go!');
		submitLink.observe('click', this.handleFormLinkClick);
		form.insert(submitLink);
		var errorSpan = new Element('span', {
			'id': this.inputErrorId
		});
		errorSpan.insert('Please enter numbers only');
		form.insert(errorSpan);
		errorSpan.hide();
		form.insert('<span class="small">(e.g. \'1\', \'36\' etc)</span>');
		
		form.observe('submit', this.handleFormSubmit);
		
		$$(this.timelineContainerSel)[0].insert({ top: form });
		
		textInput.activate();
	},
	
	/* limit entry to digits, backspace, return */
	checkInputKeyPress: function(e) {
		var allowed = [ 8, 9, 13, 37, 39, 46, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57 ];
		var key = e.which || e.keyCode;
		if (allowed.indexOf(key) == -1) {
			e.stop();
			Timeline.flashFormError();
		} else if (key == 9) {
			e.stop();
			$(Timeline.scrollerId).focus();
		}
	},
	
	flashFormError: function() {
		var errorElm = $(this.inputErrorId);
		if (!errorElm.visible()) {
			errorElm.show();
			errorElm.fade({ duration:3 });
		}
	},
	
	handleFormLinkClick: function(e) {
		e.stop();
		Timeline.parseFormWeeks();
	},
		
	handleFormSubmit: function(e) {
		e.stop();
		Timeline.parseFormWeeks();
	},
	
	parseFormWeeks: function() {
		var input = $(this.inputWeeksId);
		if (input.value == '') {
			return;
		}
		
		var week = parseInt(input.value);
		var weeksIn = null;
		if (week == 0) {
			weeksIn = 'conception';
		} else if (week >= 1 && week <= 4) {
			weeksIn = 'weeks_1_4';
		} else if (week >= 5 && week <= 8) {
			weeksIn = 'weeks_5_8';
		} else if (week >= 9 && week <= 12) {
			weeksIn = 'weeks_9_12';
		} else if (week >= 13 && week <= 16) {
			weeksIn = 'weeks_13_16';
		} else if (week >= 17 && week <= 20) {
			weeksIn = 'weeks_17_20';
		} else if (week >= 21 && week <= 23) {
			weeksIn = 'weeks_21_23';
		} else if (week >= 24 && week <= 28) {
			weeksIn = 'weeks_24_28';
		} else if (week >= 29 && week <= 32) {
			weeksIn = 'weeks_29_32';
		} else if (week >= 33 && week <= 36) {
			weeksIn = 'weeks_33_36';
		} else if (week >= 37 && week <= 40) {
			weeksIn = 'weeks_37_40';
		} else if (week > 40) {
			weeksIn = 'after_birth';
		}
		
		if (weeksIn != this.currentWeeks.id) {
			this.swapSelectedLinks($$('a[href=#' + weeksIn + ']')[0]);
			this.swapWeeks($(weeksIn), week);
		} else {
			this.findWeek($(weeksIn), week);
		}
		
		input.activate();
	},
		
	findWeek: function(weeksIn, week) {
		var weekId = null;
		$$('#' + weeksIn.id + ' div.week').reverse(false).each(function(elm) {
			if (weekId != null) {
				return;
			}
			var elmWeek = elm.id.substring(elm.id.indexOf('_') + 1);
			if (elmWeek <= week) {
				weekId = 'week_' + elmWeek;
			}
		});
		
		if (weekId) {
			this.scrollToWeek(weekId);
		}
	},
		
	scrollToWeek: function(weekId) {
		var offsetTop = $(weekId).offsetTop;
		var finalOffset = (offsetTop - 10) / ($(weekId).up('div.weeks-holder').getHeight() - this.MAX_INNER_HEIGHT);
		
		this.scrollTo(finalOffset);
	},
		
	scrollUp: function() {
		var INCREMENT = 0.05;
	
		var h = Timeline.currentWeeks.getHeight() - $(this.innerInnerId).getHeight();
		var startingOffset = $(this.innerInnerId).scrollTop / h;
		var finalOffset = startingOffset - INCREMENT;
		
		Timeline.scroller.setValue(finalOffset);
	},
			
	scrollDown: function() {
		var INCREMENT = 0.05;
	
		var h = Timeline.currentWeeks.getHeight() - $(this.innerInnerId).getHeight();
		var startingOffset = $(this.innerInnerId).scrollTop / h;
		var finalOffset = startingOffset + INCREMENT;
		
		Timeline.scroller.setValue(finalOffset);		
	},	
	
	scrollTo: function(finalOffset) {		
		var h = Timeline.currentWeeks.getHeight() - $(this.innerInnerId).getHeight();
		var startingOffset = $(this.innerInnerId).scrollTop / h;
		var offsetRange = finalOffset - startingOffset;
		
		var DURATION = 0.5;
		var FPS = 50;
		var totalFrames = DURATION * FPS;		
		var offsetIncrement = offsetRange / totalFrames;
		
		// animation
		var offset = startingOffset;
		var intervalId = setInterval(function() {
			offset += offsetIncrement;
			if (offsetIncrement > 0 && offset >= finalOffset) {
				Timeline.scroller.setValue(finalOffset);
				clearInterval(intervalId);
			} else if (offsetIncrement < 0 && offset <= finalOffset) {
				Timeline.scroller.setValue(finalOffset);
				clearInterval(intervalId);
			} else {
				Timeline.scroller.setValue(offset);
			}
		}, 1000 / FPS);
	}
};

document.observe('dom:loaded', function() {
	RoundedCorners.init();
	Timeline.init();
});