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

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

		self.isVertical = baseModel.definition().WidthType == "Fixed";
		self.isClose = false;
		self.previousPosition = 0;
		self.previousParentSize = {width : 0, height : 0};

		self.$element = $(element);
		if (self.isVertical) {
			self.$splitterComp = $(element).find(".vertical-splitterComp");
			self.$closeButton = $(element).find(".vertical-closeButton");
		} else {
			self.$splitterComp = $(element).find(".horizontal-splitterComp");
			self.$closeButton = $(element).find(".horizontal-closeButton");
		}
		self.$splitterComp.css("display", "block");
		self.cursorType = self.$splitterComp.css("cursor");

		// function to avoid to handle vertical and horizontal splitter everywhere, special case are only there
		var getWidthValueOnComp = function(comp) {
			if (comp == null) return null;
			if (self.isVertical)
				return comp.definition().WidthValue;
			else
				return comp.definition().HeightValue;
		}

		var getWidthTypeOnComp = function(comp) {
			if (comp == null) return null;
			if (self.isVertical)
				return comp.definition().WidthType;
			else
				return comp.definition().HeightType;
		}

		var getLeftOffset = function() {
			if (self.leftAttachment == null)
				return 0;
			if (self.isVertical)
				return self.leftAttachment.definition().RightOffset + baseModel.definition().LeftOffset;
			else
				return self.leftAttachment.definition().BottomOffset + baseModel.definition().TopOffset;
		}

		var getRightOffset = function() {
			if (self.rightAttachment == null)
				return 0;
			if (self.isVertical)
				return self.rightAttachment.definition().LeftOffset + baseModel.definition().RightOffset;
			else
				return self.rightAttachment.definition().TopOffset + baseModel.definition().BottomOffset;
		}

		var setWidthValueOnComp = function(comp, value) {
			if (self.isVertical)
				comp.definition().WidthValue = value;
			else
				comp.definition().HeightValue = value;
		}

		var setWidthTypeOnComp = function(comp, type) {
			if (self.isVertical)
				comp.definition().WidthType = type;
			else
				comp.definition().HeightType = type;
		}

		var getLeftPosOnElement = function($e) {
			if (self.isVertical)
				return $e.offset().left;
			else
				return $e.offset().top;
		}

		var getWidthOnElement = function($e) {
			if (self.isVertical)
				return Math.max(0, $e.width());
			else
				return Math.max(0, $e.height());
		}

		var getParentWidth = function() {
			if (self.isVertical)
				return baseModel.getParentSize().width;
			else
				return baseModel.getParentSize().height;
		}

		if (self.isVertical) {
			self.leftAttachment = baseModel.getFirstVisibleLeftAttachment();
			self.rightAttachment = baseModel.getFirstVisibleRightAttachment();
		} else {
			self.leftAttachment = baseModel.getFirstVisibleTopAttachment();
			self.rightAttachment = baseModel.getFirstVisibleBottomAttachment();
		}

		if (self.leftAttachment) {
			self.$leftElement = self.leftAttachment != null && $(self.leftAttachment.element).find(".content");
			self.oldLeftWidthType = getWidthTypeOnComp(self.leftAttachment);
			self.oldLeftWidthValue = getWidthValueOnComp(self.leftAttachment);

			self.leftAttachment.definition().ready.subscribe(function(newVal) {
				// Need to do resize cause the direct way empeach that cause the parent size didn't change.
				// The direct way look at the parent size to not empeach the splitter to get reput at 
				// the same position each time we move it (=> immobile splitter)
				if (newVal)
					self.updateSize();
			});
		}

		if (self.rightAttachment) {
			self.$rightElement = self.rightAttachment != null && $(self.rightAttachment.element).find(".content");
			self.oldRightWidthType = getWidthTypeOnComp(self.rightAttachment);
			self.oldRightWidthValue = getWidthValueOnComp(self.rightAttachment);

			self.rightAttachment.definition().ready.subscribe(function(newVal) {
				if (newVal)
					self.updateSize();
			});
		}

		self.isLeft = params.Model.Left;
		self.isFree = false;
		if (self.leftAttachment == null || self.leftAttachment.definition().ComponentName == "noComponent") {
			self.$rightElement.css("z-index", 1);
			self.$element.css("z-index", 1);
			self.isFree = true;
			self.isLeft = false;
		}
		if (self.rightAttachment == null || self.rightAttachment.definition().ComponentName == "noComponent") {
			self.$leftElement.css("z-index", 1);
			self.$element.css("z-index", 1);
			self.isFree = true;
			self.isLeft = true;
		}

		self.base.onRefresh = function(obj) {
		}

		self.changeElementSize = function(comp, pxSize) {
			var pxSize = Math.max(pxSize, 0);

			// we have to change the widthType cause percentage can't stay correct and FitToContent is useless
			setWidthTypeOnComp(comp, "Fixed");
			setWidthValueOnComp(comp, pxSize);
		}

		self.getLeftPosition = function() {
			if (self.$leftElement != null)
				left = getLeftPosOnElement(self.$leftElement);
			else
				left = 0;
			return left + getLeftOffset();
		}

		self.getRightPosition = function() {
			var max = 0;
			if (self.rightAttachment != null) {
				max = getLeftPosOnElement(self.$rightElement) + getWidthOnElement(self.$rightElement) - getWidthOnElement(self.$element);
			} else {
				max = getParentWidth();
			}

			return max - getRightOffset();
		}

		self.changePosition = function(pos) {
			// compute min and max pos
			var min = self.getLeftPosition();
			var max = self.getRightPosition();

			if (pos < min) pos = min;
			if (pos > max) pos = max;

			// change left attachment size
			if (self.leftAttachment) {
				var leftSize = pos - getLeftPosOnElement(self.$leftElement) - getLeftOffset();
				self.changeElementSize(self.leftAttachment, leftSize);
			}

			// change right attachment size
			if (self.rightAttachment) {
				var rightRight = getLeftPosOnElement(self.$rightElement) + getWidthOnElement(self.$rightElement);
				var rightSize = rightRight - pos - getWidthOnElement(self.$element) - getRightOffset();
				self.changeElementSize(self.rightAttachment, rightSize);
			}

			baseModel.definition().gridPanel.resizeChildren();

			self.position = pos;
		}

		var mouseIsDown = false;
		self.$element.on("mousedown", function() {
			if (self.isClose)  return;
			mouseIsDown = true;
			return false;
		});

		$("body").on("mouseup", function() {
			if (!mouseIsDown) {
				return true;
			}

			mouseIsDown = false;
			return false;
		});

		$("body").on("mousemove", function(event){
			if (!mouseIsDown) {
				return true;
			}

			if (self.isVertical) {
				self.changePosition(event.pageX);
			} else {
				self.changePosition(event.pageY);
			}
			return false;
		});

		// to avoid resize in close button click
		self.$closeButton.on("mousedown", function() {return false;});

		self.close = function() {
			if (self.isClose) return;
			var currentPosition = getLeftPosOnElement(self.$element);
			self.previousPosition = currentPosition;

			if (self.isLeft) {
				self.changePosition(0);
			} else {
				self.changePosition(getParentWidth());
			}

			self.$splitterComp.css("cursor", "auto");
			self.isClose = true;
		}

		self.open = function() {
			if (!self.isClose) return;
			self.changePosition(self.previousPosition);
			self.$splitterComp.css("cursor", self.cursorType);
			self.isClose = false;
		}
		self.$closeButton.on("click", function() {
			if (self.isClose) {
				self.open();
			} else {
				self.close();
			}
		});

		params.baseModel.resizeFunctions[params.baseModel.resizeFunctions.length] = function(height,width) {
			var newParentSize = baseModel.getParentSize();
			if (!self.resizeAutorized)
			{
				self.resizeAutorized = true;
				return;
			}

			if (newParentSize.width == self.previousParentSize.width &&
				newParentSize.heigth == self.previousParentSize.heigth)
			{
				return;
			}

			self.updateSize();
		}

		self.updateSize = function() {
			var newParentSize = baseModel.getParentSize();
			self.previousParentSize = newParentSize;

			var newLeftWidthType = getWidthTypeOnComp(self.leftAttachment);
			var newLeftWidthValue = getWidthValueOnComp(self.leftAttachment);
			var newRightWidthType = getWidthTypeOnComp(self.rightAttachment);
			var newRightWidthValue = getWidthValueOnComp(self.rightAttachment);
			if (self.oldLeftWidthType == newLeftWidthType && self.oldLeftWidthValue == newLeftWidthValue &&
				self.oldRightWidthType == newRightWidthType && self.oldRightWidthValue == newRightWidthValue)
			{
				return;
			}

			// we reset everything except the close status
			var wasClose = self.isClose;
			if (wasClose) {
				self.open();
			}

			if (self.leftAttachment != null) {
				setWidthTypeOnComp(self.leftAttachment, self.oldLeftWidthType);
				setWidthValueOnComp(self.leftAttachment, self.oldLeftWidthValue);
			}

			if (self.rightAttachment != null) {
				setWidthTypeOnComp(self.rightAttachment, self.oldRightWidthType);
				setWidthValueOnComp(self.rightAttachment, self.oldRightWidthValue);
			}

			// we have to resize again, to take new type and value in consideration
			baseModel.definition().gridPanel.resizeChildren();

			if (self.position) {
				self.changePosition(self.position);
			}

			if (wasClose) {
				self.close();
			}
		}

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

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

});

