var SelectReplacements = [];
function collapseAllSelectReplacements() {
	for(var i=0,j=SelectReplacements.length; i<j; i++) {
		SelectReplacements[i].collapse();
	}
}

/**
 * Select replacement
 */
function SelectReplacement(node, settings) {
	//Constructor must called on class instance
	//if (this.constructor !== SelectReplacement) return new SelectReplacement(node, settings);
	
	SelectReplacements.push(this);

	this.settings = jQuery.extend({
		class_select: "off-screen",
		class_replacement: "select",
		class_dropdown: "select-dropdown",
		hide_empty: true
	}, settings);
	
	this.node_select = node;
	
	//Get all options, because will need to use them later
	var element_select = node.get(0);
	this.optionsObj = {};
	this.optionsArr = [];
	
	for(var i=0,j=element_select.options.length; i<j; i++) {
		var op = {
			value: element_select.options[i].value,
			text: element_select.options[i].text,
			li: null
		};
		this.optionsObj[element_select.options[i].value] = op;
		this.optionsArr.push(op);
	}
	
	this.value = node.val();
	
	this._replace();
	this._bindEventListeners();
}
SelectReplacement.prototype = {
	settings: null,
	
	html_select: '<div class="%class%"><a><span>%title%</span></a></div>',
	html_dropdown: '<div class="%class%"><ul>%list%</ul></div>',
	html_dropdown_item: '<li><span>%value%</span><a>%title%</a></li>',
	
	node_select: null,
	node_replacement: null,
	node_dropdown: null,
	node_dropdown_list: null,
	node_dropdown_items: {},
	
	optionsObj: {},
	optionsArr: [],
	
	value: '',
	hoveredItem: null,
	hoveredValue: null,
	expanded: false,
	
	expand: function () {
		if (this.expanded) return;
		collapseAllSelectReplacements();
		
		this._position();
		this.node_dropdown.show();
		this._position();
		
		this.expanded = true;
	},
	
	collapse: function () {
		if (!this.expanded) return;
		this.node_dropdown.hide();
		this.expanded = false;
	},
	
	toggle: function () {
		if (this.expanded) {
			this.collapse();
		} else {
			this.expand();
		}
	},
	
	setValue: function (val) {
		if (this.node_select.val() != val) {
			this.node_select.val(val);
			this.node_select.blur();
		}
		
		if (typeof this.optionsObj[val] != 'undefined') {
			this.value = val;
			this._markItemHover(val);
			this.node_replacement.find('SPAN').html(this.optionsObj[val].text || '&nbsp;');
		}
	},
	
	_markItemHover: function (ind) {
		if (this.hoveredItem) this.hoveredItem.removeClass('hover');
		
		if (typeof ind == 'number') {
			this.hoveredItem = this.optionsArr[ind].li;
			this.hoveredValue = this.optionsArr[ind].value;
		} else if (typeof ind == 'string') {
			this.hoveredItem = this.optionsObj[ind].li;
			this.hoveredValue = this.optionsObj[ind].value;
		} else {
			var ind = ind.data('val');
			this.hoveredItem = this.optionsObj[ind].li;
			this.hoveredValue = this.optionsObj[ind].value;
		}
		
		if (this.hoveredItem) {
			this.hoveredItem.addClass('hover');
		}
	},
	
	_position: function () {
		var pos = this.node_replacement.offset();
		var css = {
				left: pos.left+'px',
				top: pos.top+'px',
				width: this.node_replacement.width() + 'px'
			};
		
		this._markItemHover(this.value);	
		this.node_dropdown.css(css);
	},
	
	_bindEventListeners: function () {
		var self = this;
		
		//When real SELECT element value changes, need to change
		//value here too
		this.node_select.change(function () {
			self.setValue(jQuery(this).val());
		});
		
		this.node_replacement.click(function () {
			self.toggle();
			return false;
		});
		this.node_dropdown.click(function (evt) {
			evt.stopPropagation();
		});
		
		this.node_dropdown_items = this.node_dropdown.find('li');
		this.node_dropdown_items.each(function () {
			var li = jQuery(this);
			var val = li.find('span').html();
			li.data('val', val);
			self.optionsObj[val].li = li;
		});
		this.node_dropdown_items.hover(function () {
			self._markItemHover(jQuery(this).data('val'));
		});
		this.node_dropdown_items.click(function () {
			self.setValue(jQuery(this).data('val'));
			self.collapse();
		});
		
		jQuery(document.body).click(function () {
			self.collapse();
		});
	},
	
	_replace: function () {
		var className = this.node_select.attr('className').replace(/select\-replacement\s?/, '');
			className += ' ' + this.settings.class_replacement; 
		
		var html = this.html_select.replace('%class%', className)
								   .replace('%title%', this.optionsObj[this.value].text || '&nbsp;');
		
		var html_items = [];
		
		for(var i in this.optionsObj) {
			if (this.optionsObj[i].text) {
				if (!this.settings.hide_empty || i) {
					var html_item = this.html_dropdown_item.replace('%value%', i)
														   .replace('%title%', this.optionsObj[i].text || '&nbsp;');
					html_items.push(html_item);
				}
			}
		}
		
		var html_dropdown = this.html_dropdown.replace('%class%', this.settings.class_dropdown);
			html_dropdown = html_dropdown.replace('%list%', html_items.join(''));
		
		this.node_select.before(html);
		this.node_select.addClass(this.settings.class_select);
		this.node_replacement = this.node_select.prev();
		this.node_dropdown = jQuery(html_dropdown).appendTo(document.body);
	}
};

