var getWindowScrollPosition = function() {
  var scrollX = 0;
  var scrollY = 0;
  if(typeof(window.pageYOffset) == 'number') {
	//Netscape compliant
	scrollY = window.pageYOffset;
	scrollX = window.pageXOffset;
  } else if(document.body && (document.body.scrollLeft || document.body.scrollTop)) {
	//DOM compliant
	scrollY = document.body.scrollTop;
	scrollX = document.body.scrollLeft;
  } else if(document.documentElement && (document.documentElement.scrollLeft || document.documentElement.scrollTop)) {
	//IE6 standards compliant mode
	scrollY = document.documentElement.scrollTop;
	scrollX = document.documentElement.scrollLeft;
  }
  return {x: scrollX, y:scrollY};
}

basicHSpyExtension = {
	// set list items as bookmarks for given elements
	// this - jQuery set of bookmarks
	// blocks - jQuery set of bookmarks content
	// [defaultIndex] - index of implicitly active bookmark, starting with 0
	bookmarksFor: function(blocks,defaultIndex) {
		if (!this.length || !blocks.length || this.length != blocks.length) {
			return false;
		}
		if (defaultIndex === undefined) {
			defaultIndex = 0;
		} else if (defaultIndex > blocks.length) {
			defaultIndex = blocks.length;
		}
		// bookmarks default appearance
		this.removeClass('prev-sibl').find('a').removeClass('prev-sibl');
		this.removeClass('active').addClass('inactive').find('a').removeClass('active').addClass('inactive');
		$(this).slice(0,defaultIndex).addClass('prev-sibl').find('a').addClass('prev-sibl');
		$(this[defaultIndex]).removeClass('inactive').addClass('active').find('a').removeClass('inactive').addClass('active');
		// blocks default appearance
		blocks.hide();
		$(blocks[defaultIndex]).show();
		for (var i = 0; i < this.length; i++) {
			// disable anchors inside bookmarks
			$(this[i]).find('a').click(function(e) {
				e.preventDefault();
				$(this).blur();
			})
			$(this[i]).bind('click',{blocks: blocks, bookmarks: this, index: i}, function(e) {
				// active bookmark with given index only
				e.data.bookmarks.removeClass('prev-sibl').find('a').removeClass('prev-sibl');
				e.data.bookmarks.removeClass('active').addClass('inactive').find('a').removeClass('active').addClass('inactive');
				$(e.data.bookmarks).slice(0,e.data.index).addClass('prev-sibl').find('a').addClass('prev-sibl');
				$(e.data.bookmarks[e.data.index]).removeClass('inactive').addClass('active').find('a').removeClass('inactive').addClass('active');
				// show block with given index only
				e.data.blocks.hide();
				$(e.data.blocks[e.data.index]).show();
			});
		}
		return $(this);
	},
	inputAutofocus: function(priority) {
		// focus priority of this element
		$(this).data('_inputFocusPriority',priority);

		var prevNodes = $('.js-input-autofocus');
		var highestPriority = priority;
		var highestPriorityNode = this;

		// find previous node with higher or the same priority
		for (var i = 0; i < prevNodes.length; i++) {
			if ($(prevNodes[i]).data('_inputFocusPriority') >= highestPriority) {
				highestPriority = $(prevNodes[i]).data('_inputFocusPriority');
				highestPriorityNode = prevNodes[i];
			}
		}

		$(function() {
			$(highestPriorityNode).unlabelNodes();
		});
		$(highestPriorityNode).focus();

		// add autofocus class
		$(this).addClass('js-input-autofocus');
	},
	// input nodes label
	// [labelWith] - string or jQuery containing a label text
	labelNodes: function(labelWith) {
		var labelText;
		for (var i = 0; i < this.length; i++) {
			if (typeof labelWith == 'undefined') {
				// label with data if defined
				if ($(this[i]).data('_labelText')) {
					labelText = $(this[i]).data('_labelText');
				// label with appropriate label tag
				} else {
					labelText = $("label[for='"+$(this[i]).attr('id')+"']").text();
					$(this[i]).data('_labelText',labelText);
				}
			// label with given string
			} else if (typeof labelWith == 'string') {
				labelText = labelWith;
				$(this[i]).data('_labelText',labelText);
			// label with given jQuery object
			} else if (typeof labelWith == 'object') {
				labelText = labelWith.text();
				$(this[i]).data('_labelText',labelText);
			}
			// label it only if field is empty
			if (!$(this[i]).val().length) {
				$(this[i]).val(labelText);
			}
		}
		return $(this);
	},
	// set absolute position of given element to center of the viewport or to upper left corner if the viewport is too small
	onTopWindowLocate: function() {
		// locate to upper left corner of current window scroll position
		var scroll = getWindowScrollPosition();
		var offsetX = scroll.x;
		var offsetY = scroll.y;
		// then move to the center of the window if possible
		var viewportWidth = $(window).width();
		var viewportHeight = window.innerHeight ? window.innerHeight : $(window).height();
		if (viewportWidth >= $(this).width()) {
			offsetX += viewportWidth/2 - $(this).width()/2;
		}
		if (viewportHeight >= $(this).height()) {
			offsetY += viewportHeight/2 - $(this).height()/2;
		}
		$(this).css('position','absolute');
		$(this).css('left',offsetX);
		$(this).css('top',offsetY);

		return $(this);
	},
	// set absolute position of current window element, function is intended as event listener
	onTopWindowRelocate: function() {
		if (typeof basicHSpyExtension.onTopWindow == 'object') {
			basicHSpyExtension.onTopWindow.onTopWindowLocate();
		}
	},
	// refresh origin position of given element
	onTopWindowUnlocate: function() {
		$(this).css('position','relative');
		$(this).css('left','auto');
		$(this).css('top','auto');

		return $(this);
	},
	// use given element as on-top window and open it
	onTopWindowOpen: function(closeOnCoverClick) {
		// style window frame
		var windowFrame = $('#frame-window');
		windowFrame.windowFrameRedraw();
		var windowHolder = $('#frame-window-holder');
		// set window closers
		if (typeof closeOnCoverClick == 'undefined' || closeOnCoverClick == true) {
			windowFrame.click(this.onTopWindowClose); // cover
		}
		$(this).find('.window-closer').click(this.onTopWindowClose); // other possible elements
		$(this).find('.window-closer').click(function(e) {
			e.preventDefault();
		});
		// exclude window itself from closers
		$(this).click(function(e) {
			e.stopPropagation();
		});
		// add holder to the origin element place (after it)
		$(this).after($('<div></div>').attr('id','holder-'+$(this).attr('id')));
		// append window to the new holder
		windowHolder.empty();
		$(this).appendTo(windowHolder);
		// show window
		$(this).show();
		windowFrame.show();
		// set correct window position
		$(this).onTopWindowLocate();
		basicHSpyExtension.onTopWindow = $(this); // current on-top window
		// bind window redrawing on various events
		$(function() {
			windowFrame.windowFrameRedraw();
		});
		$(window).bind('resize',this.windowFrameRedraw);
		$(window).bind('resize scroll',this.onTopWindowRelocate);

		return $(this);
	}
	,
	// close current on-top window and remove it to its origin place
	onTopWindowClose: function() {
		if (!typeof basicHSpyExtension.onTopWindow == 'object') {
			return false;
		}
		var windowFrame = $('#frame-window');
		var windowHolder = $('#frame-window-holder');
		var originWindowHolder = $('#holder-' + basicHSpyExtension.onTopWindow.attr('id'));
		// move window to the origin place
		originWindowHolder.before(basicHSpyExtension.onTopWindow);
		originWindowHolder.remove();
		windowHolder.empty();
		// close window
		windowFrame.hide();
		basicHSpyExtension.onTopWindow.hide();
		basicHSpyExtension.onTopWindow.onTopWindowUnlocate();
		delete basicHSpyExtension.onTopWindow;
		$(window).unbind('resize scroll',this.onTopWindowRelocate);
		$(window).unbind('resize',this.windowFrameRedraw);

		return $(this);
	}
	,
	// renews default label
	renewLabels: function() {
		// only if field is empty
		var labelText;
		for (var i = 0; i < this.length; i++) {
			if (!$(this[i]).val().length) {
				labelText = $(this[i]).data('_labelText');
				if (labelText) {
					$(this[i]).val(labelText);
				} else {
					$(this[i]).labelNodes();
				}
			}
		}
		return $(this);
	},
	// activate bookmark with given index
	// [index] - index of bookmark, starting with 0
	showBookmark: function(index) {
		if (index == undefined) {
			index = 0;
		}
		if (typeof index == 'string') {
			bookmark = $(this).filter(index).eq(0);
			bookmark.removeClass('hidden').show();
			bookmark.click();
		} else {
			$(this[index]).removeClass('hidden').show();
			$(this[index]).click();
		}
		return $(this);
	},
	// removes default label
	unlabelNodes: function () {
		var labelText;
		for (var i = 0; i < this.length; i++) {
			labelText = $(this[i]).data('_labelText');
			if ($(this[i]).val() == labelText) {
				$(this[i]).val('');
			}
		}
		return $(this);
	},
	// set window frame height due to current viewport and document sizes
	windowFrameRedraw: function() {
		var viewportHeight = window.innerHeight ? window.innerHeight : $(window).height();
		if ($('body').height() < viewportHeight) {
			$('#frame-window').height(viewportHeight);
		} else {
			$('#frame-window').height($('body').height());
		}
	}
}
$.fn.extend(basicHSpyExtension);

