var CourtSideBox = Class.create({

	initialize : function(base, identifier_pattern, identifier_slash_replacement) {
		if (!base) { return; }

		this.identifier_pattern = identifier_pattern != null ? identifier_pattern : "csb-";
		this.identifier_slash_replacement = identifier_slash_replacement != null ? identifier_slash_replacement : "-";
		this.base = base;
		
		this.setProperties();
		this.setDomElements();

		this.setupMenu();
		this.setupMatte();

		this.setTodayGame();
		
		// Fix for firefox sluggish performance with large elements in content scroller:
		//  The idea of the solution is to set elements outside the viewport to display: none
		//   using the nth-child selector by dynamically updating a style block.
		//  Also add a spacer before the elements visible in the viewport to make up for the width lost
		//  CSS will be faster than trying to manage this in javascript.
		if (Prototype.Browser.Gecko) {
			this.setupPerformanceEnchancement();
			this.setScrollerEventsForPerformanceEnhancement();
		}
	},

	setProperties : function() {

		$games_events = this.base.down(".games_events");

		this.timer = null;
		
		var games_events_id = $games_events.getAttribute("id");
		this.teamcode = games_events_id.substring(0, games_events_id.indexOf("-"));
		
		this.defaultFilter = $w($games_events.className).detect(function(n) { return n != "games_events"; });
		
		$games_events = null;
	},
	
	setDomElements : function() {

		this.menu = this.base.down("ul.menu");
		
		this.performance_enhancement_style_block = null;
		this.performance_enhancement_spacer = new Element("div", { "class" : "performance_enhancement_spacer" });
	},

	setupMenu : function() {

		if (!this.menu) { return; }
		
		new CourtSideBoxMenu(this.menu, this);
	},
	
	setupMatte : function() {
		
		this.base.insert({ top : "<div id='matte' class='" + this.teamcode + "'><div class='loading_image'></div></div>" });
		this.base.addClassName(this.teamcode);
	},
	
	setTodayGame : function() {

		this.today_game = this.base.down(".today.game");
		
		if (this.today_game) {
			this.today_game_code = this.today_game.getAttribute("id").replace(new RegExp(this.identifier_pattern), "").replace(new RegExp(this.identifier_slash_replacement), "/");
		
			this.short_date = this.today_game.down("h4").innerHTML;
			this.short_date = this.short_date.substring(0, this.short_date.indexOf("<"));
			
			this.loadTodayData();
		}
	},

	setupPerformanceEnchancement : function() {
		if (!Prototype.Browser.Gecko) { return; }
		
		this.base.down(".games_events").insert({ top : this.performance_enhancement_spacer});
		
		if (!this.performance_enhancement_style_block) {
			this.performance_enhancement_style_block = new Element("style", { "type" : "text/css", "rel" : "courtsidebox" });

			$$("head")[0].insert({ bottom : this.performance_enhancement_style_block});
		} else {
			this.performance_enhancement_style_block.update("");
		}
	},
	
	setScrollerEventsForPerformanceEnhancement : function() {

		function manageData() {

			var current_panel = this.base.scrollerModule.currentPanel;
			var scroll = this.base.scrollerModule.options.scroll;
			var panel_width = this.base.scrollerModule.panelWidth;
			var number_visible_panels = this.base.scrollerModule.viewportWidth / panel_width;
		
			var previous_to_hide = current_panel > number_visible_panels ? (current_panel - number_visible_panels) * scroll: 0;
			var next_to_hide = (current_panel + Math.ceil(1.5 * number_visible_panels)) * scroll;

			// add 1 to each nth-child selector to account for performance_enhancement_spacer div
			this.performance_enhancement_style_block.update([
				"#court_side_box .games_events > *:nth-child(-n+", previous_to_hide + 1, ") { display: none; } ",
				"#court_side_box .games_events > *:nth-child(n+", next_to_hide + 1, ") { display: none; } "
			].join(""));
			
			if (previous_to_hide > 0) {
				this.performance_enhancement_style_block.insert({bottom : ["#court_side_box .games_events .performance_enhancement_spacer { display: block; width: ", panel_width * previous_to_hide, "px; }"].join("")});
			}
		}

		this.base.scrollerModule.prevNavs.each(function(n) {
			n.observe("click", manageData.bind(this));
		}.bind(this));
		
		this.base.scrollerModule.nextNavs.each(function(n) {
			n.observe("click", manageData.bind(this));
		}.bind(this));
	},

	loadFilter : function(filter) {
		if (!filter || this.base.down(".games_events").hasClassName(filter)) { return; }

		this.base.addClassName("loading");

		new Ajax.Updater(this.base.down(".viewport"), '/csb/nba_csb.jsp?teamcode=' + this.teamcode + '&filter=' + filter, {
			method : "GET",
			onComplete: (function(response) { 
			
				if (this.base.down(".games_events *")) { // make sure data came back, if no data somehow, kill today matchup loading
				
					this.setTodayGame();

					// reset elements on scroller
					this.base.scrollerModule.setDomElements();
					this.base.scrollerModule.setProperties();
					this.base.scrollerModule.setNavStates();
					this.base.scrollerModule.navigate(0);

					this.setupPerformanceEnchancement();
				} else {
					this.cancelUpdateTodayMatchup();
				}
				
				this.base.removeClassName("loading");
			}).bind(this)
		});
	},

	loadTodayData : function() {
	
		this.cancelUpdateTodayMatchup();

		new Ajax.Request('/games/game_component/dynamic/simple_scoreboard.xml', {
			method : "GET",
			onComplete: (function(response) { this.updateTodayMatchup(response.responseXML); }).bind(this)
		});
	},

	updateTodayMatchup : function(simpleScoreboardData) {

		if (!simpleScoreboardData) { this.timer = setTimeout(this.loadTodayData.bind(this), 15000); return; }

		var games = simpleScoreboardData.getElementsByTagName("game");

		for (var i = 0; i < games.length; i++) {

			var game = games[i];
			
			var game_status = parseInt(game.getAttribute("gstat"), 10);
			var gamecode = game.getAttribute("gcd");
			var gametype = game.getAttribute("gtyp");
			
			if (gamecode == this.today_game_code) {

				if (game_status > 1) {
				
					var clock = game.getAttribute("clk");
					var period = game.getAttribute("prd");
					var game_status_text = game.getAttribute("gstattxt");

					var vtm = game.getElementsByTagName("vtm")[0];
					var vtm_teamcode = vtm.getAttribute("tcd");
					var vtm_abbreviation = vtm.getAttribute("tm").split("|")[3];
					var vtm_total_score = vtm.getAttribute("scr").split("|")[8];
					vtm_total_score = vtm_total_score ? parseInt(vtm_total_score, 10) : 0;

					var htm = game.getElementsByTagName("htm")[0];
					var htm_teamcode = htm.getAttribute("tcd");
					var htm_abbreviation = htm.getAttribute("tm").split("|")[3];
					var htm_total_score = htm.getAttribute("scr").split("|")[8];
					htm_total_score = htm_total_score ? parseInt(htm_total_score, 10) : 0;

					var brand = "NBA";
					if (this.teamcode  == vtm_teamcode) { brand = vtm_abbreviation; }
					if (this.teamcode  == htm_teamcode) { brand = htm_abbreviation; }

					var vid = game.getAttribute("vid");

					$visiting_score = this.today_game.down(".scoring ." + vtm_teamcode + " .score");
					$home_score = this.today_game.down(".scoring ." + htm_teamcode + " .score");


					// Update game
					
					this.today_game.removeClassName("pre");
					this.today_game.removeClassName("live");
					this.today_game.removeClassName("final");
					
					switch (game_status) {
						case 2:
							this.today_game.addClassName("live");
							break;
						case 3:
							this.today_game.addClassName("final");
							break;
					}

					// Update game info
					
					var status_text = game_status_text;
					var date_time = "";
					
					if (game_status == 2) {
						
						status_text = "LIVE";
						
						if (!clock.blank()) {
							if (period > 4) {
								if (period > 5) { date_time += period; }
								date_time += "OT "
							} else {
								date_time += period;
								date_time += "Q ";
							}

							date_time += clock;
						} else {
							date_time += game_status_text;
						}
					} else if (game_status == 3) {
						
						date_time = this.short_date;
					}
					
					this.today_game.down("h4").update([
						status_text,
						'<em>', date_time, '</em>',
					].join(""));

					var info_links = ['<a href="/tvc/index.html?gamecode=', gamecode, '&brand=', brand, '" class="tv_companion">TV Companion</a> '];
					if (game_status == 2) { info_links.push(['<a href="/allaccess/watchListen.html" class="listen">Listen Live</a>'].join("")); }

					this.today_game.down(".info .links").update(info_links.join(""));


					// Update scoring
					
					if (!$visiting_score) {
						$visiting_team = this.today_game.down(".scoring ." + vtm_teamcode);	

						$visiting_score = new Element("span").addClassName("score");
						$visiting_team.insert({ bottom : $visiting_score});
						
						$home_team = null;
					}

					if (!$home_score) {
						$home_team = this.today_game.down(".scoring ." + htm_teamcode);	

						$home_score = new Element("span").addClassName("score");
						$home_team.insert({ bottom : $home_score});
						
						$home_team = null;
					}
					
					$visiting_score.update(vtm_total_score);
					$home_score.update(htm_total_score);
					
					if (vtm_total_score > htm_total_score) {
						$visiting_score.addClassName("winning");
					} else {
						$visiting_score.removeClassName("winning");
					}
					
					if (htm_total_score > vtm_total_score) {
						$home_score.addClassName("winning");
					} else {
						$home_score.removeClassName("winning");
					}
					
					// Update game links

					if (game_status == 3) {

						var highlight_link = vid ? ['<a href="', vid, '" class="highlights">Highlights</a> '].join("") : "";

						this.today_game.down(".broadcast_info").replace([
							'<div class="links">',
								'<a href="/games/', gamecode, '/gameinfo.html" class="recap">Recap</a> ',
								'<a href="/games/', gamecode, '/gameinfo.html#nbaGIboxscore" class="boxscore">Box</a> ',
								highlight_link,
							'</div>'
						].join(""));
					}
					
					$visiting_score = null;
					$home_score = null;
				}

				if (game_status < 3) { this.timer = setTimeout(this.loadTodayData.bind(this), 15000); }

				break;
			}
		}

		simpleScoreboardData = null;
	},
	
	cancelUpdateTodayMatchup : function() {
	
		clearTimeout(this.timer);
		delete this.timer;
	}

});

