var UITabPlacement = {
	"left": 0,
	"group": 1,
	"right": 2
};

var debug__project;

var UIHandler = function() {
	var project = undefined;
	var tab_set = undefined;
	var project_info = undefined;
	var self = this; // WARNING: Ugly hack detector might go nuts here (thx ECMAScript!)
	var general_setting_bar = $("div#general_settings_bar");
	
	var create_tabs = function(setting_bar) {
		tab_set = new UITabSet($("div#nav"), $("div#mainContent div.content"),
								project, setting_bar, self);
		
		tab_set.add("Forside", UITabPlacement.left, "frontpage");
		tab_set.add("Byggesagsinformation", UITabPlacement.left, "information");
		
		var groups = project.list_groups();
		for (var key in groups) {
			tab_set.add(groups[key].name, UITabPlacement.group, groups[key].id);
		}
		
		tab_set.add("Om siden", UITabPlacement.right, "about");
		//tab_set.add("Info / hjælp", UITabPlacement.right, "helpinfo"); // Alm. tab
		tab_set.add("Info / hjælp", UITabPlacement.right, "helpinfo", "http://hfabc.dk/totaloko/help/"); // Tab som åbner et nyt vindue
		
		tab_set.goto_tab(UITabPlacement.left, 0);
	};
	
	var init_general_settings = function() {
		general_setting_bar.find("ul").empty();
		new UISettingBar(general_setting_bar.find("ul"), project, self);
	};
	
	this.recalculate_all = function() {
		tab_set.recalculate_all();
	};
	
	var init = function(project_obj) {
		// Destory objects if they already exists
		if (tab_set != undefined) {
			tab_set.destroy();
			tab_set = undefined;
		}

		if (project_info != undefined) {
			project_info.destroy();
			project_info = undefined;
		}

		project = project_obj;
		debug__project = project;
		
		// Show calcultion rate
		$("div#mainContent div.kalkrente span").text("Kalkulationsrente: " +
			percent_to_pstring(project.get_setting("calculation_rate").get_active_value())
		);
		
		project_info = new UIProjectInformation($("div#information"), project);

		init_general_settings();
		create_tabs(general_setting_bar);
	};

	var default_project = function() {
		var def_proj = new Project(tov_config);
		
		// Open 3 constructions per group
		var groups = def_proj.list_groups();
		for (var i = 0; i < groups.length; i++) {
			var group = def_proj.get_group(groups[i].id);
			var constructions = group.list_constructions();
			for (var j = 0; j < constructions.length && j < 3; j++) {
				group.add_construction(constructions[j].id);
			}
		}

		return def_proj;
	};

	// Initialize
	init( default_project() );
	
	$("a#logo").click(function(){
		tab_set.goto_tab(UITabPlacement.left, 0);
		return false;
	});
	
	var backend_box = new UIBackendBox($("#mainContent").find('.content').get(0), {"top": 35, "right": 9});
	var save_failure_notification = undefined;
	$("a#button_save").click(
		function(){
			if (backend_box.is_open()) backend_box.close();
			backend_box.set_content($("<div>Forbereder fil til gemning.</div>"));

            $.ajax({
                type: "post",
                url: "./backend/save.php" ,
                data: {"input": TreeRawOutput(project)},
                success: function(data, textStatus) {
			        var link = $('<a href="./backend/save.php?ret=true" target="_blank">'
			         			+ 'Hent din gemte fil</a>');
			        backend_box.set_content(link);
			        link.click(backend_box.close);
                    
			        if (save_failure_notification != undefined) {
			            save_failure_notification.close();
			            save_failure_notification = undefined;
			        }
                },
                error: function(request, textStatus, error) {
                    backend_box.close();
					if (save_failure_notification == undefined) {
					    var msg = undefined;
					    switch (request.status) {
					        case 400:
					            msg = $("<p>Der skete en fejl under gemningen af den "
    					 		      + "totaløkonomiskevurdering. Den genererede .tovx-fil er ikke gyldig."
    					 		      + "Hvis denne fejl forsætter kontakt da en administrator.</p>");
					            break;
					        default:
					            msg = $("<p>Der skete en fejl under gemningen af den "
        					 		  + "totaløkonomiskevurdering. Hvis denne fejl forsætter "
        					 		  + "kontakt da en administrator.</p>");
					    }
					     
					    save_failure_notification = new UINotification($("div.content"),
					 												  "Gemning fejlede", msg);
					}
                }
            });
			
			return false;
		}
	);
	
	this.save_to_server = function() {
	    if (backend_box.is_open()) backend_box.close();
		if(confirm("Når du indsender, vil din rapport blive gemt på serveren, for herefter senere at blive transporteret til BosInf systemet. Er du sikker på at du vil indsende?")) {
			backend_box.set_content($("<div>Forbereder fil til indrapportering.</div>"));

			$.post("./backend/save.php?atserver=1", {"input": TreeRawOutput(project)},
				   function(data) {
					   if (data == "ok") {
						   backend_box.set_content($('<div style=\"\">Din rapport er nu indberettet!</div>'));

						   if (save_failure_notification != undefined) {
							   save_failure_notification.close();
							   save_failure_notification = undefined;
						   }
					   } else {
						   backend_box.close();
						   if (save_failure_notification == undefined) {
							   var msg = $("<p>Der skete en fejl under indrapporteringen af den "
										   + "totaløkonomiskevurdering. Hvis denne fejl forsætter "
										   + "kontakt da en administrator.</p>");
							   save_failure_notification = new UINotification($("div.content"),
																			  "Indrapportering fejlede", msg);
						   }
					   }
				   });
			
			return false;
		}
	};
	
	$("a#button_save_server").click(this.save_to_server);

	$("a#button_load").click(function(){
		if (backend_box.is_open()) backend_box.close();
		var iframe = $('<iframe src="./iframe_load.html" width="300" scrolling="no" '
					   + 'height="25" frameborder="0"/>');
		backend_box.set_content(iframe);
		var submitted = false;

		iframe.load(function(){
			if (submitted !== true) {
				$("input[type=submit]", iframe.contents()).click(
					function(event) {
						$("form", iframe.contents()).submit();
						submitted = true;
						backend_box.append_content($('<p style="width:300px;">Vent mens '
													 + 'data indlæses.</p>'));
						iframe.css({
									   "position": "absolute",
									   "left": "-10000px"
								   });
						event.preventDefault();
					}
				);
			} else {
				$.get("./backend/load.php", { "ret": "true" },
					  function(data) {
						  try {
					          do_load(data);
						      
						      tab_set.goto_tab(UITabPlacement.left, 1);
						      var msg = $("<p>Den totaløkonomiske vurdering er nu indlæst.</p>");
  							  new UINotification($("div.content"), "Indlæst", msg, null, 15000);
						  } catch (x) {							
							  // Goto frontpage tab
							  tab_set.goto_tab(UITabPlacement.left, 0);
							  init( default_project() );

							  var msg = $("<p>Filen du har uploaded er ikke gyldig. Er du sikker "
										  + "på det er en korrekt fil?</p>");
							  new UINotification($("div.content"), "Ugyldig fil", msg);
						  }
						  
						  iframe.remove();
						  backend_box.close();
					  }, "text");
			}
		});
	});
	
	var print_failure_notification = undefined;
	$("a#button_print").click(function(){
		if (backend_box.is_open()) backend_box.close();
		backend_box.set_content($("<div>Forbereder print...</div>"));

		$.post("./backend/print_xml.php", {"input": TreeRawOutput(project)},
			   function(data) {
				   if (data == "ok") {
					   var link = $('<a href="./backend/print_xml.php?ret=true" target="_blank">'
									+ 'Hent udskriften</a>');
					   backend_box.set_content(link);
					   link.click(backend_box.close);

					   if (print_failure_notification != undefined) {
						   print_failure_notification.close();
						   print_failure_notification = undefined;
					   }
				   } else {
					   backend_box.close();
					   if (print_failure_notification == undefined) {
						   var msg = $("<p>Der skete en fejl under udskrivningen "
									   + "Hvis denne fejl forsætter "
									   + "kontakt da en administrator.</p>");
						   print_failure_notification = new UINotification($("div.content"),
																		  "Udskrift fejlede", msg);
					   }
				   }
			   });
		
		return false;
	});

	var do_load = function(xml) {
		var load = new XMLLoader(xml);
		
		if (load.passed !== true) {
			for (var i = 0; i < load.reasons.length; i++) {
				switch (load.reasons[i]) {
					case DataLoadNonPassedReasons.CalculationRateChanged:
						var calcrate_setting = load.project.get_setting("calculation_rate");
						calcrate_setting.set_active_value( load.current_calculation_rate );
						
						// Show HTML interface to the user
						var frontpage_container = $("div#frontpage");
					    var calcrate_chooser = new UICalcRateChooser(calcrate_setting,
																	 {"new_rate":load.new_calculation_rate,
																	  "old_rate":load.current_calculation_rate},
																	 self.recalculate_all);

					    var notification_text = $("<p>Kalkulationsrenten er blevet ændret, og nu har du "
												  + "derfor mulighed for at vælge hvilken kalkulationsrente "
												  + "du ønsker at benytte.</p>");
					    new UINotification(frontpage_container, "Kalkulationsrente ændret",
										   notification_text, calcrate_chooser);

						break;
					case DataLoadNonPassedReasons.GroupDeleted:
						var msg = $('<div class="notification">Der er sket ændringer i totaløkonomiske '
						  + 'vurderingers konfiguration, og det er derfor ikke muligt for dig '
						  + 'at se og ændre alle dine eksisterende vurderinger her på siden. '
						  + '<br />Du kan til hver en tid se dine tidligere vurderinger ved, '
						  + 'at åbne .tovx-filen i en browser, som fx Mozilla Firefox eller '
						  + 'Microsoft Internet Explorer.</div>');

					    new UINotification($("div#frontpage"), "Gruppe slettet", msg);
						break;
				}
			}
		}
		
		init( load.project );
	};
};

