define(['scripts/knockout-3.3.0','scripts/ACTComponent.js'], function(ko, ACTComponent) {

	function StartPageHeaderComponentViewModel(params, element) {
		var self = this;
		self.base = new ACTComponent($(element), params);

		// do this here to let the possibility to set the cssproperty in the c#
		$(element).css("background-color", "#F0F0F0");

		self.icon = ko.observable();
		self.title = ko.observable();

		self.$comp   = $(element).find(".headerComp");
		self.$icon   = $(element).find(".icon");
		self.$title  = $(element).find(".title");
		self.$text   = $(element).find(".text");
		self.$banner = $(element).find(".banner");

		self.base.onRefresh = function(obj) {
			self.icon(obj.Icon);
			self.title(obj.Title);

			// hack : fix for a right white margin which appears for no reason
			$(element).children().hide();
			setTimeout(function() {
				$(element).children().show();
			}, 0);
		}

		params.baseModel.resizeFunctions[params.baseModel.resizeFunctions.length] = function(height,width) {
			var rightMargin = 30; // to not overcharge the UI

			// alignements
			var h = self.$comp.height();
			self.$title.css("line-height", h + "px");
			self.$title.css("height", h + "px");
			self.$icon.css("top", (h - self.$icon.height()) * 0.5 + "px");
			self.$banner.css("top", (h - self.$banner.height()) * 0.5 + "px");

			// set correct title width
			var bannerWidth = self.$banner.outerWidth();
			var titleWidth = width - bannerWidth;
			self.$title.outerWidth(titleWidth - rightMargin);

			// hide icon if necessary
			if (!self.basePaddingLeft)
				self.basePaddingLeft = self.$text.css("padding-left");
			self.$text.css("padding-left", self.basePaddingLeft);

			self.$icon.css("display", "block");
			var textRight = self.$text.outerWidth() + rightMargin;
			if (self.icon() == "" || self.icon() == null || textRight > titleWidth) {
				self.$icon.css("display", "none");
				self.$text.css("padding-left", "5px");
			}
		}

		/* Will someone notice ? */
		var makeRotate = function($element, startAngle, endAngle, duration) {
			$({deg: startAngle}).animate({deg: endAngle},
				{
					duration: duration,
					step: function(now) {
						$element.css({transform: 'rotate(' + now + 'deg)',});
					},
				}
			);
		}

		var counterMax = 10;
		var counter = 0;
		var $element = $(element);
		var $icon = $element.find(".icon");
		$icon.on("click", function() {
			$(element).css("overflow", "hidden");
			counter++;
			if (counter > 1) {
				makeRotate($icon, 0, counter%2 > 0 && counter || -counter, 100);
			}

			var now = new Date().getTime();
			if (counter > counterMax) {
				counter = 0;

				var $screenElement = $("<div/>");
				$screenElement.css({
					width: "100%", height:"100%", "z-index":"99999",
					position:"absolute", top:"0px", left:"0px"
				});
				$("body").append($screenElement);

				var $oldIcon = $icon;
				$icon = $oldIcon.clone();
				$oldIcon.hide();
				var $iconOnBody = $("<div class='headerComp noselect'><div class='title'></div></div>");
				$iconOnBody.css({"width":"0px", "height":"0px"});
				$screenElement.append($iconOnBody);
				$iconOnBody.find(".title").append($icon);

				var rotationDuration = 500;
				makeRotate($icon, 0, 360, rotationDuration);

				const KEY_LEFT = 37;
				const KEY_UP = 38;
				const KEY_RIGHT = 39;
				const KEY_DOWN = 40;
				const KEY_SPACE = 32;
				const KEY_ESCAPE = 27;
				var startX = $icon.offset().left;
				var startY = $icon.offset().top;
				var nextDirection = null;
				var direction = null;
				var iconSize = $icon.outerWidth(true);
				var $headIcon = $icon;
				var $tailIcon = $icon;
				var oldTitle = self.title();
				var score = 0;
				$icon.next = $icon.previous = $icon;
				var idxCurrentIcon = 0;
				var $bonusElements = {};
				var freqUpdate = 0;
				var stoped = false;
				var freqUpdate = 10;
				$(window).on("keydown", function(event) {
					var kCode = event.keyCode;
					if ((direction != KEY_LEFT && direction != KEY_RIGHT && (kCode == KEY_LEFT || kCode == KEY_RIGHT)) ||
						(direction != KEY_UP && direction != KEY_DOWN && (kCode == KEY_DOWN || kCode == KEY_UP)))
					{
						nextDirection = kCode;
					}
					if (kCode == KEY_SPACE)
						freqUpdate *= 1.1;
					if (kCode == KEY_ESCAPE)
						stop();
				});

				var isIncollisionWithSn = function(left, top) {
					var s = $headIcon;
					do {
						if (s.offset().top == top && s.offset().left == left)
							return true;
						s = s.previous;
					} while(s != null && s != $headIcon)
					return false;
				}

				var getIconCountWidth  = function() { return Math.floor($(window).outerWidth(true) / iconSize); };
				var getIconCountHeight = function() { return Math.floor($(window).outerHeight(true) / iconSize); };

				var idMaxBonusElement = 0;
				var createNewBonusElement = function() {
					var left, top;
					var countWidth = getIconCountWidth() - 1;
					var countHeight = getIconCountHeight() - 1;
					do {
						left = (startX + Math.floor(Math.random() * countWidth) * iconSize);
						top  = (startY + Math.floor(Math.random() * countHeight) * iconSize);
					} while (isIncollisionWithSn(left, top) || isInCollisionWithBonusElement(left, top));

					var $iconOnBodyClone = $iconOnBody.clone();
					var $newBonusElement = $iconOnBodyClone.find(".icon");
					$newBonusElement.css({
						"left": left + "px",
						"top": top + "px",
						"background-color": "rgba(1, 1, 1, 0.1)",
						transform: 'rotate(0deg)',
					});
					makeRotate($newBonusElement, 0, 360, 400);
					$newBonusElement.bonusId = idMaxBonusElement++;
					$screenElement.append($iconOnBodyClone);
					$bonusElements[$newBonusElement.bonusId] = $newBonusElement;
				}

				var isInCollisionWithBonusElement = function(left, top) {
					for (var key in $bonusElements) {
						var $be = $bonusElements[key];
						if (left == $be.offset().left && top == $be.offset().top) {
							return $be;
						}
					}
					return null;
				}

				var updateTitle = function() {
					self.title("SNAKE - Press Escape to quit - Score: " + score);
				}

				var applyCollisionWithBonusElement = function($be) {
					delete $bonusElements[$be.bonusId];
					score += 10;
					updateTitle();
				}

				createNewBonusElement();

				var stop = function() {
					// stop
					$oldIcon.css("transform", "rotate(0deg)");
					$oldIcon.show();
					$icon = $oldIcon;
					$screenElement.remove();
					self.title(oldTitle);
					stoped = true;
				}

				var updateFunction = function() {
					if (stoped)
						return;

					setTimeout(updateFunction, 1000/freqUpdate);

					if (direction == null && nextDirection == null)
						return;

					// deplacement
					if (nextDirection != null)
						direction = nextDirection;
					var left = $headIcon.offset().left;
					var top = $headIcon.offset().top;
					if (direction == KEY_LEFT) {
						left -= iconSize;
					} else if (direction == KEY_RIGHT) {
						left += iconSize;
					} else if (direction == KEY_DOWN) {
						top += iconSize;
					} else if (direction == KEY_UP) {
						top -= iconSize;
					}

					// torus
					var windowWidth  = getIconCountWidth() * iconSize;
					var windowHeight = getIconCountHeight() * iconSize;
					if (left > windowWidth) left -= windowWidth;
					if (left < 0)           left += windowWidth;
					if (top > windowHeight) top  -= windowHeight;
					if (top < 0)            top  += windowHeight;

					// collisions
					var $bonusElementInCollisionWith = isInCollisionWithBonusElement(left, top);
					if (isIncollisionWithSn(left, top))
					{
						stop();
						return;
					} else if ($bonusElementInCollisionWith != null) {
						// add element
						$bonusElementInCollisionWith.css("background-color", "");
						$bonusElementInCollisionWith.previous = $headIcon;
						$headIcon.next = $bonusElementInCollisionWith;
						$headIcon = $bonusElementInCollisionWith;
						createNewBonusElement();
						freqUpdate += 0.5;

						applyCollisionWithBonusElement($bonusElementInCollisionWith);
					} else {
						$headIcon.next = $tailIcon;
						$tailIcon.previous = $headIcon;
						$tailIcon.css({"left": left + "px", "top": top + "px"});
						$headIcon = $tailIcon;
						$tailIcon = $tailIcon.next;
						$headIcon.next = null;
						$tailIcon.previous = null;
					}
				}

				setTimeout(function() {
					setTimeout(updateFunction, 1000/freqUpdate);
					updateTitle();
					$screenElement.on("click", function() { stop(); });
				}, rotationDuration);
			}
		});

		self.base.initialize();
		params.ready(true);
	}

	return {
		createViewModel: function(params, componentInfo) {
			return new StartPageHeaderComponentViewModel(params, componentInfo.element);
		}
	};
});