var CourtSideBoxMenu = Class.create(Menu.Menu, {

	initialize : function($super, menu, court_side_box) {
	
		$super(menu);
		
		this.court_side_box = court_side_box;
		this.open_submenu = null;
		this.selected_filter_element = null;

		this.setupMenuitems();
		this.setupCalendar();
	},

	setupMenuitems : function() {

		this.menu.observe("click", function(event) {
			
			var $selected_filter = event.findElement("li[data-filter != '']");
		
			if ($selected_filter) { this.selectFilter($selected_filter, $selected_filter.innerHTML); }
			
			$selected_filter = null;
		}.bind(this));
		
		this.menu.select("li.has_children").each(function(n) { n.submenu_name = n.firstChild.nodeValue; });
		
		// highlight default selected date if it exists
		$default_selected_listitem = this.menu.down("li[data-filter = " + this.court_side_box.defaultFilter + "]");
		if ($default_selected_listitem) {
			this.selectFilter($default_selected_listitem, $default_selected_listitem.innerHTML);
		}

		// cleanup
		$default_selected_listitem = null;
	},

	setupCalendar : function() {

		var month_displays = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
		var dates_with_games_data = {};

		function padDatePartString(number) { return (number < 10 ? "0" : "") + number; }
		
		function convertDateStringToShortText(date_string) { 
			if (!date_string) { return ""; }
			
			var year = date_string.substring(0, 4);
			var month = parseInt(date_string.substring(4, 6), 10) - 1;
			var date = parseInt(date_string.substring(6, 8), 10);
			
			return [month_displays[month], " ", date, ", ", year].join("");
		}
		
		var buildCalendar = function() {

			var start_date_string = dates_with_games_data.get("startdate");
			var end_date_string = dates_with_games_data.get("enddate");

			var dates_with_games = dates_with_games_data.get("dates");

			var start_year = parseInt(start_date_string.substring(0, 4), 10);
			var start_month = parseInt(start_date_string.substring(4, 6), 10) - 1;
			var start_day = parseInt(start_date_string.substring(6, 8), 10);

			var end_year = parseInt(end_date_string.substring(0, 4), 10);
			var end_month = parseInt(end_date_string.substring(4, 6), 10) - 1;
			var end_day = parseInt(end_date_string.substring(6, 8), 10);

			var start_date = new Date(start_year, start_month, start_day);
			var end_date = new Date(end_year, end_month, end_day);

			var current_date = new Date(start_year, start_month, 1);
			var end_month = new Date(end_year, end_month + 1, 1);

			var current_month = -1;

			var calendar_display = [];

			while (current_date < end_month) {

				var current_date_filter = "" + current_date.getFullYear() + padDatePartString(current_date.getMonth() + 1) + padDatePartString(current_date.getDate());

				if (current_month != current_date.getMonth()) {

					current_month = current_date.getMonth();

					calendar_display.push([
						"<table cellspacing='1' cellpadding='0'>",
							"<tr>",
								"<th colspan='7' class='month'>",
									month_displays[current_month], " ",
									current_date.getFullYear(),
								"</th>",
							"</tr>",
							"<tr>",
								"<th>S</th>",
								"<th>M</th>",
								"<th>T</th>",
								"<th>W</th>",
								"<th>T</th>",
								"<th>F</th>",
								"<th>S</th>",
							"</tr>"
					].join(""));

					if (current_date.getDay() != 0) {
						calendar_display.push("<tr>");
						
						for (var i = 0, howmany = current_date.getDay(); i < howmany; i++) {
							calendar_display.push("<td class='inactive'>&nbsp;</td>");
						}
					}
				}

				// begin build table row for each week
				
					if (current_date.getDay() == 0) { calendar_display.push("<tr>"); }

					// begin build table cell for each date

						calendar_display.push("<td");
							
							if ((current_date < start_date || current_date > end_date) || !dates_with_games[current_date_filter]) {
								calendar_display.push(" class='inactive'");
							}
							
							if (dates_with_games[current_date_filter]) { calendar_display.push(" data-filter='date_" + current_date_filter + "'"); }
							
						calendar_display.push(">");
						
						calendar_display.push(current_date.getDate());
						calendar_display.push("</td>");

					// end build table cell for each date

					if (current_date.getDay() == 6) { calendar_display.push("</tr>"); }

				// end build table row for each week

				current_date.setDate(current_date.getDate() + 1);

				if (current_month != current_date.getMonth()) {

					if (current_date.getDay() != 0 && current_date.getDay() - 1 != 6) {
						for (var i = 0, howmany = 7 - current_date.getDay(); i < howmany; i++) {
							calendar_display.push("<td class='inactive'>&nbsp;</td>");
						}

						calendar_display.push("</tr>");
					}

					calendar_display.push("</table>");
				}

			}
			
			// have to do this here since AJAX call is asynchronous		
			var $calendar = this.menu.down("li.calendar");
			$calendar.addClassName("has_children");
			
			$calendar.insert({
				bottom : [
					"<ul prevSelector = '.calendar-nav-prev' ",
						"nextSelector = '.calendar-nav-next' ",
						"viewportSelector = 'li' ",
						"holderSelector = '.months' ",
						"panelSelector = '.months > table' ",
						"tocSelector = '' ",
						"activeTocClass = '' ",
						"enabledNavClass = 'enabled' ",
						"disabledNavClass = 'disabled' ",
						"hoverNavClass = 'hover' ",
						"scroll = '1' ",
						"wrap = 'false' ",
						"duration = '0.3'>",

						"<li>",
							"<a href='javascript:{}' class='calendar-nav-prev calendar_nav_button'><</a>",
							"<div class='months'></div>",
							"<a href='javascript:{}' class='calendar-nav-next calendar_nav_button'>></a>",
						"</li>",
					"</ul>"
				].join("")
			});
			
			$calendar.submenu_name = $calendar.firstChild.nodeValue;
			$calendar_submenu = $calendar.down("ul");

			// append calendar html to .months holder, set up click event for table cells with event delegation
			var $months = $calendar.down(".months");
			$months.insert({ bottom : calendar_display.join("") });
			$months.observe("click", function(event) {
			
				var $selected_date = event.findElement("td[data-filter != '']");
				
				if ($selected_date) { this.selectFilter($selected_date, convertDateStringToShortText($selected_date.readAttribute("data-filter").substring(5))); }
				
				$selected_date = null;
			}.bind(this));
			
			// set up calendar scrolling, add class so that calendar will be invisible but scroller can still calculate widths
			
			var $calendar_scroller = $calendar.down("ul");
			$calendar_scroller.addClassName("setting_up");

			new contentScroller($calendar_scroller);

			var today_date = new Date();
			$calendar_scroller.scrollerModule.navigate(today_date.getMonth() + (12 * (today_date.getFullYear() - start_year)) - start_month);

			$calendar_scroller.removeClassName("setting_up");
			
			// highlight default selected date if it exists
			$default_selected_date = $calendar.down("td[data-filter = " + this.court_side_box.defaultFilter + "]");
			if ($default_selected_date) {
				this.selectFilter($default_selected_date, convertDateStringToShortText($default_selected_date.readAttribute("data-filter").substring(5)));
			}

			// explicitly remove references to elements (clean up)
			$default_selected_date = null;
			$calendar = null;
			$months = null;
			$calendar_scoller = null;
			
		}.bind(this);


		new Ajax.Request('/schedules/dates_with_games_team.jsp?teamcode=' + this.court_side_box.teamcode, {
			method: 'get',
			evalJS : false,
			onSuccess: function(transport){
				if (transport.responseText) {
					dates_with_games_data = $H(transport.responseText.evalJSON(true));
					
					buildCalendar();
				}
			}
		});

	},
	
	selectFilter : function($selected_element, selected_text) {
		if (!$selected_element) { return; }
	
		var filter = $selected_element.readAttribute("data-filter");
					
		if (filter && this.selected_filter_element != $selected_element) {
		
			if (this.selected_filter_element) {
				this.selected_filter_element.removeClassName("selected");

				var $old_selected_element_parent = this.selected_filter_element.up("li.has_children");
				if ($old_selected_element_parent) {
					$old_selected_element_parent.removeClassName("selected");
					$old_selected_element_parent.firstChild.nodeValue = $old_selected_element_parent.submenu_name;
				}
				$old_selected_element_parent = null;
			}

			$selected_element.addClassName("selected");

			var $selected_element_parent = $selected_element.up("li.has_children");
			if ($selected_element_parent) {
				$selected_element_parent.addClassName("selected");
				$selected_element_parent.firstChild.nodeValue = selected_text;
			}
			$selected_element_parent = null;

			this.court_side_box.loadFilter(filter);
			
			this.selected_filter_element = $selected_element;
			this.closeSubmenu(this.open_submenu);
		}
	},
	
	openSubmenu : function($super, submenu) {
		if (!submenu) { return; }
			
		$super(submenu);
		
		this.open_submenu = submenu;
	},
	
	closeSubmenu : function($super, submenu) {
		if (!submenu) { return; }

		$super(submenu);
		
		this.open_submenu = null;
	}

});

NBAUtil.Events.addDomLoadedHandler(function() { new CourtSideBox($("court_side_box")); });