var UITabSet = function(tab_bar, content_container, project, setting_bar, parent) {
	var title_bar = $(content_container).siblings("div.contentTitle").find("h3.left");
	var tab_container = [ [], [], [] ];
	var bar_dom = [
		$("<ul></ul>").appendTo(tab_bar),
		$("<ul></ul>").appendTo(tab_bar),
		$("<ul class=\"sub\"></ul>").appendTo(tab_bar)
	];
	
	var next_link = $("a.nextLink", content_container.siblings("div.contentTitle"));
	if (next_link.length == 0) {
	    next_link = $('<a href="#" class="nextLink">Gå videre til <span class="name" /></a>').insertAfter(title_bar);
	}
	var update_next_link = function(cur_placement, cur_pos) {
	    // Callback function for when the user presses the link
	    function link_change_to(event) {
	        switch (typeof(event.data)) {
	            case "object":
	                change_to_tab(event.data);
	                break;
	            case "function":
	                event.data();
	                break;
	            default: alert("Ukendt handling!");
	        }
	    }
	    next_link.unbind("click");
	    
	    if (cur_placement == UITabPlacement.right) {
	        next_link.hide();
	        return;
	    }
	    
	    if (tab_container[cur_placement].length > (cur_pos+1)) {
	        var tab = tab_container[cur_placement][cur_pos+1];
	        $("span.name", next_link).text(tab.title);
	        next_link.bind("click", tab, link_change_to);
	    } else if (cur_placement == UITabPlacement.group) {
	        // In this case we should go to "Indberet"
	        $("span.name", next_link).text("Indberet");
	        next_link.bind("click", parent.save_to_server, link_change_to);
	    } else {
	        // Otherwise we just go to the next group
	        var tab = tab_container[cur_placement+1][0];
	        $("span.name", next_link).text(tab.title);
	        next_link.bind("click", tab, link_change_to);
	    }
	    next_link.show();
	};
	
	this.destroy = function() {
		for (var key in bar_dom) {
			bar_dom[key].remove();
		}

		for (var tab_key in tab_container[UITabPlacement.left])
			tab_container[UITabPlacement.left][tab_key].tab_dom.hide();

		for (var tab_key in tab_container[UITabPlacement.right])
			tab_container[UITabPlacement.right][tab_key].tab_dom.hide();

		for (var tab_key in tab_container[UITabPlacement.group]) {
			tab_container[UITabPlacement.group][tab_key].tab_dom.remove();
		}
	};

	this.add = function(tab_name, placement, tab_id, href) {
		var tab_object = undefined;		
		var group_tree = undefined;
		var new_group  = undefined;
		
		switch (placement) {
			case UITabPlacement.group:
				group_tree = project.get_group(tab_id);
				new_group = add_group(group_tree, tab_id);
				tab_id = new_group.get_container_id();
			case UITabPlacement.left:
			case UITabPlacement.right:
				var label_dom = $("<li><a href=\"#\"><span>"+ tab_name + "</span></a></li>")
					.appendTo(bar_dom[placement]);
				
				var tab_dom = $("#" + tab_id);
			
				tab_object = {
					"tab_dom": tab_dom,
					"label_dom": label_dom,
					"group_tree": group_tree,
					"tab_id": tab_id,
					"title": tab_name,
					"placement": placement,
					"position": tab_container[placement].length,
					"group_obj": new_group
				};
				tab_container[placement].push(tab_object);
				
				if(href === undefined) {
					label_dom.click(function(){
						change_to_tab(tab_object);
					});
				} else {
					$('a', label_dom).attr('href', href);
					$('a', label_dom).attr('target', 'blank');
				}
				break;
			default:
				throw "Undefined placement '"+ placement +"'";
		}
	};
	
	var add_group = function(group_tree, tab_id) {
		var group = new UIGroup(tab_id, group_tree, content_container);
		return group;
	};
	
	var deactivate_all = function() {
		var all_tabs = tab_container[0].concat(tab_container[1], tab_container[2]);
		for (var key in all_tabs) {
			$(all_tabs[key].label_dom).removeClass("selected");
			$(all_tabs[key].tab_dom).hide();
		}
	};

	this.goto_tab = function(placement, tab_number) {
		change_to_tab(tab_container[placement][tab_number]);
	};
	
	var change_to_tab = function(tab) {
		deactivate_all();
		$(tab.label_dom).addClass("selected");
		$(tab.tab_dom).show();
		
		// Fix the table header width
		if (tab.group_obj) {
			tab.group_obj.fix_table_header_width();
		}
		
		// Update bar
		title_bar.text(tab.title);
		update_next_link(tab.placement, tab.position);
		
		// BUG FIX: This is fixing an bug in IE where the inputs get disabled after load.
		// Fixed by focusing on the first input in the tab
		$($("input", tab.tab_dom).get(0)).focus();
		
		if (tab.placement == UITabPlacement.group)
			setting_bar.show();
		else
			setting_bar.hide();
	};
	
	this.recalculate_all = function() {
		var groups = tab_container[UITabPlacement.group];
		for(var key in groups)
		{
			groups[key].group_obj.recalculate_all();
		}
	};
};