$(function() {
	/* [[common forms]] */

	// input node on-focus selection
	$('.js-input-selectable').bind('click focus', function() {
		$(this).select();
	});
	// select with form submit function
	$('.js-select-autosubmit').change(function() {
		$(this).parents('form').eq(0).submit();
	});
	$('.js-submit-controller').click(function(e) {
		$(this).parents('form').eq(0).submit();
	});
	$('.js-submit-controller .submit').click(function(e) {
		e.stopPropagation();
	});
	// input node label
	$('.js-input-label').labelNodes();
	$('.js-input-label').focus(function() { // removes default label on field focus
		$(this).unlabelNodes();
	});
	$('.js-input-label').blur(function() { // renews default label on field blur
		$(this).renewLabels();
	})
	$('form').filter(function() { // removes default labels on form submit
		return $(this).find(':input').filter(function() {
			return $(this).data('_labelText') ? true : false;
		}).length;
	}).submit(function() {
		$(this).find(':input').unlabelNodes();
	});

	/* [[common elements]] */

	// JS hovers
	$('.js-rollover-area').hover(function() {
		$(this).find('.js-rollover-content').eq(0).show();
	}, function() {
		$(this).find('.js-rollover-content').eq(0).hide();
	});
	// JS anchors with target blank
	$('.js-target-blank').click(function() {
		return !window.open($(this).attr('href'));
	});
	// JS disabled anchors
	$('.js-target-disabled').click(function() {
		return false;
	});
	$('.js-hidden').css('display','none');
	// // JS anchors with immediate blur
	$('.js-onclick-blur').click(function() {
		$(this).blur();
	});
});