/* Shastic Calendar Script 
 * Requires Prototype and Script.aculo.us Libraries
 * By: Joseariel Gomez Ortigoza <joseariel1@gmail.com>
*/

if (typeof Effect == 'undefined')
  throw("You must have the script.aculo.us library to use Shastic's calendar");

var ShasticCalendar = Class.create({

    initialize: function(weeks, currDay, options) {
				this.options = Object.extend({ duration: 0.75, 
																			 mainWrapperId: 'events_wrapper',
																			 weeklyCarouselId: 'events_weekly_accordion_cal_carousel',
																			 weeklyCarouselClass: 'horizontal-accordion',
																			 monthlyCarouselId: 'events_monthly_cal_carousel',
													 						 monthlyCarouselPositionId: 'monthly_calendar_position_marker',
																			 listCarouselId: 'events_list_cal_carousel',
																			 mainDayHeaderId: 'calendar_day_header',
																			 weeklyCarouselHeaderClass: 'weekly_accordion_carousel_day_header',
																			 weeklyAccordionHeadingsHeight: 47 }, options || {});

				//console.info("initializing 'currCalendar'");
				
				// Main wrapper
				this.wrapper = $(this.options.mainWrapperId);
				
				var self = this;
				
				// Monthly Carousel Setup
				//this.accordionMonthlyCarousel = window[this.options.monthlyCarouselId]; // Monthly Carousel Object
				
				// Weekly Carousel Setup
				//this.accordionWeeklyCarousel = window[this.options.weeklyCarouselId]; // Weekly Carousel Object
				
				// For IE which doesn't support javascript variables named excatly the same as dom elements.
				// So accordions are added as they are instantiated.
				
				//this.weeklyAccordions = this.accordionWeeklyCarousel.sections.map(function(section){  // Weeks' Accordions
				//	return window[section.down('.'+self.options.weeklyCarouselClass).identify()]; 
				//});
				this.weeklyAccordions = []; 
				
				this.weeks = [];
				weeks.each(function(week_array){
					days_array = [];
					week_array.each(function(day){
						days_array.push(self.extractCalendarDay(day));
					});

					self.weeks.push(days_array);
				});
				
				// Current Day Setup
				this.currDay = this.extractCalendarDay(currDay);
				
				// Month Names Setup
				this.monthNames = new Array(12);
				this.monthNames[0]="January";
				this.monthNames[1]="February";
				this.monthNames[2]="March";
				this.monthNames[3]="April";
				this.monthNames[4]="May";
				this.monthNames[5]="June";
				this.monthNames[6]="July";
				this.monthNames[7]="August";
				this.monthNames[8]="September";
				this.monthNames[9]="October";
				this.monthNames[10]="November";
				this.monthNames[11]="December";
				
				// Initial Month Setup
				this.initialMonth = this.monthNames[this.currDay.getMonth()]; // Initial month name
				this.initialMonthIndex = this.currDay.getMonth(); // Initial month index
				
				// Behavior Tracking Variables
				this.triggeredNextMonth = false;
				this.triggeredLastMonth = false;
        this.isAnimating = false;
    },
		
		// Monthly Carousel Setup
		accordionMonthlyCarousel: function() {
			return window[this.options.monthlyCarouselId]; // Monthly Carousel Object
		},
		
		// Weekly Carousel Setup
		accordionWeeklyCarousel: function() {
			return window[this.options.weeklyCarouselId]; // Weekly Carousel Object
		},
		
		// Returns the current week's index (accordion's index)
		currAccordionIndex: function() {
			return this.accordionWeeklyCarousel().current._index;
		},
		
		// Returns the current week (accordion)
		currAccordion: function() {
			/*
			console.info(this.weeklyAccordions.length);
			console.info(this.currAccordionIndex());
			console.info("-------------------------------------------------------");
			this.weeklyAccordions.each(function(a) { 
				//console.info(a); 
				if (a != undefined && a.accordion != undefined) { console.info(a.accordion.identify()); }
			});
			console.info("-------------------------------------------------------");
			*/
			return this.weeklyAccordions[this.currAccordionIndex()];
		},
		
		// Returns the current week's number in reference to the whole year
		// Note: Requires the 'getWeek()' method from:
		// 		http://syn.ac/tech/19/get-the-weeknumber-with-javascript/
		//
		//		Date.prototype.getWeek = function() {
		//			var determinedate = new Date();
		//			determinedate.setFullYear(this.getFullYear(), this.getMonth(), this.getDate());
		//			var D = determinedate.getDay();
		//			if(D == 0) D = 7;
		//			determinedate.setDate(determinedate.getDate() + (4 - D));
		//			var YN = determinedate.getFullYear();
		//			var ZBDoCY = Math.floor((determinedate.getTime() - new Date(YN, 0, 1, -6)) / 86400000);
		//			var WN = 1 + Math.floor(ZBDoCY / 7);
		//			return WN;
		//	  }
		//
		currWeek: function() { 
			return this.currDay.getWeek(); 
		},
		
		// Return a displayable day string
		shortDay: function() {
			return this.monthNames[this.currDay.getMonth()] + ' ' + this.currDay.getDate();
		},
		
		// Returns de current month's index based on the current day
		currMonthIndex: function() {
			return this.currDay.getMonth();
		},
		
		// Returns de current month's name based on the current day
		currMonth: function() {
			return this.monthNames[this.currMonthIndex()];
		},
		
		updateCalendar: function(e) {
			var event = e || window.event;
			//console.info("currCalendar updateCalendar"); 
			
			// Setup the correct height
			this.updateHeight();
			
			//currAccordion = window[event.currentTarget.id];
			var currAccordion = this.currAccordion();
			currAccordionSectionIndex = currAccordion.contents.indexOf(this.toExpandOrCurrent());


			//console.info('currAccordionIndex: '+currCalendar.currAccordionIndex());
			//console.info('currAccordionSectionIndex: '+currAccordionSectionIndex);
			this.currDay = this.weeks[this.currAccordionIndex()][currAccordionSectionIndex];

			//console.info(currCalendar.currDay);
			$(this.options.mainDayHeaderId).update('<b>'+this.shortDay()+'</b>');
			// Update the headers to be displayed next inside the weekly carousel
			this.accordionWeeklyCarousel().current.down('.'+this.options.weeklyCarouselHeaderClass).update('<b>'+this.shortDay()+'</b>');

			// If the user goes beyond the next or previous month by browsing the weeks, then
			// make his life easier and show him the monthly view
			var currMonth = this.currMonth();
			if (currMonth != this.initialMonth) {
				if (!this.triggeredNextMonth && currMonth == this.monthNames[this.initialMonthIndex + 1] && this.accordionMonthlyCarousel() != null) {
					var wrapper_id = this.accordionMonthlyCarousel().wrapper.up('#'+this.options.monthlyCarouselId+'_wrapper').identify();
					if (!$(wrapper_id).visible()) {
						new Effect.SlideDown(wrapper_id, { duration: this.options.duration, scaleFrom: 0, scaleTo: 100 });
						$(wrapper_id).next('a').down('div').update('<b>Hide monthly view</b>');
					}
					if (!$(this.options.monthlyCarouselId+'_wrapper').visible()) {
						setTimeout("new Effect.ScrollTo('"+this.options.monthlyCarouselPositionId+"', { duration: "+this.options.duration+", queue: 'end', offset: -1 });", 1000);
					}
					this.triggeredNextMonth = true;
				}
				if (!this.triggeredLastMonth && currMonth == this.monthNames[this.initialMonthIndex - 1] && this.accordionMonthlyCarousel() != null) {
					var wrapper_id = this.accordionMonthlyCarousel().wrapper.up('#'+this.options.monthlyCarouselId+'_wrapper').identify();
					if (!$(wrapper_id).visible()) {
						new Effect.SlideDown(wrapper_id, { duration: this.options.duration, scaleFrom: 0, scaleTo: 100 });
						$(wrapper_id).next('a').down('div').update('<b>Hide monthly view</b>');
					}
					if (!$(this.options.monthlyCarouselId+'_wrapper').visible()) {
						setTimeout("new Effect.ScrollTo('"+currCalendar.options.monthlyCarouselPositionId+"', { duration: "+this.options.duration+", queue: 'end', offset: -1 });", 1000);
					}
					this.triggeredLastMonth = true;
				}
			}

			// Stop event propagation.
			if (event) {
				if (event.stopPropagation) {
			    event.stopPropagation();
			  } else {
			    event.cancelBubble = true;
			  }
			}
		},
		
		moveToDay: function(day) {
			var currDay = this.currDay;
			var currDayIndex = currDay.getDay();
			var currWeek = this.currWeek();
			var newDay = this.extractCalendarDay(day);
			var newDayIndex = this.getWorkDay(newDay); // new index for the appropriate week's accordion (1 - 7 instead of 0 - 6)
			var newWeek = newDay.getWeek();
			var carousel = this.accordionWeeklyCarousel();
			var currAccordion = this.currAccordion();

			//console.info(newDay);
			//console.info(newDayIndex);
			
			if (carousel.current) {
		    var currentIndex = carousel.current._index;
				var indexDiff = newWeek - currWeek;
				var lastIndex = (carousel.sections.length - 1);

				var newIndex = currentIndex + indexDiff;
				//console.info('currentIndex: '+currentIndex);
				//console.info('currWeek: '+currWeek);
				//console.info('newWeek: '+newWeek);
				//console.info('newIndex: '+newIndex);
				if (newIndex > lastIndex) {
					newIndex = indexDiff - ( lastIndex - currentIndex ) - 1;
				} else if (newIndex < 0) {
					newIndex = carousel.sections.length - indexDiff + currentIndex;
				}

		    //var nextIndex = (carousel.sections.length - 1 == currentIndex) ? 0 : currentIndex + 1;      
		  } else var newIndex = 1;	
			
			if (newDay != currDay && carousel.wrapper.visible()) {
				if (newIndex != currentIndex) {
					carousel.moveTo(carousel.sections[newIndex], carousel.scroller, { duration: carousel.options.duration });
				} else {
					new Effect.ScrollTo(this.options.mainWrapperId, { duration: this.options.duration, queue: 'end', offset: -1 });
				}
				
				setTimeout("currCalendar.updateCalendarDay("+ (newDayIndex - 1).toString() +"); currCalendar.updateTalentFlow();", (this.options.duration * 1000));
			}
		},
		
		updateCalendarDay: function(newIndex) {
			//console.info('executing updateCalendarDay');
			var currAccordion = this.currAccordion();
			currAccordion.expand(currAccordion.toggles[newIndex]);
			
			this.updateHeight();
			this.updateCalendar(); 
			
			//setTimeout("new Effect.ScrollTo('"+currCalendar.options.mainWrapperId+"', { duration: "+this.options.duration+", queue: 'end', offset: -1 });", 1000);
			new Effect.ScrollTo(currCalendar.options.mainWrapperId, { duration: this.options.duration, queue: 'front', offset: -1 });
		},
		
		toExpandOrCurrent: function() {
			var currAccordion = this.currAccordion();
			
			//console.info("---------------------------------------");
			//console.info(currAccordion);
			//console.info(currAccordion.accordion);
			//console.info(currAccordion.toExpand);
			//console.info(currAccordion.current);
			//console.info("---------------------------------------");
			
			return (currAccordion.toExpand == null ? currAccordion.current : currAccordion.toExpand)
		},
		
		extractCalendarDay: function(day) {
			day_attrs = day.split('-');

			formatted_day_attrs = [];
			day_attrs.each(function(attr){
				// Take the second digit only. To avoid the first 0 of 08 for instance and only use 8.
				formatted_attr = ( attr.match(/^0\d$/) ? parseInt(attr[1]) : parseInt(attr) );
				formatted_day_attrs.push(formatted_attr);
				//console.info(formatted_attr);
			});
			//console.info(formatted_day_attrs);

			return new Date(formatted_day_attrs[0], (formatted_day_attrs[1] - 1), formatted_day_attrs[2]);
		},
		
		getWorkDay: function(day) {
			var rawDayIndex = day.getDay();
			if (rawDayIndex == 0) {
				return 7; // We want to treat Sunday as 7, not 0.
			} else {
				return rawDayIndex;
			}
		},
		
		updateTalentFlow: function() {
			var currContent = this.toExpandOrCurrent();
			/*
			console.info(this.currAccordion().toExpand == currContent);
			console.info(this.currAccordion().toExpand == null);
			console.info(currContent);
			console.info(currContent.down("div div div b"));
			console.info(currContent.down("div div div b").innerHTML);
			*/
			currContent.down('.carousel').down('.scroller_container').down('a').onclick();
		},
		
		updateHeight: function() {
			this.accordionWeeklyCarousel().maxHeight = (this.toExpandOrCurrent().getHeight() + this.options.weeklyAccordionHeadingsHeight + 2);
			this.accordionWeeklyCarousel().attachMaxHeight();
		}

});