var UIGroup = function(tab_id, group_tree, content_container) {
	var container_id = "group_"+ tab_id;
	var setting_bar = undefined;
	var table_dom = undefined;
	var table_header = undefined;
	var button_bar = undefined;
	var constructions = [ ];
	var comparison = undefined;
	
	this.get_container_id = function() {
		return container_id;
	};
	
	this.add_first_construction = function() {
		var first_construction = group_tree.list_constructions()[0].id;
		this.add_construction(first_construction);
	};
	
	this.unregister_construction_ui = function(ui_ref) {
		for(var key in constructions)
		{
			if(constructions[key] == ui_ref)
			{
				constructions.splice(key, 1);
				return;
			}
		}
	};
	
	this.add_construction = function(construction_id) {
		constructions.push( new UIConstruction(table_dom, construction_id, group_tree, this) );
	};
	
	this.add_ff_construction = function() {
	    // __freeform
		this.add_construction("freeform");
	};
	
	this.recalculate_all = function() {
		for(var key in constructions)
		{
			constructions[key].recalculate_all();
		}
		this.update_construction_comparison();
	};
	
	this.update_construction_comparison = function() {
		if (comparison == undefined) {
			// Add comparitor between constructions
			comparison = new UIComparison(obj, group_tree);
		}
		
		comparison.compare_constructions();
	};
	
	this.replace_construction = function(construction_to_replace, new_id) {
		for (var i = 0; i < constructions.length; i++) {
			if (constructions[i] == construction_to_replace) {
				var old_c = constructions[i];
				var new_c = new UIConstruction(old_c.get_root(), new_id, group_tree, this, true);
				
				constructions[i] = new_c;
				old_c.remove();
				return true;
			}
		}
		return false;
	};

	// Constructor
	var obj = $('<div id="'+ container_id +'" style="display:none;"></div>')
		.appendTo(content_container);
				
	var optionsbar = $('<div class="options"><ul class="std"></ul></div>')
		.appendTo(obj).find("ul.std");
	
	// Create warnings
	new UIWarnings(obj, group_tree);
	
	var buttonbar = $('<div class="buttons"></div>').appendTo(obj);
	var wrapper_div = $('<div style="position:relative;"></div>').appendTo(obj);
	table_dom = $('<table cellspacing="0" class="grid"></table>').appendTo(wrapper_div);
	var thead_dom = $('<thead></thead>').appendTo(table_dom);
	
	setting_bar = new UISettingBar(optionsbar, group_tree, this);
	table_header = new UITableHeader(thead_dom);
	button_bar = new UIButtonBar(buttonbar, group_tree, this);
	
	this.fix_table_header_width = function() {
		table_header.fix_header_width();
	}
	
	// Make the table header able to be repositioned
	var reposition_table_header = function() {
		var offset = wrapper_div.offset();
		var scrollTop = $(window).scrollTop();
		if ((scrollTop > offset.top) && (scrollTop < offset.top + wrapper_div.height())) {
			table_header.get_clone().css("top", Math.min(scrollTop - offset.top, 
				wrapper_div.height() - $(".tableHeader", wrapper_div).height()) + "px");
		} else {
			table_header.get_clone().css("top", "0px");
		}
	}
	reposition_table_header();
	$(window).scroll(reposition_table_header);
	
	// Set correct size on moveable thead.th
	/*
	var set_th_width = function() {
		var old_trs = $('tr:first th');
		old_trs.show();
		//console.log($(old_trs[2]).width());
		$('tr:first th', thead_dom).each(function(idx) {
			// var old_width = old_trs.width();
			// console.log(old_trs[idx].innerWidth());
			// $('tr:second th').width($(old_width).width());
		});
	}
	set_th_width();
	$(window).bind('resize', set_th_width);
	*/

	// Add precreated constructions
	var precreated_constructions = group_tree.get_constructions();
	for (var key in precreated_constructions) {
		this.add_construction(precreated_constructions[key]);
	}
};

var UIButtonBar = function(container_dom, group_tree, group) {
	// Constructor
	{
		$('<a href="#" class="button"><span>Tilføj en række</span></a>')
			.appendTo(container_dom)
			.click(function() { group.add_first_construction(); return false; });
		
		$('<a href="#" class="button"><span>Tilføj en valgfri række</span></a>')
			.appendTo(container_dom)
			.click(function() { group.add_ff_construction(); return false; });
	}
};