jQuery.fn.selectReplacement = function (settings) {
	jQuery(this).each(function () {
		//Can be applied only to SELECT elements
		if (jQuery(this).attr('tagName') != 'SELECT') return;
		
		var select = jQuery(this);
		var replacement = select.data('selectReplacement');
		
		if (!replacement) {
			replacement = new SelectReplacement(select, settings || {});
			select.data('selectReplacement', replacement);
		}
	});
};

jQuery.fn.checboxReplacement = function () {
	jQuery(this).each(function () {
		var html = jQuery('<div class="checkbox-replacement"></div>');
		if (jQuery(this).hasClass('checkbox-replacement-2')) {
			html.addClass('checkbox-replacement-2');
		}
		
		jQuery(this).after(html);
		jQuery(this).addClass('off-screen');
		
		var self = this;
		var ch = jQuery(this).next();
			ch.click(function () {
				if ($(self).attr('type') == 'checkbox') {
					//checkbox
					self.checked = !self.checked;
				} else {
					//radio
					self.checked = true;
				}
				$(self).change();
			});
		
		jQuery(this).change(onChange).click(onChange);
		jQuery(this).data('replacementOnChange', onChange);
		
		function onChange () {
			if (self.checked) {
				ch.addClass('checked');
				if ($(self).attr('type') == 'radio') {
					ch.siblings('div.checkbox-replacement').removeClass('checked');
				}
			} else {
				ch.removeClass('checked');
			}
		}
		
		onChange();
	});
};

jQuery.fn.labelOverflow = function () {
	jQuery(this).each(function () {
		if ($(this).parent().hasClass('label-normal') || $(this).parent().hasClass('label-line')) return;
		
		var inp = jQuery(this);
		var label = inp.prev();
		
		if (label.attr('tagName') != 'LABEL') return;
		
		function hideLabel () {
			label.hide();
		}
		function updateLabelVisiblity () {
			if (inp.val().replace(/^\s+|\s+$/, '') != '') {
				label.hide();
			} else {
				label.show();
			}
		}
		
		inp.change(updateLabelVisiblity).blur(updateLabelVisiblity).focus(hideLabel);
		updateLabelVisiblity();
	});
};


/**
 * Validation plugin
 */
