var belanger = {
	init: function() {
		ub.a.append(this.events, ub.e.attach(window, 'load', function() {
			this.menu.init();
			this.page.init();
			//get a user session
			ub.json.async.post('session::get', [], function(json) {
				if(json.result == 'pass') {
					this.user.session = json.response;
					this.onsessionloaded(new ub.e.event('sessionloaded'));
					this.ping.interval = setInterval(function() {
						belanger.ping.send();
					}, 10000);
				}
			}, null, this);
		}, false, this));
		ub.a.append(this.events, ub.e.attach(window, 'unload', function() {
			belanger.destruct();
		}, false, this));
	},
	destruct: function() {
		for(var i=this.events.length-1;i>=0;i--) {
			this.events[i].detach();
			this.events[i] = null;
		}
		this.events = [];
		clearInterval(this.ping.interval);
		this.menu.destruct();
		this.page.destruct();
	},
	events: [],
	ping: {
		interval: null,
		send: function() {
			ub.json.async.post('session::ping', [], function(json) { });
		}
	},
	menu: {
		init: function() {
			this.container = ub.$('submenu_container');
			this.make(this.data);
			//auto hide menu event
			ub.a.append(belanger.events, ub.e.attach(document.body, 'mousemove', function(e) {
				if(belanger.menu.visible.length > 0) {
					var buffer = 40;
					var offset = ub.n.realOffset(this);
					if(
						(offset[0] - buffer > e.coords[0]) ||
						(offset[1] + this.offsetHeight + buffer < e.coords[1]) ||
						(offset[0] + this.offsetWidth + buffer < e.coords[0])
					)
						ub.a.each(belanger.menu.data, function(menu) {
							var target = ub.$(menu.target);
							if(target) {
								ub.n.removeClassName(target, 'button_active');
								target = null;
								if(menu.div)
									belanger.menu.hide(menu.div);
							}
						});
				}
			}, false, this.container));
		},
		destruct: function() { },
		data: [],
		_events: [],
		visible: [],
		dom: {
			wrapper: null
		},
		container: null,
		make: function(menu) {
			var make_div = function() {
				var div = ub.$(document.createElement('div'));
				ub.n.addClassName(div, 'menu');
				return div;
			};
			var make_a = function(sub_menu) {
				var a = ub.$(document.createElement('a'));
				if(sub_menu.new_window)
					a.target = '_blank';
				ub.n.addClassName(a, 'button');
				a.innerHTML += sub_menu.display;
				if(sub_menu.sub_menu.length) {
					ub.n.addClassName(a, 'has_children');
				}
				a.href = sub_menu.href;
				return a;
			}
			var make_menu = function(menu, parent, target) {
				var div = make_div();
				//link to DOM node
				menu.div = div;
				//extend DOM node with menu object
				div.menu = menu;
				//make sure a target or a parent anchor exists
				if(target || menu.a) {
					menu.fx = new ub.fx.opacity(div);
					menu.fx.hide();
					div.style['display'] = 'none';
					ub.a.append(belanger.events, ub.e.attach(((target) ? target : menu.a), 'mouseover', function() {
						belanger.menu.display(this);
						//check for an arbitrary target
						if(target) {
							//hide all sibling menus - we do this for arbitrary targets
							//since the same code below won't get set for them
							ub.a.each(parent, function(sibling) {
								if(sibling.div && sibling != menu) {
									belanger.menu.hide(sibling.div);
									ub.n.removeClassName(ub.$(sibling.target), 'button_active');
								}
							});
							ub.n.addClassName(target, 'button_active');
						}
					}, false, div));
				}
				//run through each sub_menu
				ub.a.each(menu.sub_menu, function(sub_menu) {
					//create an anchor
					var a = make_a(sub_menu);
					
					div.appendChild(a);
					//link to the DOM anchor
					sub_menu.a = a;
					ub.a.append(belanger.events, ub.e.attach(a, 'mouseover', function() {
						//run through all sibling menus and hide them
						ub.a.each(menu.sub_menu, function(sibling) {
							if(sibling.div && sibling != sub_menu)
								belanger.menu.hide(sibling.div);
							ub.n.removeClassName(sibling.a, 'button_active');
							if(sibling.sub_menu.length > 0)
								ub.n.removeClassName(sibling.a, 'has_children_active');
						});
						ub.n.addClassName(sub_menu.a, 'button_active');
						if(sub_menu.sub_menu.length > 0)
								ub.n.addClassName(sub_menu.a, 'has_children_active');
					}));
					a = null;
				});
				return div;
			}
			ub.a.each(menu, function(sub_menu) {
				//create a sub_menu if needed
				if(sub_menu.sub_menu.length > 0) {
					var div = make_menu(sub_menu, menu, (sub_menu.target) ? ub.$(sub_menu.target) : null);
					belanger.menu.container.appendChild(div);
					belanger.menu.make(sub_menu.sub_menu);
				} 
				//no sub_menu needed - check for a target
				else if(sub_menu.target) {
					//locate the target node
					var target = ub.$(sub_menu.target);
					if(target) {
						//add an event handler
						ub.a.append(belanger.events, ub.e.attach(target, 'mouseover', function() {
							//hide all sub_menus
							ub.a.each(belanger.menu.data, function(sub_menu) {
								if(sub_menu.div) {
									belanger.menu.hide(sub_menu.div);
									ub.n.removeClassName(ub.$(sub_menu.target), 'button_active');
								}
							});
						}));
					}
				}
			});
		},
		display: function(node) {
			ub.a.append(belanger.menu.visible, node, true);
			setTimeout(function() {
				node.style['display'] = 'block';
				node.menu.fx.expose();
			}, node.menu.fx.options.duration);
		},
		hide: function(node) {
			ub.a.remove(belanger.menu.visible, node);
			node.menu.fx.conceal();
			setTimeout(function() {
				node.style['display'] = 'none';
			}, node.menu.fx.options.duration);
			ub.a.each(node.menu.sub_menu, function(sub_menu) {
				ub.n.removeClassName(sub_menu.a, 'button_active');
				if(sub_menu.div)
					belanger.menu.hide(sub_menu.div);
			});
		}
	},
	user: {
		session: null,
		login: function(credentials) {
			ub.json.async.post('session::login', [credentials], function(json) {
				if(json.result == 'pass') {
					belanger.user.session.user_id = json.response.user_id;
					belanger.onuserlogin(new ub.e.event('userlogin'), json);
				} else {
					belanger.onuserloginfail(new ub.e.event('userloginfail'), json);
				}
			}, null, this);
		},
		logout: function() {
			ub.json.async.post('session::logout', [], function(json) {
				if(json.result == 'pass') {
					belanger.user.session.user_id = 0;
					belanger.onuserlogout(new ub.e.event('userlogout'));
				} else {
					belanger.onuserlogoutfail(new ub.e.event('userlogoutfail'), json);
				}
			});
		}
	},
	page: {
		init: function() {
			this.mask.init();
		},
		destruct: function() {
			this.mask.destruct();
		},
		mask: {
			init: function() {
				this.bg = document.createElement('div');
				this.bg.className = 'mask';
				ub.$('content_wrapper').appendChild(this.bg);
				var coords = [0,80];//$('content_wrapper').cumulativeOffset();
				//adjust the coords
				coords[0] += 10;
				ub.n.setCoords(this.bg, coords);
				this.bg.style['display'] = 'none';
				this.fx = new ub.fx.opacity(this.bg, { maxOpacity: 0.8 });
				this.fx.hide();
			},
			destruct: function() {
				this.bg = null;
				this.fx.destruct();
				this.fx = null;
			},
			bg: null,
			fx: null,
			show: function() {
				this.position();
				this.fx.expose();
				this.bg.style['display'] = 'block';
				document.body.style['cursor'] = 'wait';
			},
			hide: function() {
				this.position();
				document.body.style['cursor'] = 'default';
				this.fx.conceal();
				setTimeout(function() {
					belanger.page.mask.bg.style['display'] = 'none';
				}, this.fx.options.duration + 10);
			},
			position: function() {
				var coords = [0,80];//$('content_wrapper').cumulativeOffset();
				//adjust the coords
				coords[0] += 10;
				ub.n.setCoords(this.bg, coords);
				this.bg.style['width'] = (ub.$('content_wrapper').clientWidth - 20) + 'px';
				this.bg.style['height'] = ub.$('content_wrapper').clientHeight + 'px';
			}
		}
	},
	onsessionloaded: function(e) {},
	onuserlogin: function(e, json) {},
	onuserlogout: function(e, json) {},
	onuserloginfail: function(e, json) {},
	onuserlogoutfail: function(e, json) {}
};
belanger.init();