var UITableHeader = function(table_head_dom) {
	// Constructor
	var tr = $('<tr>											\
		<th style="width: 16%;">Konstruktion</th>                                       \
																						\
		<th style="width: 12%;" title="Her indtastes anlægsomkostningerne inkl. '
	  + 'byggepladsomkostninger i kr."><a href="#">Anlæg<br/>kr.</a></th>               \
		<th style="width: 5%;" title="Den af programmet beregnede levetid eller '
	  + 'driftsinterval."><a href="#">Levetid / driftsinterval<br/>år</a></th>          \
		<th style="width: 5%;" title="Her indtastes eventuel korrektion til den '
	  + 'beregnede levetid på baggrund af viden om det aktuelle byggeri.">'
	  + '<a href="#">Korrektion<br/>± år</a></th>                                       \
		<th style="width: 5%;" title="Valgt levetid/driftsinterval. Beregnes '
	  + 'automatisk som den valgte levetid +/- den indtastede korrektion.">'
	  + '<a href="#">Valgt<br/>år</a></th>                                              \
																						\
		<th style="width: 5%;" title="Vedligeholdssomkostninger i % af '
	  + 'anlægsomkostninger. Beregnes automatisk."><a href="#">'
	  + 'Vedlige-<br/>holdelse<br/>%</a></th>                                                 \
		<th style="width: 5%;" title="Her indtastes eventuel korrektion '
	  + '(i procent- point) til den beregnede vedligeholds-%."><a href="#">'
	  + 'Korr.<br/>± %</a></th>                                                         \
		<th style="width: 5%;" title="Valgt vedligeholds-%. Beregnes automatisk '
	  + 'som den valgte vedligeholds-% +/- den indtastede korrektion.">'
	  + '<a href="#">Valgt<br/>%</a></th>                                               \
		<th style="width: 6%;" title="Vedligeholdsomkostninger i kr. Beregnes '
	  + 'automatisk."><a href="#">Vedligehold<br/>kr.</a></th>                          \
																						\
		<th style="width: 6%;" title="Her indtastes byggepladsomkostningerne ved '
	  + 'vedligehold i kr."><a href="#">Stillads mv.<br/>kr.</a></th>                   \
																						\
		<th style="width: 10%;" title="Summen af vedligeholdsomkostninger og '
	  + 'byggepladsomkostninger ved vedligehold. Beregnes automatisk.">'
	  + '<a href="#">I alt<br/>kr.</a></th>                                             \
		<th style="width: 6%;" title="Ekstraordinære omkostninger til afskaffelse '
	  + 'eller udskiftning."><a href="#">Eks.omk.<br/>%</a></th>                        \
		<th style="width: 8%;" class="last" title="Årsomkostningerne  for anlægs- og '
	  + 'byggepladsomkostninger, vedligeholdsomkostninger samt byggepladsomkostninger '
	  + 'ved vedligehold. Beregnes automatisk."><a href="#">Årsomk.<br/>kr.</a></th>    \
	</tr>').appendTo(table_head_dom);
	
	var tr_clone = tr.clone().appendTo(table_head_dom);
	tr_clone.addClass("tableHeader");
	tr_clone.css({
		'position': 'absolute',
		'top': '0px',
		'left': '0px',
		'width': '100%',
		'visibility': "visible"
	});
	
	this.fix_header_width = function() {
		var ths = $("th", tr);
		var ths_clone = $("th", tr_clone);
		
		for (var i = 0; i < ths.length; i++) {
			$(ths_clone[i]).css("min-width", $(ths[i]).width());
		}
	};
	
	// Fix the width
	$(window).resize(this.fix_header_width);
	
	this.get_clone = function() {
		return tr_clone;
	};

	// Tooltips
	$("th[title]", table_head_dom).each(
		function() {
			var tooltip = undefined;
			
			var over = function() {
				if (tooltip != undefined) out();

				var offset = 5;

				$(this).addClass("hover");
				tooltip = $('<div class="tooltip"></div>').appendTo($("#mainContent").find(".content").get(0));
				tooltip.text( $(this).attr("title") );
				$(this).attr("title", "");

				tooltip.css({
								"position": "absolute",
								"width": "250px",
								"text-align": "left"
							});

				var th_position = $(this).offset();
				var th_width = $(this).outerWidth();
				var th_height = $(this).outerHeight();
				var tooltip_height = $(tooltip).outerHeight();
				var tooltip_width = $(tooltip).outerWidth();
				var window_width = $(window).width();

				var left_pos = th_position.left + th_width + offset;
				if (left_pos + tooltip_width > window_width)
					left_pos = th_position.left - tooltip_width - offset;

				tooltip.css("left", left_pos+"px");
				tooltip.css("top", (th_position.top + (th_height/2) - (tooltip_height/2))+"px");
			};

			var out = function() {
				if (tooltip != undefined) {
					$(this).removeClass("hover");
					$(this).attr("title", tooltip.text());
					tooltip.remove();
					tooltip = undefined;
				}
			};

			$(this).hover(over, out);
		}
	);
};

var UISettingBar = function(container_dom, tree, group) {
	// Constructor
	var setting_groups = tree.get_setting_groups();
	for (var key in setting_groups) {
		new UISettingGroup(setting_groups[key], tree, container_dom, group);
	}
};

var UISettingGroup = function(setting_group, tree, container_dom, group) {
	// Constructor
	var li = $('<li><fieldset><legend>'+ setting_group.label +'</legend></fieldset></li>');
	var fieldset = li.appendTo(container_dom).find("fieldset");
	
	var settings = setting_group.settings;
	for (var key in settings) {
		var setting = tree.get_setting(settings[key]);
		new UISetting(fieldset, setting, group);
	}
};

var UISetting = function(container, setting, group) {
	// Constructor
	switch (setting.get_type()) {
		case "radio":
			container = $("<ul></ul>").appendTo(container);
			var options = setting.get_options();
			var value = setting.get_active_value();
			
			for (var key in options) {
				var option = options[key];
				var checked = "";
				var this_val = option.get_value();
				if (value == this_val)
					checked = ' checked="checked"';
				
				var input_name = 'option__' + setting.get_name();
				var id = input_name + "_" + key;
				
				$('<li><input type="radio" class="formradio" id="'+ id +'" \
					name="'+ input_name + '" value="'+ this_val +'"'+ 
					checked +' /><label for="'+ id +'">'+ option.get_label() 
					+'</label></li>').appendTo(container);
			}
			$('input[name=' + input_name + ']', container).click(function(){
				var value = $(this).val();
				setting.set_active_value(value);
				group.recalculate_all();
			});
			
			break;
		
		case "checkbox":
			container = $('<ul></ul>').appendTo(container);
			var label = setting.get_label();
			var value = (setting.get_active_value() == 1 ? ' checked="checked"':'');
			var input_name = 'option__' + setting.get_name();
			var id = input_name;
			$('<li><input type="checkbox" class="formcheckbox" id="'+id+'" name="' + 
				input_name + '"'+value+'" /><label for="'+input_name+'">'
				+label+'</label>').appendTo(container);
			$('input#' + id, container).click(function() {
				var value = $(this).attr('checked') != "" ? 1 : 0;
				setting.set_active_value(value);
				group.recalculate_all();
			});
			break;
		
		default: break;
	}
};