jQuery.validator = {
	rules: {},
	
	notEmpty: function (val) {
		return (val && val != '' ? true : false);
	},
	isEmail: function (val) {
		return val.match(/^.+\@(\[?)[a-zA-Z0-9\-\.]+\.([a-zA-Z]{2,3}|[0-9]{1,3})(\]?)$/);
	},
	isPhone: function (val) {
		return val.match(/^\+?[0-9]*$/);
	},
	isAlphabet: function (val) {
		return val.match(/^([a-zA-Z ])+$/);
	},
	isDate: function (month, day, year, age) {
      	
      	if(
      		month == '' &&
      		day == '' &&
      		year == ''
      	)
      	{
      		return true;
      	}

      	// Attention! Javascript consider months in the range 0 - 11
      	month -= 1;
      	// This instruction will create a date object
      	source_date = new Date(year,month,day);

		if(year != source_date.getFullYear())
		{
		   return false;
		}
		
		if(month != source_date.getMonth())
		{
		   return false;
		}
		
		if(day != source_date.getDate())
		{
		   return false;
		}
		
		if(
			typeof age != 'undefined' &&
			age != false
		)
		{
			current_date = new Date();
			if(
				parseInt(year) > parseInt(current_date.getFullYear()) - parseInt(age))
			{
				return false;
			} else if (parseInt(year) == parseInt(current_date.getFullYear()) - parseInt(age)) {
				if(parseInt(month) > parseInt(current_date.getMonth()))
				{
					return false;
				} else if(parseInt(month) == parseInt(current_date.getMonth())) {
					if(parseInt(day) > parseInt(current_date.getDate()))
					{
						return false;
					}
				}
			}
		}
		return true;
	},
	valueMatch: function (val, params, inp) {
		return (params.match && params.match.val() == val);
	},
	valueLength: function (val, params) {
		var l = val.length;
		if (typeof params.min != 'undefined' && l < params.min) return false;
		if (typeof params.max != 'undefined' && l > params.max) return false;
		return true; 
	},
	
	validateField: function (field, allowErrorCallback, allowSuccessCallback) {
		var id = jQuery.data($(field).get(0));
		var success = true;
		
		var val = jQuery.validator.rules[id].node.val();
			val = val.replace(/^\s+|\s+$/, '');
		var rules = jQuery.validator.rules[id].rules;
		
		for(var n=0; n<rules.length; n++) {
			if (!rules[n].fn(val, rules[n], jQuery.validator.rules[id].node)) {
				if (allowErrorCallback && rules[n].failure) rules[n].failure(jQuery.validator.rules[id], rules[n]);
				success = false;
			} else {
				if (allowSuccessCallback && rules[n].success) rules[n].success(jQuery.validator.rules[id], rules[n]);
			}
		}
		
		return true;
	},
	
	validate: function () {
		var success = true;
		
		for(var i in jQuery.validator.rules) {
			var val = jQuery.validator.rules[i].node.val();
				val = val.replace(/^\s+|\s+$/, '');
			var rules = jQuery.validator.rules[i].rules;
			
			for(var n=0; n<rules.length; n++) {
				if (!rules[n].fn(val, rules[n], jQuery.validator.rules[i].node)) {
					if (rules[n].failure) rules[n].failure(jQuery.validator.rules[i], rules[n]);
					success = false;
					break;
				} else {
					if (rules[n].success) rules[n].success(jQuery.validator.rules[i], rules[n]);
				}
			}
		}
		
		return success;
	}
};

jQuery.fn.addValidationRule = function (rule) {
	$(this).each(function () {
		var id = jQuery.data($(this).get(0));
		
		if (!jQuery.validator.rules[id]) {
			jQuery.validator.rules[id] = {
				node: $(this),
				rules: []
			};
		}
		
		jQuery.validator.rules[id].rules.push(rule);
	});
};



jQuery(document).ready(function () {
	jQuery('div.form select.select-replacement').selectReplacement({class_dropdown: "select-dropdown form-select-dropdown"});
	jQuery('select.select-replacement').selectReplacement();
	jQuery('input.checkbox-replacement').checboxReplacement();
	
	//Labels as input values
	jQuery('div.form input.text').labelOverflow();
});