function CornholioGUI() {
	var soul = this;
	
	this.helper = new CornholioGUIHelper();
	
	this.children = {participants: new CornholioGUIParticipants()};
	
	this.initEditor = function(elem, options) {
		valid_elements    = '@[title],strong/b,em,a[href|target=_blank],p,h1,h2,h3,h4,h5,h6,ul,ol,li,br';
		
		theme_advanced_buttons1 = 'formatselect,|,mybutton,bold,italic,|,bullist,numlist,|,link,unlink,|,undo,redo,code';
		theme_advanced_buttons2 = '';
		theme_advanced_buttons3 = '';
		
		plugins = 'paste';
		
		forced_root_block = 'p';
		force_br_newlines = false;
		force_p_newlines  = true;

		if (!empty(options)) {
			valid_elements 
				= options.valid_elements != undefined 
				? options.valid_elements
				: valid_elements;

			theme_advanced_buttons1 
				= options.theme_advanced_buttons1 != undefined 
				? options.theme_advanced_buttons1
				: theme_advanced_buttons1;

			theme_advanced_buttons2 
				= options.theme_advanced_buttons2 != undefined 
				? options.theme_advanced_buttons2
				: '';

			theme_advanced_buttons3 
				= options.theme_advanced_buttons3 != undefined 
				? options.theme_advanced_buttons3
				: '';
			
			plugins 
				= options.plugins != undefined 
				? options.plugins
				: plugins;

			if (!empty(options.force_br_newlines)) {
				force_br_newlines = true;
				force_p_newlines  = false;
				forced_root_block = '';
			}
		}

		elem.tinymce({
			plugins : plugins,
			paste_preprocess : function(pl, o) {
				o.content = o.content.replace(/<!--.*-->/, "");
				o.content = o.content.replace(/<p>&nbsp;<\/p>/, "");
		    },
			valid_elements    : valid_elements,
			forced_root_block : forced_root_block,
			force_br_newlines : force_br_newlines,
			force_p_newlines  : force_p_newlines,
			remove_redundant_brs : true,
			theme : "advanced", 
			skin : "o2k7",
			language : "ru",
			theme_advanced_buttons1 : theme_advanced_buttons1, 
			theme_advanced_buttons2 : theme_advanced_buttons2,
			theme_advanced_buttons3 : theme_advanced_buttons3,
			theme_advanced_toolbar_location : "top", 
			theme_advanced_toolbar_align : "left", 
			theme_advanced_statusbar_location : "bottom",
			theme_advanced_resizing : true,
			theme_advanced_resize_horizontal : false,
			theme_advanced_blockformats : "p,h1,h2,h3"
		});
	};

	this.initDatepicker = function(elem, options) {
		var monthNamesShort =
			['Январь', 'Февраль', 'Март', 'Апрель', 'Май', 'Июнь', 
			 'Июль', 'Август', 'Сентябрь', 'Октябрь', 'Ноябрь','Декабрь'];
		
		var dayNamesMin = ['Вс', 'Пн', 'Вт', 'Ср', 'Чт', 'Пт', 'Сб'];

		var datepickerOptions = {
			changeMonth:     true,
			changeYear:      true,
			dateFormat:      'dd.mm.yy',
			minDate:         '-80Y', 
			maxDate:         '+5Y',
			yearRange:       '1900:2020',
			firstDay:        1,
			monthNamesShort: monthNamesShort, 
			dayNamesMin: dayNamesMin
		};

		if (typeof options != "undefined") {
			if (!empty(options.maxDate)) {
				datepickerOptions.maxDate = options.maxDate;
			}
			if (!empty(options.minDate)) {
				datepickerOptions.minDate = options.minDate;
			}
			if (!empty(options.yearRange)) {
				datepickerOptions.yearRange = options.yearRange;
			}
		}
		
		elem.datepicker(datepickerOptions);
	};
	
	this.initSlider = function(elem) {
		elem.selectToUISlider({
			labels: 0,
			tooltip: false,
			valspan: '#slider-value-' + elem.attr('id')
		});
		
		elem.attr('class', 'hidden');
	};

	this.initDialogMapsForList = function(options) {
		options = !empty(options) ? options : new Object();
		options.icon = !empty(options.icon) ? options.icon : 'home';
		
		var map     = "div[id$='_dialog_map']";
		var mapLink = "span[id$='_link_map']";
		
		$(map).dialog({
			bgiframe: true,
			autoOpen: false,
			height: 500,
			width: 500,
			modal: true,
			resizable: false,
			zIndex: 2,
			buttons: {
				'Закрыть': function() {
					$(this).dialog("close");
				}
			},
			close: function() {
				$(this).empty();
			},
			open: function() {
				id = $(this).attr('id');

				map = new CornholioGMap2(document.getElementById(id));

				map.showPoint(
					new GLatLng(
						$('#' + id.substring(0, id.length - 11) + '_lat').val(), 
						$('#' + id.substring(0, id.length - 11) + '_lng').val()
					), 
					options.icon
				);
			}
		});
		
		
		$(mapLink).click(function() {
			id = $(this).attr('id');
			id = "#" + id.substring(0, id.length - 9) + "_dialog_map";

			$(id).dialog("open");
		});
	};
	
	this.initEditMap = function(elem, options) {
		options = !empty(options) ? options : new Object();
		options.icon = !empty(options.icon) ? options.icon : 'home';
		
		var mainId        = elem.attr('id');
		var mapId         = mainId + '_map';
		var showMarkerId  = mainId + '_showMarker';
		var findAddressId = mainId + '_findAddress';
		var stationId     = mainId + '_station';
			
		var map      = new CornholioGMap2(document.getElementById(mapId));
	    var geocoder = new GClientGeocoder();
		
	    var marker   = new GMarker(new GLatLng(0, 0), {draggable: true, icon: map.getIcon(options.icon)});

		map.addOverlay(marker);
		
		marker.hide();
		
		function setStations(markers) {
			var stationNames = new Array();

			$.each(markers, function(i, item){
		    	stationNames[i] = '<span style = "color:' + item.station.color + '">' + item.station.name + '</span>';
			});

			$('#station').html(stationNames.join(', '));

			$('#station_id') .val(markers[0].station.id);
			$('#station_id2').val(markers[1].station.id);
			$('#station_id3').val(markers[2].station.id);
		}
		
		GEvent.addListener(marker, "dragend", function() {
	        point = marker.getLatLng();
	    	
	        $('#lat') .attr('value', point.lat());
	    	$('#lng').attr('value', point.lng());

	    	map.showStations(point, setStations);
	    });

		map.setUIToDefault();
		
		geocoder.getLatLng(
			$('#' + mainId).attr('value'),
			function(point) {
				if ($('#lat').attr('value')) {
			    	lat = $('#lat').attr('value');
			    } else {
			    	lat = 0;
			    }
			    if ($('#lng').attr('value')) {
			    	lng = $('#lng').attr('value');
			    } else {
			    	lng = 0;
			    }

			    if (lat && lng) {
			    	center = new GLatLng(lat, lng);

			    	marker.setLatLng(center);
			    	marker.show();

			    	map.showStations(center, setStations);
			    } else if (!point) {
				    center = new GLatLng(55.755786, 37.617633);
			    } else {
			    	center = point;
			    }
		    	
				map.setCenter(center, 12);
			}
		);
	    
	    $('#' + showMarkerId).click(function() {
	        geocoder.getLatLng(
	    		$('#' + mainId).attr('value'),
	    		function(point) {
	    		    if (!empty(point)) {
	    		    	map.setCenter(point);

	    		    	marker.setLatLng(point);
	    		    	
	    		    	marker.show();

	    		    	$('#lat').attr('value', point.lat());
	    		    	$('#lng').attr('value', point.lng());
	    		    	
	    		    	map.showStations(point, setStations);
	    		    }
	    		}
	    	);
	    });

	    $('#' + findAddressId).click(function() {
			if (marker.getLatLng().lat()) {
		    	geocoder.getLocations(
					marker.getLatLng(),
					function(response) {
						address = response.Placemark[0].address;
						address = address.replace('Россия, ', '');
						address = address.replace(/[0-9]{6}, /, '');
						address = address.replace('город ', '');
		
						$('#address').attr('value', address);
					}
				);
				
				map.setCenter(marker.getLatLng());
				
				marker.show();
			}
	    });
	};

	this.initJsTree = function (elem, options) {
		options.three_state = !empty(options.three_state) ? options.three_state : false;
		options.count       = !empty(options.count)       ? options.count       : 1;
		
		elem.tree({
			plugins: { 
				checkbox: {
					three_state: options.three_state
				}
			},
			ui: {
				theme_name: (options.count == 1) ? 'radio' : 'checkbox'
			},
			data: {
				type: 'json',
				async: true,
				opts: {
					method: 'GET',
					url: options.url
				}
			},
			callback: {
				onload: function() {
					var id = elem.attr('id').substring(0, elem.attr('id').length - 7);
					
					$('[name^=' + id + ']').each(function (i) {
						$.tree.plugins.checkbox.check($('#' + id + '_dialog').find('ul li a[key=' + $(this).val() + ']').parent());
					});
					
					soul.jsTreeSetSelected(id, options);
				},
				beforedata: function (node, tree) {
					if (node == false) {
						var id = elem.attr('id').substring(0, elem.attr('id').length - 7);
						var nodes = new Array();

						$('[name^=' + id + ']').each(function (i) {
							nodes[i] = $(this).val();
						});

						if (nodes.length) {
							return {nodes:'[' + nodes.join(',') + ']'};
						} else {
							return null;
						}
					} else {
						return {id: node.attr('id') || 0};
					}
				},
				check: function (rule, node, value, tree) {
					if (options.count == 1) {
						var id = elem.attr('id').substring(0, elem.attr('id').length - 7);
						
						$('#' + id + '_dialog').find('ul li a').parent().each(function() {
							$.tree.plugins.checkbox.uncheck($(this));
						});
						
						$.tree.plugins.checkbox.check(node);
					} else {
						return value;
					}
				}
			}
		});
	};

	this.initJsTreeForm = function(id, options) {
		var dialog        = $('#' + id + '_dialog');
		var link          = $('#' + id + '_link');
		var label         = $('#' + id + '_label');

		link.live('click', function() {
			dialog.dialog("open");
		});

		label.find('.dialog-value').live("click", function () {
			$.tree.plugins.checkbox.uncheck(dialog.find('ul li a[key=' + $(this).attr('id').substring(id.length + 1, $(this).attr('id').length) + ']').parent());
			
			soul.jsTreeSetSelected(id, options);
			
			$(this).remove();
		});
	};
	
	this.jsTreeSetSelected = function(id, options) {
		
		var elementCount  = options.count;
		var hiddenDiv = "hidden_div_" + id;
		var dialog        = $('#' + id + '_dialog');

		$("#" + id + "_label").empty();
		
		nodes = $.tree.plugins.checkbox.get_checked($.tree.reference(dialog));

		var intIndex = 0;
		
		nodes.each(function(intIndex) {
			if (intIndex < elementCount) {
				$("#" + id + "_label").append(
					'<div id = "' + id + '_' + $(this).find('a').attr('key') + '" class = "dialog-value">' + 
						'<img class = "button_small delete_element" src = "/i.gif"/>' + 
						'<span class = "dashed">' + $(this).find('> a').text().substring(1) + '</span>' + 
					'</div>'
				);
			} else {
				 $.tree.plugins.checkbox.uncheck(this);
			}
		});

		$("#" + hiddenDiv).remove();
		$("#edit").append("<div style = \"display: none\" id = \"" + hiddenDiv + "\"></div>");
		
		nodes = $.tree.plugins.checkbox.get_checked($.tree.reference(dialog));
		
		if (nodes.length > 1) {
			var intIndex = 0;
			
			nodes.each(function(intIndex) {
				if (intIndex < elementCount) {
					$('<input type = hidden name = "' + id + '[]" value = "' + $(this).find('a').attr('key') + '">').appendTo("#" + hiddenDiv);
				}
			});
		} else if (nodes.length == 1) {
			$('<input type = hidden name = "' + id + '" value = "' + nodes.find('a').attr('key') + '">').appendTo("#" + hiddenDiv);
		}
	};
		
	this.initJsTreeDialog = function(id, options) {
		var dialog        = $('#' + id + '_dialog');

		this.initJsTree(dialog, options);
		this.initJsTreeForm(id, options);

		dialog.dialog({
			bgiframe: true,
			autoOpen: false,
			height: 630,
			width: 600,
			modal: true,
			resizable: false,
			zIndex: 2,
			buttons: {
				'Отмена': function() {
					$(this).dialog("close");
				},
				'Выбрать': function() {
					soul.jsTreeSetSelected(id, options);
					
					$(this).dialog("close");
				}
			},
			open: function() {
			}
		});
	};

	this.initCurrency = function(elem, options) {
		elem.parent().find('input:text').css('width', '90%');
		elem.parent().append('<span class = "dashed" style = "font-family: times; font-weight: bold; font-size: 1.2em; margin-left: .5em" id = "' + elem.attr('id') + '_selector"><em></em></span>');
		
		var selector = $('#' + elem.attr('id') + '_selector em');
		
		var options = {0: {}, 1: {}, 2: {}};
		var counter = 0;
		
		options[0].text = '<span class="rur">p<span>уб.</span></span>';
		options[0].val  = 'ru';
		options[1].text = '$';
		options[1].val  = 'us';
		options[2].text = '&euro;';
		options[2].val  = 'eu';

		switch (elem.val()) {
			case 'us':
				counter = 1;
				break;
			case 'eu': 
				counter = 2;
				break;
			default:
				counter = 0;
		}

		selector.html(options[counter].text);
		elem.val(options[counter].val);
		
		selector.live('click', function() {
			counter++;

			selector.html(options[counter % 3].text);
			elem.val(options[counter % 3].val);
		});
	};

	this.initSelectorDashed = function(elem, options) {
		var options = !empty(options) ? options : new Object();
		var values = !empty(options.values) ? options.values : new Array();
		var counter = 0;
		var size = values.length;
		var x = elem.parent().offset().left + 246;
		var y = elem.parent().offset().top  + 5;

		var selectorId = elem.attr('id') + '_selector';
		
		$('#' + selectorId).remove();
		
		$('body').append(
			'<div ' +
				'id = "' + elem.attr('id') + '_selector" ' +
				'class = "hidden" ' +
				'style = "z-index: 999; position:absolute; ' + 
					'padding: 5px; background: #FEFFD6;' +
					'top: ' + y + 'px; left: ' + x + 'px' +
				'"' +
			'></div>'
		);

		var selector =  $('#' + elem.attr('id') + '_selector');

		for(i = 0; i < size; i++) {
			selector.append('<div class = "dashed" style = "margin-bottom: .25em;" id = "' + selectorId + '_value_' + i + '"><em>' + values[i].text + '</em></div>')
			
			if (!empty(values[i]) && values[i].val == elem.val()) {
				counter = i;
			}
		}
		$('#' + selectorId + '_value_' + counter).css('font-weight', 'bold');

		elem.parent().find('div.rightColumn').remove();
		elem.parent().append('<div class = "rightColumn"><span class = "dashed"  id = "' + selectorId + '_text"><em>' + values[counter].text + '</em></span></div>');

		$('#' + selectorId + '_text').live('click', function() {
			selector.removeClass('hidden');
		});
		
		selector.find('div').live('click', function() {
			selector.addClass('hidden');
			
			var i = $(this).attr('id').substring(new String(selectorId + '_value_').length);
			
			if (!empty(values[i])) {
				selector.find('div').css('font-weight', 'normal');
				$(this).css('font-weight', 'bold');
				
				$('#' + selectorId + '_text').html($(this).html());
				
				elem.val(values[i].val);
			}
		});
	};
	
	this.initTooltip = function (elem, options) {
		var options = !empty(options) ? options : new Object();
		var tooltip = !empty(options.tooltip) ? options.tooltip : new String();
		
		var iconId = options.id + '_tooltipIcon';
		
		elem.css('margin-right', '.5em');
		elem.append(' ' + this.helper.icon({icon: 'question-small', id: iconId}));
		
		this.helper.tooltip({id: iconId, tooltip: tooltip});
	};
	
	this.initSelectJson = function (elem, options) {
		var options = !empty(options) ? options : {url:''};
		elem.find('option').remove();
		
		if (!empty(options.url)) {
			if (options.nullValue != undefined) {
				elem.append('<option value = "">' + options.nullValue + '</option>');
			}
			
			$.getJSON(options.url, function(data) {
				$.each(data, function(i, item) {
					elem.append('<option value = "' + item.id + '">' + item.name + '</option>');
				});
			});
		}
	};
}


function initFields(elem) {
	for(index = 0; index < 128; index++) {
		id = elem.attr('id').replace(/[\d]*$/, index);

		if (!$('#' + id).attr('id')) {
			break;
		}
	}

	elem.val('');
	elem.attr('value', '');
	elem.find('option').removeAttr('selected');
	elem.attr('id', elem.attr('id').replace(/[\d]*$/, index));
	elem.attr('name', elem.attr('name').replace(/[\d]*$/, index));
}