/**
 * Creates a new user-interface for a construction.
 * @param construction_id may be an id, or a construction object.
 */
var UIConstruction = function(table_dom, construction_id, group_tree, parent, insert_mode) {
	var spacer = $('<tbody class="space"><tr><td colspan="13"><hr /></td></tr></tbody>');
	var root = $('<tbody></tbody>');
	
	if (insert_mode != true) spacer = spacer.appendTo(table_dom);
	else spacer = spacer.insertAfter(table_dom);
	
	root = root.insertAfter(spacer);
	
	var calculator = undefined;
	var construction = undefined;
	if (typeof(construction_id) != "object") {
		if(construction_id != "freeform") {
			construction = group_tree.add_construction(construction_id);
		} else {
			construction = group_tree.add_freeform_construction();
		}
	} else {
		construction = construction_id;
	}
	var ui_subconstructions = [];
	var self = this; // UGLY
	
	this.get_construction_id = function() { return construction.get_id(); };
	this.get_construction = function() { return construction; };
	
	this.remove = function(animate) {
		group_tree.remove_construction(construction);
		calculator = undefined;
		parent.unregister_construction_ui(this);
		
		for(var key in ui_subconstructions)
		{
			ui_subconstructions[key] = null;
		}
		ui_subconstructions = null;
		
		if(animate === true) {
			$(root).animate({opacity: 0.25}, 300, 'swing', function() { // Hides the box
				$(root).add(spacer).animate({height: 0}, // Slides the now "empty" space away
					250, 'swing', function() {
					// Finally, delete it.
					$(spacer).remove();
					$(root).remove();
				});
			});
		}
		else
		{
			$(spacer).remove();
			$(root).remove();
		}
	};
	
	this.grab_focus = function() {
		var top_border       = $(root).offset().top;
		var bottom_border    = top_border + $(root).height();
		var window_height    = $(window).height();
		var curscroll_top    = $(document).scrollTop();
		var curscroll_bottom = curscroll_top + window_height;
		if(window_height >= $(root).height()) {
			if(bottom_border >= curscroll_bottom) {
				$(document).scrollTop(bottom_border - window_height);
			} else if(top_border <= curscroll_top) {
				$(document).scrollTop(top_border);
			}
		} else {
			$(document).scrollTop(top_border);
		}
		if(!construction.is_freeform()) {
			$("input[name=cost]", root).focus();
		} else {
			$("textarea[name=name]", root).focus();
		}
	}
	
	this.get_root = function() {
		return root;
	};
	
	this.recalculate_all = function()
	{
		if(calculator == undefined) calculator = new Calculator(construction);
		GlobalWarningManager.remove_warnings_for(group_tree.get_id(), construction.get_id());
		var calc_results = calculator.calculate_construction();
		if(calc_results == undefined || calculator == undefined) {
			reset();
			
			if (construction.get_cost() > 0) {			
				$('span[describes=lifetime_calculated]', first_row)
					.html('<span style="color:darkred;">ej def. (garanti?)</span>');
				
				// Make the subconstructions appear like not defiend
				for (var i = 0; i < ui_subconstructions.length; i++) {
					ui_subconstructions[i].fill_in_results(undefined);
				}
			}
			
			return;
		}
		
		// Fill in main construction
		$('span[describes=lifetime_calculated]', first_row)
			.text(calc_results.main.lifetime.calculated);
		$('span[describes=lifetime_corrected]', first_row)
			.text(calc_results.main.lifetime.corrected);
		standard = "";
		if(calc_results.main.lifetime.standard != 0 && calc_results.main.lifetime.standard != calc_results.main.lifetime.calculated)
			standard = "(" + calc_results.main.lifetime.standard + ")";
		$('span[describes=lifetime_standard]', first_row).text(standard);
		
		// Round the yearly cost to #.000
		var yearly_cost = Math.round(calc_results.main.yearly_cost / 1000) * 1000;
		$('span[describes=yearly_cost]', first_row).text(number_to_cstring(yearly_cost));
		
		// Fill in subconstructions
		for (var i = 0; i < ui_subconstructions.length; i++) {
			ui_subconstructions[i].fill_in_results(calc_results.others[i]);
		}
		
		parent.update_construction_comparison();
		
		// Ensure that the table header is peoperly displayed
		parent.fix_table_header_width();
	};
	
	var reset = function()
	{
		$('span[describes]', first_row).text("");
		for(var key in ui_subconstructions)
			ui_subconstructions[key].reset();
	};
	
	var make_uisubconstructions = function()
	{
		var raw_subconstructions = construction.get_subconstructions();
		for(var key in raw_subconstructions)
		{
			ui_subconstructions.push(
				new UISubconstruction(self, root, raw_subconstructions[key])
			);
		}
	};
	
	var make_toolbar = function() {
		var toolbar = $(
			'<tr class="toolbar">												 \
				<td class="choice last" colspan="13">                            \
					<a href="#" class="remove">Fjern rækken</a>                  \
					<a href="#" class="advance">Vis avancerede udregninger</a>   \
				</td>															 \
			</tr>'
		).appendTo(root);
		
		$('a.remove', root).click(function(){
			if(confirm('Er du sikker på at du vil slette denne post? Denne handling kan ikke fortrydes!')) {
				self.remove(true);
			}
			return false;
		});
		
		$('a.advance', root).click(function(){
			alert("TODO!");
			return false;
		}).css("display", "none");
	};
	
	var first_row = undefined;
	
	var make_firstrow = function() {
		first_row = $(
			'<tr class="toprow">																\
				<td class="rowHead"><a href="#" class="construction">							\
					<strong class="name">'+ construction.get_name() +'</strong></a></td>        \
				<td><input type="text" value="0" name="cost" />&nbsp;</td>                      \
				<td><span><span describes="lifetime_calculated"></span>                         \
					<span describes="lifetime_standard"></span></span>&nbsp;</td>               \
				<td><input type="text" value="0" name="lifetime_correction">&nbsp;</td>                \
				<td><span describes="lifetime_corrected"></span>&nbsp;</td>                     \
				<td colspan="6">&nbsp;</td>                                                     \
				<td><input type="text" value="0" name="extra_cost" />&nbsp;</td>                \
				<td class="result last"><span describes="yearly_cost"></span>&nbsp;</td>        \
			</tr>'
		).appendTo(root);
		
		// Set input handlers
		$('input[name=cost]', first_row).bind("keyup change", function() {
			var cost = cstring_to_number($(this).val());
			construction.set_cost(cost);
			self.recalculate_all();
			$(this).val(number_to_cstring(cstring_to_number($(this).val())));
		}).val(number_to_cstring( construction.get_cost() ));
		
		$('input[name=lifetime_correction]', first_row).bind("keyup change", function() {
			var ltc = cstring_to_number($(this).val());
			construction.set_lifetime_correction(ltc);
			self.recalculate_all();
			self.handle_comment_ui();
		}).val(number_to_cstring( construction.get_lifetime_correction() ));
		
		$('input[name=lifetime_correction]', first_row).bind("change blur", function() {
			var ltc = cstring_to_number($(this).val());
			$(this).val(ltc + "");
		});
		
		$('input[name=extra_cost]', first_row).keyup(function() {
			var extra_cost = pstring_to_percent($(this).val());
			construction.set_extra_cost(extra_cost);
			self.recalculate_all();
		});
		
		$("input[name=extra_cost]", first_row).bind("change blur", function(){
			$(this).val(percent_to_pstring(pstring_to_percent($(this).val())));
		}).val(percent_to_pstring( construction.get_extra_cost() ));
		
		$("input[name=extra_cost]", first_row).focus(function() {
			$(this).val(percent_to_pstring_noending(pstring_to_percent($(this).val())));
		});
		
		// Set extra input handling for freeform constructions
		if(!construction.is_freeform())
		{
			new UIPopup(first_row.find("a.construction"), group_tree.list_constructions(),
			function(new_id) {
				replace_me(new_id);
				//parent.replace_construction(self, new_id);
			});
		}
		else
		{
			var tmp_obj = $('td.rowHead', root);
			tmp_obj.removeClass("rowhead");
			tmp_obj.addClass("optional");
			tmp_obj.html('<textarea expand_min_height="20" class="expand" name="name">' + construction.get_name() + '</textarea>');
			$('textarea[name=name]', tmp_obj).bind("keyup change", function() {
				construction.set_name($(this).val());
			});
			expand($('textarea.expand', tmp_obj));
		}
	}
	
	var comment = undefined;
	
	this.handle_comment_ui = function() {
		if (construction.should_show_comment()) comment.show();
		else comment.hide();
	};
	
	var make_comment_ui = function() {
		// Comment
		comment = $(
			'<tr class="comment_tr"><td style="text-align:right;"><stong><span>... kommentar</span></strong></td>'
			+ '<td class="result last" colspan="12"><textarea expand_min_height="47" class="expand formarea" /></td></tr>'
		).appendTo(root).hide();
		expand($("textarea.formarea", comment));

		$("textarea.formarea", comment).change(
			function(){ construction.set_comment($(this).val()); }
		).val( construction.get_comment() );

		/**
		 * Show/hide comment user-interface based on user corrections.
		 */
		self.handle_comment_ui();
	}
	
	var replace_me = function(new_id) {
		calculator = undefined; // Delete the current calculator
		group_tree.remove_construction(construction);
		construction = group_tree.add_construction(new_id);
		for(var key in ui_subconstructions)
		{
			ui_subconstructions[key] = null;
			
		}
		ui_subconstructions = [];
		
		$('tr.toprow', root).remove();
		$('tr.comment_tr', root).remove();
		$('tr.ui_subconstruction', root).remove();
		$('tr.toolbar', root).remove();
		make_firstrow();
		make_uisubconstructions();
		make_comment_ui();
		make_toolbar();
		self.recalculate_all();
	}

	make_firstrow();
	make_uisubconstructions();
	make_comment_ui();
	make_toolbar();
	this.recalculate_all();
	this.grab_focus();
};

