﻿/// <reference name="MicrosoftAjax.js"/>

Type.registerNamespace("Renins");

Renins.TrackBar = function(element) {
	Renins.TrackBar.initializeBase(this, [element]);
	this._track = null;
	this._leftBlock = null;
	this._rightBlock = null;
	this._begun = null;
	this._begunLeftBlock = null;
	this._begunRightBlock = null;
	this._begunInput = null;
	this._width = 0;
	this._begunWidth = 0;

	this._dragElemMouseDownDelegate = null;
	this._mouseUpDelegate = null;
	this._mouseMoveDelegate = null;
	this._mouseClickDelegate = null;
	this._inputBlurDelegate = null;
	this._inputEnterDelegate = null;
	this._inputKeyDownDelegate = null;
	this._inputKeyPressDelegate = null;

	this._isMouseDown = false;

	this._state = null;

	this._isValidKey = false;
	this._isEnterKey = false;

	this._min = 0;
	this._max = 0;
	this._value = 0;
	this._fullMax = 0;

	this._inputClass = "";
	this._inputOutOfRangeClass = "";

	this._offsetG = 0;
	this._offsetL = 0;
	this._offset = 0;

	this._wasMoving = false;
}

Renins.TrackBar.prototype = {
	get_track: function() { return this._track; },
	set_track: function(value) { this._track = value; },

	get_leftBlock: function() { return this._leftBlock; },
	set_leftBlock: function(value) { this._leftBlock = value; },

	get_rightBlock: function() { return this._rightBlock; },
	set_rightBlock: function(value) { this._rightBlock = value; },

	get_begun: function() { return this._begun; },
	set_begun: function(value) { this._begun = value; },

	get_begunLeftBlock: function() { return this._begunLeftBlock; },
	set_begunLeftBlock: function(value) { this._begunLeftBlock = value; },

	get_begunRightBlock: function() { return this._begunRightBlock; },
	set_begunRightBlock: function(value) { this._begunRightBlock = value; },

	get_begunInput: function() { return this._begunInput; },
	set_begunInput: function(value) { this._begunInput = value; },

	get_width: function() { return this._width; },
	set_width: function(value) { this._width = value; },

	get_begunWidth: function() { return this._begunWidth; },
	set_begunWidth: function(value) { this._begunWidth = value; },

	get_state: function() { return this._state; },
	set_state: function(value) { this._state = value; },

	get_min: function() { return this._min; },
	set_min: function(value) { this._min = value; },

	get_max: function() { return this._max; },
	set_max: function(value) { this._max = value; },

	get_fullMax: function() { return this._fullMax; },
	set_fullMax: function(value) { this._fullMax = value; },

	get_value: function() { return this._value; },
	set_value: function(value) { this._value = value; },

	get_inputClass: function() { return this._inputClass; },
	set_inputClass: function(value) { this._inputClass = value; },

	get_inputOutOfRangeClass: function() { return this._inputOutOfRangeClass; },
	set_inputOutOfRangeClass: function(value) { this._inputOutOfRangeClass = value; },

	add_valueChanged: function(handler) { this.get_events().addHandler("valueChanged", handler); },
	remove_valueChanged: function(handler) { this.get_events().removeHandler("valueChanged", handler); },

	initialize: function() {
		Renins.TrackBar.callBaseMethod(this, 'initialize');

		var element = this.get_element();

		// Add custom initialization here
		if (this._dragElemMouseDownDelegate == null) {
			this._dragElemMouseDownDelegate = Function.createDelegate(this, this._onMouseDownHandler);
		}
		$addHandler(this.get_begunLeftBlock(), "mousedown", this._dragElemMouseDownDelegate);
		$addHandler(this.get_begunRightBlock(), "mousedown", this._dragElemMouseDownDelegate);

		if (this._mouseUpDelegate == null) this._mouseUpDelegate = Function.createDelegate(this, this._onMouseUpHandler);
		$addHandler(document, "mouseup", this._mouseUpDelegate);

		if (this._mouseMoveDelegate == null) this._mouseMoveDelegate = Function.createDelegate(this, this._onMouseMoveHandler);
		$addHandler(document, "mousemove", this._mouseMoveDelegate);

		if (this._mouseClickDelegate == null) this._mouseClickDelegate = Function.createDelegate(this, this._onMouseClick);
		$addHandler(this.get_begunLeftBlock(), "click", this._mouseClickDelegate);
		$addHandler(this.get_begunRightBlock(), "click", this._mouseClickDelegate);
		$addHandler(this.get_leftBlock(), "click", this._mouseClickDelegate);
		$addHandler(this.get_rightBlock(), "click", this._mouseClickDelegate);
		$addHandler(this.get_track(), "click", this._mouseClickDelegate);

		if (this._inputBlurDelegate == null) this._inputBlurDelegate = Function.createDelegate(this, this._onBlurHandler);
		$addHandler(this.get_begunInput(), "blur", this._inputBlurDelegate);

		if (this._inputEnterDelegate == null) this._inputEnterDelegate = Function.createDelegate(this, this._onInputEnterHandler);
		$addHandler(this.get_begunInput(), "focus", this._inputEnterDelegate);

		if (this._inputKeyDownDelegate == null) this._inputKeyDownDelegate = Function.createDelegate(this, this._onInputKeyDownHandler);
		$addHandler(this.get_begunInput(), "keydown", this._inputKeyDownDelegate);

		if (this._inputKeyPressDelegate == null) this._inputKeyPressDelegate = Function.createDelegate(this, this._onInputKeyPressHandler);
		$addHandler(this.get_begunInput(), "keypress", this._inputKeyPressDelegate);

		var state = document.createElement("input");
		state.type = "hidden";
		state.id = state.name = element.id + "_state";
		element.appendChild(state);
		this.set_state(state);
	},

	dispose: function() {
		//Add custom dispose actions here
		if (this._dragElemMouseDownDelegate != null) {
			Sys.UI.DomEvent.removeHandler(this.get_begunLeftBlock(), "mousedown", this._dragElemMouseDownDelegate);
			Sys.UI.DomEvent.removeHandler(this.get_begunRightBlock(), "mousedown", this._dragElemMouseDownDelegate);
			delete this._dragElemMouseDownDelegate;
		}

		if (this._mouseUpDelegate != null) {
			Sys.UI.DomEvent.removeHandler(document, "mouseup", this._mouseUpDelegate);
			delete this._mouseUpDelegate;
		}

		if (this._mouseMoveDelegate != null) {
			Sys.UI.DomEvent.removeHandler(document, "mousemove", this._mouseMoveDelegate);
			delete this._mouseMoveDelegate;
		}

		if (this._mouseClickDelegate != null) {
			Sys.UI.DomEvent.removeHandler(this.get_begunLeftBlock(), "click", this._mouseClickDelegate);
			Sys.UI.DomEvent.removeHandler(this.get_begunRightBlock(), "click", this._mouseClickDelegate);
			Sys.UI.DomEvent.removeHandler(this.get_leftBlock(), "click", this._mouseClickDelegate);
			Sys.UI.DomEvent.removeHandler(this.get_rightBlock(), "click", this._mouseClickDelegate);
			delete this._mouseClickDelegate;
		}

		if (this._inputBlurDelegate != null) {
			Sys.UI.DomEvent.removeHandler(this.get_begunInput(), "blur", this._inputBlurDelegate);
			delete this._inputBlurDelegate;
		}

		if (this._inputEnterDelegate != null) {
			Sys.UI.DomEvent.removeHandler(this.get_begunInput(), "focus", this._inputEnterDelegate);
			delete this._inputEnterDelegate;
		}

		if (this._inputKeyDownDelegate != null) {
			$removeHandler(this.get_begunInput(), "keydown", this._inputKeyDownDelegate);
			delete this._inputKeyDownDelegate;
		}

		if (this._inputKeyPressDelegate != null) {
			$removeHandler(this.get_begunInput(), "keypress", this._inputKeyPressDelegate);
			delete this._inputKeyPressDelegate;
		}

		Renins.TrackBar.callBaseMethod(this, 'dispose');
	},

	_onValueChanged: function(e) {
		var h = this.get_events().getHandler("valueChanged");
		if (h) h(this, e);
	},

	_insertSpaces: function(value) {
		///<summary>Через каждые три символа вставляет пробелы в числа.</summary>
		value = value.toString().trim().split('');
		var result = "";
		var j = 0;
		for (var i = value.length - 1; i >= 0; i--) {
			result = value[i] + result;
			j++;
			if (j == 3) {
				result = " " + result;
				j = 0;
			}
		}
		return result.trim();
	},

	_replaceSpaces: function(value) {
		///<summary>Удаляет все пробелы из строки</summary>
		return value.replace(/\s+/g, '');
	},

	_getNextValue: function(direction) {
		var newValue = 0;
		if (direction != 0) {
			var max = this.get_max();
			var min = this.get_min();
			var value = this.get_value();
			var percent = parseInt((max - min) / 100);
			newValue = direction < 0 ? value - percent : value + percent;
			//if (min <= newValue && newValue <= max) this.setValue(newValue);
		}
		else newValue = this.get_value();
		return newValue;
	},

	_updateInnerState: function() {
		var min = this.get_min();
		var max = this.get_max();
		var value = this.get_value();
		var state = this.get_state();
		state.value = String.format("min={0};max={1};value={2}", min, max, value);
	},

	_setMouseDown: function(value) {
		this._isMouseDown = value;
	},

	_getMouseDown: function() {
		return this._isMouseDown;
	},

	_debugText: function(message) {
		//this.get_begunInput().value = message;
		//$get("divD").innerHTML = message;
	},

	defPosition: function(event) {
		var x = y = 0;
		if (Sys.Browser.agent == Sys.Browser.InternetExplorer) {
			x = event.clientX + document.documentElement.scrollLeft + document.body.scrollLeft;
			y = event.clientY + document.documentElement.scrollTop + document.body.scrollTop;
		}
		else {
			x = event.clientX + (window.scrollX ? window.scrollX : 0);
			y = event.clientY + (window.scrollY ? window.scrollY : 0);
		}
		return { x: x, y: y };
	},

	absPosition: function(obj) {
		var x = y = 0;
		while (obj) {
			x += obj.offsetLeft;
			y += obj.offsetTop;
			obj = obj.offsetParent;
		}
		return { x: x, y: y };
	},

	_move: function(offset) {
		this.get_begun().style.left = offset + "px";
	},

	_setTextValue: function(value) {
		this.get_begunInput().value = this._insertSpaces(value);
		this._onValueChanged(Sys.EventArgs.Empty);
	},

	_onMouseDownHandler: function(e) {
		if (e.preventDefault) e.preventDefault();
		e.returnValue = false;
		this._setMouseDown(true);
		this._target = e.target;
		this._offsetG = this.absPosition(this.get_element()).x;
		this._offsetL = this.defPosition(e).x - this.absPosition(this.get_begun()).x;
	},

	_onMouseUpHandler: function(e) {
		if (e.preventDefault) e.preventDefault();
		e.returnValue = false;
		if (this._getMouseDown()) {
			this._setMouseDown(false);
		}
	},

	_onMouseMoveHandler: function(e) {
		if (e.preventDefault) e.preventDefault();
		e.returnValue = false;
		if (this._getMouseDown()) {
			this._wasMoving = true;
			this._offset = this.defPosition(e).x - this._offsetG - this._offsetL;
			var w = this.get_width();
			var wS = this.get_begunWidth();
			var max = this.get_max();
			var min = this.get_min();
			var isNeedMove = this._offset >= 0 && this._offset <= w - wS;
			if (isNeedMove) {
				this.get_begunInput().className = this.get_inputClass();
				this._move(this._offset);
				var value = parseInt(this._offset * (max - min) / (w - wS) + min);
				this.set_value(value);
				this._updateInnerState();
				this._setTextValue(value);
				//this._debugText("; offset = " + this._offset + "; offsetL = " + this._offsetL + "; offsetG = " + this._offsetG);
			}
		}
	},

	_onBlurHandler: function(e) {
		var input = this.get_begunInput();
		var value = 0;
		if (input.value.trim().length == 0) {
			value = parseInt((this.get_max() + this.get_min()) / 2);
		}
		else {
			value = parseInt(input.value);
			if (this.get_fullMax() > 0 && value > this.get_fullMax()) {
				value = this.get_fullMax();
			}
		}
		this.setValue(value);
	},

	_onInputEnterHandler: function(e) {
		var input = this.get_begunInput();
		input.value = this._replaceSpaces(input.value);
		if (input.createTextRange) {
			//Для IE переводим фокус в конец
			var r = input.createTextRange();
			r.collapse(false);
			r.select();
		}
	},

	_onInputKeyDownHandler: function(e) {
		if (e.keyCode == Sys.UI.Key.backspace
            || e.keyCode == Sys.UI.Key.del
            || e.keyCode == Sys.UI.Key.enter
            || e.keyCode == Sys.UI.Key.home
            || e.keyCode == Sys.UI.Key.end
            || e.keyCode == Sys.UI.Key.left
            || e.keyCode == Sys.UI.Key.right
            || e.keyCode == Sys.UI.Key.tab
            || (e.keyCode >= 48 && e.keyCode <= 57)
            || (e.keyCode >= 96 && e.keyCode <= 105)) {

			this._isValidKey = true;
			this._isEnterKey = e.keyCode == Sys.UI.Key.enter;
		}
		else {
			this._isValidKey = false;
		}
	},
	_onInputKeyPressHandler: function(e) {
		if (!this._isValidKey) e.preventDefault();
		else {
			if (this._isEnterKey) {
				var value;
				if (e.target.value.trim().length == 0) {
					value = parseInt((this.get_max() + this.get_min()) / 2);
				}
				else {
					value = parseInt(e.target.value);
					if (this.get_fullMax() > 0 && value > this.get_fullMax()) {
						value = this.get_fullMax();
					}
				}
				this.setValue(value);
				e.target.value = this._replaceSpaces(e.target.value);
				e.preventDefault();
				e.stopPropagation();
			}
		}
	},

	_onMouseClick: function(e) {
		if (!this._wasMoving) {
			var newValue = 0;
			if (e.target.id == this.get_begunLeftBlock().id) {
				newValue = this._getNextValue(-1);
			}
			else if (e.target.id == this.get_begunRightBlock().id) {
				newValue = this._getNextValue(1);
			}
			else if (e.target.id == this.get_leftBlock().id) {
				newValue = this.get_min();
			}
			else if (e.target.id == this.get_rightBlock().id) {
				newValue = this.get_max();
			}
			else if (e.target.id == this.get_track().id) {
				//alert("begun click");
				var max = this.get_max();
				var min = this.get_min();
				var w = this.get_width();
				newValue = e.offsetX * (max - min) / w + min;
			}
			if (this.get_min() <= newValue && newValue <= this.get_max()) this.setValue(newValue);
		}
		this._wasMoving = false;
	},

	updateView: function() {
		///<summary>Перерисовывает вид в зависимости от значений</summary>
		var min = this.get_min();
		var max = this.get_max();
		var value = this.get_value();
		var w = this.get_width();
		var wS = this.get_begunWidth();
		var input = this.get_begunInput();
		var offset = 0;
		var className = "";
		if (min <= value && value <= max) {
			className = this.get_inputClass();
			offset = parseInt((w - wS) * (value - min) / (max - min));
		}
		else {
			className = this.get_inputOutOfRangeClass();
			offset = value < min ? 0 : w - wS;
		}
		if (input.className != className) input.className = className;
		var leftBlockText = this._insertSpaces(min);
		var rightBlockText = this._insertSpaces(max);
		if (this.get_leftBlock().innerHTML != leftBlockText)
			this.get_leftBlock().innerHTML = leftBlockText;
		if (this.get_rightBlock().innerHTML != rightBlockText)
			this.get_rightBlock().innerHTML = rightBlockText;
		this._setTextValue(value);
		this._move(offset);
	},

	setValue: function(value) {
		///<summary>Устанавливает текущее значение</summary>
		///<param name="value">Значение</param>
		this.set_value(parseInt(value));
		this._updateInnerState();
		this.updateView();
	},

	setValues: function(min, max, value) {
		///<summary>Устанавливает границы, текущее значение и перерисовывает контрол</summary>
		///<param name="min">Нижная граница</param>
		///<param name="max">Верхняя граница</param>
		///<param name="value">Значение</param>
		if (min < max) {
			this.set_min(min);
			this.set_max(max);
			this.set_value(value);
			this._updateInnerState();
			this.updateView();
		}
	},

	restoreState: function(min, max, value) {
		this.setValues(min, max, value);
	}
}
Renins.TrackBar.registerClass('Renins.TrackBar', Sys.UI.Control);

if (typeof (Sys) !== 'undefined') Sys.Application.notifyScriptLoaded();