var UISubconstruction = function(parent, tbody_dom, subconstruction) {
	var row = $(
		'<tr class="ui_subconstruction">									  				\
			<td class="firstTd" style="text-align: right"><strong class="name"></strong>&nbsp;</td>\
			<td><input type="text" value="0" name="cost" disabled="disabled"                \
				style="display:none;"/>&nbsp;</td>                                          \
			<td><span><span describes="lifetime_calculated"></span>                         \
				<span describes="lifetime_standard"></span></span>&nbsp;</td>               \
			<td><input type="text" value="0" name="lifetime_correction" />&nbsp;</td>       \
			<td><span describes="lifetime_corrected"></span>&nbsp;</td>                     \
			<td><span describes="maintainance_default">&nbsp;</span>&nbsp;</td>             \
			<td><input type="text" value="0" name="maintainance_correction" />&nbsp;</td>   \
			<td><span describes="maintainance_corrected">&nbsp;</span>&nbsp;</td>          	\
			<td><span describes="maintainance_cost">&nbsp;</span>&nbsp;</td>               	\
			<td><input type="text" value="0" name="work_cost" />&nbsp;</td>                 \
			<td class="result"><span describes="total_cost">&nbsp;</span>&nbsp;</td>        \
			<td>&nbsp;</td>                                                       		    \
			<td class="result last"><span describes="yearly_cost"></span>&nbsp;</td>        \
		</tr>'
	).appendTo(tbody_dom);
	
	$("input[name=cost]", row).bind("keyup change", function(){
		var cost = cstring_to_number($(this).val());
		subconstruction.set_cost(cost);
		recalculate();
		$(this).val(number_to_cstring(cstring_to_number($(this).val())));
	}).val(number_to_cstring( subconstruction.get_cost() ));
	
	$("input[name=lifetime_correction]", row).bind("keyup change", function(){
		var correction = cstring_to_number($(this).val());
		subconstruction.set_lifetime_correction(correction);
		recalculate();
	    parent.handle_comment_ui();
	}).val(number_to_cstring( subconstruction.get_lifetime_correction() ));
	
	$('input[name=lifetime_correction]', row).bind("change blur", function() {
		var ltc = cstring_to_number($(this).val());
		$(this).val(ltc + "");
	});
	
	$("input[name=maintainance_correction]", row).keyup(function(){
		var correction = pstring_to_percent($(this).val());
		subconstruction.set_maintainance_percent_correction(correction);
		recalculate();
	    parent.handle_comment_ui();
	}).val(percent_to_pstring( subconstruction.get_maintainance_percent_correction() ));
	
	$("input[name=work_cost]", row).bind("keyup change", function(){
		var cost = cstring_to_number($(this).val());
		subconstruction.set_work_cost(cost);
		recalculate();
		$(this).val(number_to_cstring(cstring_to_number($(this).val())));
	}).val(number_to_cstring( subconstruction.get_work_cost() ));
	
	$("input[name=maintainance_correction]", row).bind("change blur", function(){
		$(this).val(percent_to_pstring(pstring_to_percent($(this).val())));
	});
	
	$("input[name=maintainance_correction]", row).focus(function() {
		$(this).val(percent_to_pstring_noending(pstring_to_percent($(this).val())));
	});
	
	var create_elements = function() {
		var strong_dom = $("strong.name", row);
		var elements = subconstruction.list_elements();
		if (elements.length > 1) {
			var link = $('<a href="#" class="construction"><span>'+
					subconstruction.get_name() + ": " + subconstruction.get_active_element().name
					+'</span></a>').appendTo(strong_dom);
			
			var label_span = $("span", link);
			
			new UIPopup($(link).parent(), elements, function(id) {
				subconstruction.set_active_element(id);
				label_span.text( subconstruction.get_name() + ": " +
								subconstruction.get_active_element().name );
				recalculate();
			});
		} else {
			if(!parent.get_construction().is_freeform())
				$('<span>'+ subconstruction.get_name() +'</span>').appendTo(strong_dom);
			else
			{
				var tmp_obj = $('td.firstTd', row);
				tmp_obj.addClass("optional");
				tmp_obj.html('<strong>...</strong><input type="text" name="name" />');
				$('input[name=name]', tmp_obj).bind("keydown change", function() {
					subconstruction.set_name($(this).val());
				}).val( subconstruction.get_name() );
			}
		}
	};
	create_elements();
	
	this.fill_in_results = function(results) {
		if (results == undefined || results.lifetime == undefined || results.costs == undefined) {
			this.reset();
			$('span[describes=lifetime_calculated]', row)
				.html('<span style="color:darkred;">ej def. (garanti?)</span>');
			return ;
		}
		
		$('span[describes=lifetime_calculated]', row).text(results.lifetime.calculated);
		// $('span[describes=lifetime_standard]', tbody_dom).text(results.lifetime.standard);
		$('span[describes=lifetime_corrected]', row).text(results.lifetime.corrected);
		$('span[describes=maintainance_default]', row).text(
			percent_to_pstring(results.costs.maintainance_default));
		$('span[describes=maintainance_corrected]', row).text(
			percent_to_pstring(results.costs.maintainance_corrected));
		$('span[describes=maintainance_cost]', row).text(
			number_to_cstring(results.costs.maintainance_cost));
		$('span[describes=total_cost]', row).text(
			number_to_cstring(results.costs.total_cost));
	};
	
	this.reset = function() {
		$("span[describes]", row).text("");
	};
	
	var recalculate = function() {
		parent.recalculate_all();
	};
};

var UIComparison = function(container, group) {
	var comparison = new Comparison(group);
	var comparison_html =  $('<div class="comparison">Årlig besparelse <strong>dyreste</strong> (<span class="expensive"/>) / <strong>billigste</strong> (<span class="cheap"/>): <span class="costDiff"/> kr.<br/>Svarende til en nutidsværdi på kr. <span class="nowvalue"/> over en levetid på det første <span class="lifetime"/> år.</div>').appendTo(container);
	
	var get_construction_name_with_sub_names = function(construction) {
	    var name = construction.get_name();
	    var subcons = construction.get_subconstructions();
	    for (var i = 0; i != subcons.length; i++) {
	        // Only add it to the name, if the user have customization choice.
	        if (subcons[i].list_elements().length > 1)
	            name += ", "+ subcons[i].get_name() +": "+ subcons[i].get_active_element().name;
	    }
	    return name;
	};
	
	this.compare_constructions = function() {
		var analyze = comparison.analyze();
		
		if (analyze != undefined) {
			var cost_diff = analyze.constructions.difference.max.cost -
								analyze.constructions.difference.min.cost;
			
			$("span.costDiff", comparison_html).text(number_to_cstring(Math.round(cost_diff/1000)*1000));
			$("span.nowvalue", comparison_html).text(number_to_cstring(Math.round(analyze.nowvalue/1000)*1000));
			$("span.lifetime", comparison_html).text(analyze.constructions.shortest_lifetime);
			$("span.expensive", comparison_html).text(get_construction_name_with_sub_names(analyze.constructions.difference.max.construction));
			$("span.cheap", comparison_html).text(get_construction_name_with_sub_names(analyze.constructions.difference.min.construction));
		} else {
			$("span.costDiff", comparison_html).text(number_to_cstring(0));
			$("span.nowvalue", comparison_html).text(number_to_cstring(0));
			$("span.lifetime", comparison_html).text(0);
			$("span.expensive", comparison_html).text("");
			$("span.cheap", comparison_html).text("");
		}
	};
	this.compare_constructions();
};

var UIProjectInformation = function(parent_dom, project) {
	// Update adapter function
	var set_field = function() {
	    project.set_general_information($(this).attr("id"), $(this).val());
	};

	// Listeners
	$("input.formfield,textarea.formfield", parent_dom).change(set_field).keyup(set_field);

	var information = project.export_general_information();
	for (var i = 0; i < information.length; i++) {
		$("#"+information[i].id, parent_dom).val( information[i].value );

		// Mark the label with a star if the field is required
		if (information[i].required) {
			var label = $("label[for="+information[i].id+"]", parent_dom);
			var cur_text = label.text();
			if (cur_text.charAt(cur_text.length-1) != "*")
				label.text( cur_text + " *" );
		}
	}

	/**
	 * Destroy the listeners
	 */
	this.destroy = function() {
		$("input.formfield,textarea.formfield", parent_dom)
		    .unbind('change', set_field)
		    .unbind('keyup', set_field);
	};
};

/**
 * Creates a new notification to the user.
 * @param the container where the notification box will be prepended to.
 * @param the title of the notification.
 * @param the content as a jQuery object.
 * @param (optional) an extension to extend the notification. An extension object
 * should hold a render method returning a jQuery object. The render mathod is called 
 * with the notification as the first argument. 
 */
var UINotification = function(container, title, content, extension, displayTime)
{
	var notification = $('<div class="notification"></div>').prependTo(container);
	$('<h3>'+ title +'</h3>').appendTo(notification);
	content.appendTo(notification);

	if (extension != undefined) {
		extension.render(this, notification);
	}

	this.close = function() {
	    notification.slideUp("normal", function(){ $(this).remove(); });
	};
	
	// Set the box to close
	if (displayTime != undefined)
	    setTimeout(this.close, displayTime);
};

/**
 * User interface for choosing a calculation rate, if it has been changed.
 * @param calcrate_settings is a setting object for the calculation rate for the current project.
 * @param calc_rates is the current and new calculation rates.
 * @param calc_callback function to recalculate everything.
 */
var UICalcRateChooser = function(calcrate_setting, calc_rates, calc_callback)
{
	var set_calculation_rate = function(cr, notification) {
		calcrate_setting.set_active_value(cr);

		// Show calcultion rate
		$("div#mainContent div.kalkrente span").text("Kalkulationsrente: " +
			percent_to_pstring(cr)
		);

		notification.close();
		calc_callback();
	};

	this.render = function(notification, container) {
		$('<div class="button small"><button class="old button">Benyt gammel ('+ 
		  percent_to_pstring(calc_rates.old_rate) +')</button></div>  \
		  <div class="button small"><button class="new button">Benyt ny ('+
		  percent_to_pstring(calc_rates.new_rate) +')</button></div>').appendTo(container);
		
		$("button.old", container).click(function(){
			set_calculation_rate(calc_rates.old_rate, notification);
		});

		$("button.new", container).click(function(){
			set_calculation_rate(calc_rates.new_rate, notification);
		});
	};
};

/**
 * The box used when the user is saveing, loading or printing.
 * @param the container where the box should be placed in.
 * @param the position formed as { "top": xx, "right": xx }
 */
var UIBackendBox = function(container, position)
{
	var box = $(
		'<div class="dropdown top"><div class="t"><div class="r"/><a class="close" href="#">Luk</a><div/></div>'
		+ '<div class="c clearfix"><div class="shadow"><div class="drpContent"></div></div></div>'
		+ '<div class="f"><div class="r"/><div/></div>'
	);
	var content_div = $("div.drpContent", box);
	var removed = true;
	var self = this;

	this.set_content = function(dom_content) {
		if (removed == true) { 
			box.appendTo(container);
			$('a.close', box).click(function() {
				self.close();
			});
		}

		// Set the content
		content_div.empty();
		dom_content.appendTo(content_div);

		place_box();
	};

	this.append_content = function(dom_content) {
		dom_content.appendTo(content_div);
		place_box();
	};

	this.is_open = function() {
		return !removed;	
	};

	this.close = function() {
		removed = true;
		content_div.empty();
		box.remove();
	};

	var place_box = function() {
		var window_width = $(window).width();
		box.css({
			"left": (window_width - position.right - box.outerWidth()) + "px",
			"top": position.top
		});
	};
};

var UIWarnings = function(content_div, group_tree) {
	var warning_dom  = $('<div class="warnings" style="display:none;"></div>').appendTo(content_div);
	$("<h3>Bemærk!</h3>").appendTo(warning_dom);
	var ul_container = $("<ul></ul>").appendTo(warning_dom);
	
	var remove_elements = function() {
		ul_container.html("");
	};
	
	// Register the warning callback
	var warning_cb = function(warning_array)
	{
		remove_elements();
		
		var elements = 0;
		for (var key in warning_array) {
			if (warning_array[key] != undefined) {
				for (var warning_key in warning_array[key]) {
					$("<li>"+ warning_array[key][warning_key] +"</li>").appendTo(ul_container);
					elements++;
				}
			}
		}
		
		if (elements > 0) warning_dom.show();
		else warning_dom.hide();
	};
	
	GlobalWarningManager.add_listener(group_tree.get_id(), warning_cb);
};

var UIPopupManager = function() {
	var popups = [ ];
	
	this.subscribe = function(obj) {
		popups.push(obj);
	};
	
	this.unsubscribe = function(obj) {
		for (var i = 0; i < popups.length; i++) {
			if (popups[i] == obj) return popups.splice(i, 1) != undefined;
		}
		return false;
	};
	
	this.hide_all = function() {
		for (var i = 0; i < popups.length; i++) {
			popups[i].hide();
		}
	};
};
var GlobalPopupManager = new UIPopupManager();

var UIPopup = function(open_dom, elements, callback) {
	var is_showed = false;
	
	var dropdown_dom = $(
		'<div class="dropdown" style="width:200px; display:none;">	\
			<div class="t">                                         \
			    <div class="r"/>                                    \
			    <a class="close" href="#"/>                         \
			    <div/>                                              \
			</div>        				                            \
			<div class="c clearfix">                                \
                <div class="shadow">                                               \
			        <div class="drpContent"/>                    	\
				</div>                              				\
			</div>                                  				\
			<div class="f">                                         \
			    <div class="r"/>                                    \
			    <div/>                                              \
			</div>						                            \
		</div>'
	).appendTo($('#mainContent').find('.content').get(0));
	
	var element_container = $("div.drpContent", dropdown_dom);
	var element_len = elements.length;
	
	for (var i = 0; i < element_len; i++) {
		var element = $('<a href="#">'+ elements[i].name +'</a>')
						.appendTo(element_container);
		if (i == element_len-1) element.addClass("last");
		
		var id = elements[i].id;
		element.bind("click", {"id": id}, function(event){
			callback(event.data.id);
			GlobalPopupManager.hide_all();
			return false;
		});
	}
	
	var reposition = function() {
		var open_dom_offset = open_dom.offset();
		var parent_width = $(open_dom.parent()).outerWidth();
		
		var window_height = $(window).height() + $(document).scrollTop();
		var dropdown_height = dropdown_dom.outerHeight();
		if (open_dom_offset.top + dropdown_height > window_height)
			open_dom_offset.top = window_height - dropdown_height;
		
		dropdown_dom.css({
			"top": open_dom_offset.top,
			"left": open_dom_offset.left + parent_width
		});
	};
	
	var self = this;
	var click_handler = function(event) {
		if ($(event.target).parents("div.dropdown").length == 0)
			self.hide();
	};
	
	var click_cb = function() {
		if (!is_showed) self.show();
		else self.hide();
		return false;
	};
	open_dom.mousedown(click_cb);
	open_dom.click(function(){return false;});
	
	this.hide = function() {
		GlobalPopupManager.unsubscribe(this);
		
		is_showed = false;
		dropdown_dom.hide();
		$(document).unbind("mousedown", click_handler);
		$(window).unbind("resize scroll", reposition);
	};
	
	this.show = function() {
		GlobalPopupManager.hide_all();
		GlobalPopupManager.subscribe(this);
		
		is_showed = true;
		dropdown_dom.show();
		reposition();
		
		$(document).mousedown(click_handler);
		$(window).bind("resize scroll", reposition);
	};
};

$(document).ready(function(){
	new UIHandler();
});

function percent_to_pstring(percent) {
	return percent_to_pstring_noending(percent) + "%";
}

function percent_to_pstring_noending(percent) {
	return (percent * 100).toFixed(1).replace(/\./gi, ',');
}

function pstring_to_percent(string) {
	string = string.replace(/\,/gi, ".").replace(/\%/gi,'');
	var num = parseFloat(string) / 100.0;
	if(isNaN(num)) return 0;
	return num;
}

function number_to_cstring(currency) {
	var str = currency.toFixed(0);
	var str2 = "";
	var strlen = str.length;
	for(var i = strlen-1; i >= 0; i--)
	{
		str2 = str.charAt(i) + str2;
		if((i-strlen) % 3 == 0 && i > 0) str2 = "." + str2;
	}
	return str2;
}

function cstring_to_number(string) {
	var num = parseInt(string.replace(/\,/g,'').replace(/\./gi,''), 10);
	if(isNaN(num)) return 0;
	return num;
}

