//classes

/*
 * Class EventDispatcher < Class
 * Classe base de implementação de eventos.
 */
EventDispatcher = Class.$extend(function(){
	//private
	function orderByPriority(a,b) {return b.priority - a.priority;}
	
	return {
		//public
		events:{},
		
		hasEventListener:function(type) {
			return (typeof this.events[type] != 'undefined');
		},
		
		addEventListener:function(type, callback, priority, scope) {
			(!priority)&&(priority = 0);
			(typeof this.events[type] == 'undefined')&&(this.events[type]=[]);
			var eventObj = {};
			eventObj.type = type;
			eventObj.callback = callback;
			eventObj.priority = parseInt(priority);
			eventObj.scope = scope || this;
			this.events[type].push(eventObj);
			this.events[type].sort(orderByPriority);
		},
		
		removeEventListener : function(type, callback) {
			var l = this.events[type].length;
			for(var i = 0; i < l; i++) {
				if (this.events[type][i].callback == callback) {
					this.events[type].splice(i, 1);
				}
			}
		},
		
		dispatchEvent : function(event) {
			if (typeof this.events[event.type] == 'undefined') return;
			var l = this.events[event.type].length;
			for(var i = 0; i < l; i++) {
				event.target = event.currentTarget = this;
				event.toString = function() {
					return "[Event {type="+event.type+"} ]";
				}
				this.events[event.type][i].callback.apply(
					this.events[event.type][i].scope, [event]
				);
			}
		}
	}
})

/*
 * Class UI < EventTarget
 * Classe base de interface, atrela um elemento atravéz do id à instância da classe.
 */
UI = EventDispatcher.$extend({
		
		//Elemento HTML
		element : null, 
		
		//construtor
		__init__ : function (id) {
			var el = $("#" + id);
			if (el.length) 
				this.element = $(el);
			this.createChildren();
		}, 
		
		/*
		 * createChildren:
		 * Funcão executada após o construtor, ideal para criar e montar elementos da instância.
		 */
		createChildren : function () {
		}
	});
	
/*
 * Class Application < UI:
 * Classe central das funcionalidades da aplicação/site.
 */
	Application = UI.$extend(function () {

	    //private
	    var DEFAULT_WALLPAPERS = [
			"/util/img/papeldeparede/imgPapeldeFundo01.jpg",
			"/util/img/papeldeparede/imgPapeldeFundo02.jpg",
			"/util/img/papeldeparede/imgPapeldeFundo03.jpg",
			"/util/img/papeldeparede/imgPapeldeFundo04.jpg",
			"/util/img/papeldeparede/imgPapeldeFundo05.jpg",
			"/util/img/papeldeparede/imgPapeldeFundo06.jpg",
			"/util/img/papeldeparede/imgPapeldeFundo07.jpg",
			"/util/img/papeldeparede/imgPapeldeFundo08.jpg",
			"/util/img/papeldeparede/imgPapeldeFundo09.jpg"
		];

	    function resizeCardapioWindow(e) {
	        var app = e.data.app;
	        var cardapioWindow = app.Windows.getCurrent();
	        var content = $(".content-cardapio", cardapioWindow);

	        content.height(app.element.height() - app.Nav.element.height() - 50);
	        content.width(app.element.width());
	    }

	    function resizeImageBox(e) {
	        var app = e.data.app;
	        var imageWindow = app.Windows.getCurrent();
	        var content = $(".content-imagebox", imageWindow);
	        var button = $("a.fecharimagebox", imageWindow);
	        var image = content.find(".image");
	        content.height(app.element.height() - 61);
	        image.height(content.height());

	        button.css("left", image.position().left + (image.width() - button.width()));
	    }

	    //class prototype
	    return {

	        //public
	        //Components;
	        Wallpaper: null,
	        Nav: null,
	        Windows: null,
	        WidgetsBar: null,
	        Stage: null,

	        //public construtor
	        createChildren: function () {
	            this.Wallpaper = this.element.find("#wallpaper");
	            $(window).resize(function (e) {
	                var image = $(".image", this.Wallpaper);

	                var bw = $("body").width(), bh = $("body").height(), w, h;
	                var ow = 1600, oh = 800;
	                var rt = ow / oh;
	                w = bw;
	                h = bw / rt;
	                if (h < bh) {
	                    h = bh;
	                    w = bh * rt;
	                }

	                image.width(w).height(h);
	                image.css("top", -(h - bh) / 2);
	                image.css("left", -(w - bw) / 2);

	            } .bind(this));

	            //Instanciando Nav 
	            this.Nav = new Nav("nav", this);
	            //Adicionar um evento a navegação muda para outro conteúdo;
	            this.Nav.addEventListener("loadContent", this._onLoadContent.bind(this));

	            //Instanciando Windows 
	            this.Windows = new Windows("windows");
	            //Adicionar um evento quando a janela ['bemvindo' > Windows] é fechada;
	            this.Windows.addEventListener("hide-bemvindo", this._onHideBemvindoWindow.bind(this));
	            this.Windows.addEventListener("show-cardapio", this._onShowCardapioWindow.bind(this));
	            this.Windows.addEventListener("show-imagebox", this._onShowImageBoxWindow.bind(this));
	            this.Windows.addEventListener("hide-cardapio", this._onHideCardapioWindow.bind(this))
	            this.Windows.addEventListener("hide-imagebox", this._onHideImageBoxWindow.bind(this));

	            //Instanciando Stage;
	            this.Stage = new Stage("stage", 10);

	            //Instanciando WidgetsBar
	            this.WidgetsBar = new WidgetsBar("widgetsbar", this.Stage);

	            //Instanciando Content
	            this.Content = new Content("content", this.Nav);
	            this.Content.addEventListener("changeContent", this._onChangeContent.bind(this));

	            //Verificar o primeiro acesso e mostrar o papel de parede de acordo com a configuração do usuário.
	            //this.showFirstAccessWindow();
	            this.changeWallpaper(this.getUserWallpaper());
	        },

	        /*
	        * getUserWallpaper:
	        * Obtem o papel de parede do usuário no Cookie:'piraja_wallpaper', caso contrário será retornado um aleatório pelo array DEFAULT_WALLPAPERS.
	        * return:
	        * url:String
	        */
	        getUserWallpaper: function () {
	            var url = $.cookie("piraja_wallpaper");
	            if (!!url)
	                return url;

	            return DEFAULT_WALLPAPERS[0]; //DEFAULT_WALLPAPERS[Math.floor(Math.random() * DEFAULT_WALLPAPERS.length)];
	        },

	        /*
	        * getCurrentWallpaper:
	        * Obtem o papel de parede do elemento #wallpaper.
	        */
	        getCurrentWallpaper: function () {
	            return this.Wallpaper.find("img.image").attr("src");
	        },

	        /*
	        * setWallpaper:
	        * Define o papel de parede
	        * @urlImage:Stringurl da imagem do papel de parede
	        */
	        changeWallpaper: function (urlImage) {
	            var image = this.Wallpaper.find(".image");
	            image.fadeOut('fast', function () {
	                image.attr("src", urlImage);
	                image.bind('load', function () {
	                    $(window).resize();
	                    image.hide().fadeIn("slow");
	                    image.unbind('load', arguments.callee);
	                });
	            });
	        },

	        /*
	        * setUserWallpaper:
	        * Define o papel de parede pessoal do usuário, gravando o escolhido no Cookie:'piraja_wallpaper'
	        * @urlImage:Stringurl da imagem do papel de parede
	        */
	        setUserWallpaper: function (urlImage) {
	            $.cookie("piraja_wallpaper", urlImage);
	            this.changeWallpaper(urlImage);
	        },

	        /*
	        * showFirstAccessWindow:
	        * Mostra a janela inicial caso seja o primeiro acesso do usuário pelo Cookie:'piraja_access'. 
	        */
	        showFirstAccessWindow: function () {
				
	            if ($.cookie('piraja_access') != "true" && this.Nav.getCurrentPage() === "/home") {
	                this.Windows.show("bemvindo", { topMost: true });
	            }
	        },

	        /*
	        * _onChangeContent:
	        */
	        _onChangeContent: function (evt) {
	            if (this.Windows.getCurrentClass() != "bemvindo")
	                this.Windows.hide();
	        },

	        /*
	        * _onHideBemvindoWindow:event
	        * Evento acionado quando a janela ('bemvindo' > Windows) é fechada.
	        * Salvar no Cookie:piraja_access uma flag indicando o primeiro acesso realizado.
	        */
	        _onHideBemvindoWindow: function (evt) {
	            var current = this.Windows.getCurrent();

	            if ($("#optinBemvindo:checked", current).length)
	                $.cookie('piraja_access', 'true');
	        },

	        /*
	        * _onLoadContent:event
	        * Evento acionado quando o menu de navegação troca de conteúdo. 
	        */
	        _onLoadContent: function (evt) {
	            this.Content.setContent(evt.file);
	        },

	        /*
	        * _onShowCardapioWindow:event
	        */
	        _onShowCardapioWindow: function (evt) {
	            var cardapioWindow = this.Windows.getCurrent();
	            var content = $(".content-cardapio", cardapioWindow);
	            var swfReader = '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" style="width:100%;height:100%" id="reader" ><param name="movie" value="/Util/Swf/PagesReader/Reader.swf?xml={XML_FILE}&basepath=/Util/Swf/PagesReader/data/" /><param name="allowfullscreen" value="true"/><param name="bgcolor" value="#333333"/><param name="menu" value="false"/><param name="wmode" value="transparent"/><embed src="/Util/Swf/PagesReader/Reader.swf?xml={XML_FILE}&basepath=/Util/Swf/PagesReader/data/" type="application/x-shockwave-flash" allowfullscreen="true" menu="false" wmode="transparent" style="width:100%;height:100%" flashvars="" bgcolor="#333333" /></object>';
	            var params = cardapioWindow.data("settings") && cardapioWindow.data("settings").data;
	            if (params) {
	                swfReader = swfReader.replace(/{XML_FILE}/gi, params.id + ".xml");
	            }
	            content.empty();
	            content.append(swfReader);
	            $(window).bind('resize', { app: this }, resizeCardapioWindow);
	            $(window).resize();
	        },

	        /*
	        * _onShowImageBoxWindow:event
	        */
	        _onShowImageBoxWindow: function (evt) {
	            var current = this.Windows.getCurrent();
	            var content = $(".content-imagebox .inner-content", current);
	            var _this = this;
	            var image = $("<img src='" + evt.settings.data + "' class='image' />").load(function (e) {
	                $(this).css("max-height", $(this).height());
	                $(this).css("max-width", $(this).width());
	                $(window).bind('resize', { app: _this }, resizeImageBox);
	                $(window).resize();
	            });
	            content.prepend(image);
	        },

	        /*
	        * _onHideImageBoxWindow:event
	        */
	        _onHideImageBoxWindow: function (evt) {
	            var current = this.Windows.getCurrent();
	            var content = $(".content-imagebox .inner-content", current);
	            content.css("height", "100%");
	            var image = $(".content-imagebox .image", current);
	            image.remove();
	            $(window).unbind('resize', resizeImageBox);
	        },

	        /*
	        * _onShowCardapioWindow:event
	        */
	        _onHideCardapioWindow: function (evt) {
	            var current = this.Windows.getCurrent();
	            var content = $(".content-cardapio", current);
	            content.empty();
	            $(window).unbind('resize', resizeCardapioWindow);
	        }
	    }
	});

/*
 * Class WidgetApp < UI
 * Classe base do widgets-apps;
 */
WidgetApp = UI.$extend(function () {
		//private;
		var _startZIndex = 0;
		var _delay = 0;
		
		return{
			//public
			config : {}, 
			
			__init__ : function (id, config, startZIndex) {
				_startZIndex = startZIndex || _startZIndex;
				this.config = config;
				
				this.$super(id);
				
				if(!!this.config.settings)
					this.element.css(this.config.settings)
			}, 
			
			createChildren : function () {
				var element = this.element;
				
				this.element.data("widgetappclass", this);
				
				element.hide().delay(500).slideDown('slow');
				
				element.draggable({
						disabled : true,
						stop : this._onStopMove.bind(this),
						start : this._onStartMove.bind(this)
					});
				
				if (element.is('.widget-drag-point')) {
					element.draggable("enable");
					element.css("cursor", "move");
				} else {
					this.element.find('.widget-drag-point') 
					.mouseenter(function (e) {
							element.draggable("enable");
							element.css("cursor", "move");
						}) 
					.mouseleave(function (e) {
							element.draggable("disable");
							element.css("cursor", "inherit");
						});
				}
				
				var closeButton = this.element.find('.widget-close');
				
				if(closeButton.length)
					closeButton.click(this._onClose.bind(this));
			}, 
			
			/*
			 * updateConfig:
			 * Atualizar a configuração e dispara um evento;
			 */
			update : function (updateData) {
				$.extend(true, this.config, updateData);
				this.dispatchEvent({
						type : "update", 
						currentApp : this, 
						currentConfig : this.config
					});
			},
			
			/*
			 * _sortIndexes:event
			 */
			_sortIndexes : function(index, includeTop) {
				var children = this.element.parent().children();
				var len = includeTop == true ? children.length+1 : children.length;
				var target;
				var newIndex;
				while(index++ < len) {
					newIndex = _startZIndex+(index-2);
					target = children.filter("[widget-index='"+(index)+"']");
					target.attr("widget-index", index-1).css("z-index", newIndex)
					target.data("widgetappclass").update({settings:{"z-index":newIndex}});
				}
				newIndex = _startZIndex+len-1;
				this.element.attr("widget-index", len).css("z-index", newIndex);
				this.update({settings:{"z-index":newIndex}});
			},
			
			/*
			 * _onClose:event
			 */
			_onClose : function (e, ui) {
				
				e.preventDefault();
				
				this.element.slideUp('fast', function(){
						var index = this.element.attr("widget-index");
						this._sortIndexes(index);
						this.element.remove();
						this.dispatchEvent({
								type : "close", 
								currentApp : this, 
								currentConfig : this.config
							});
					}.bind(this));
			},
			
			/*
			 * _onStartMove:event
			 */
			_onStartMove : function (e, ui) {
				var children = this.element.parent().children();
				var index = parseInt(this.element.attr("widget-index"));
				
				if(!isNaN(index))
					this._sortIndexes(index)
			},
			
			/*
			 * _onStopMove:event
			 */
			_onStopMove : function (e, ui) {
				this.update({settings:ui.position});
			}
		}
		
	});

/*
 * Class Stage < UI
 * Classe do container e controle de widgets
 */
Stage = UI.$extend(function () {
		//private;
		var _startZIndex = 0;
		
		return{
			//public
			apps : null, 
			
			__init__ : function (id, startZIndex) {
				_startZIndex = startZIndex || _startZIndex;
				var data = $.parseJSON($.cookie('piraja_apps'));
				this.apps = data || [];
				this.$super(id);
			}, 
			
			createChildren : function () {
				this.checkInstalledWidgets();
			}, 
			
			/*
			 * getApps:
			 */
			getApps : function () {
				return this.apps;
			}, 
			
			/*
			 * openWidgetApplication:
			 * Abre/Instala widget
			 * @data:Objectobjeto de configuracao do widget;
			 */
			openWidgetApplication : function (data, isAutoInstall) {
				if (data) {
					$.get(data.root + 'widget.html', function (resultData) {
							
							var bodyFragment = resultData.slice(resultData.indexOf("<body>") + 6, resultData.indexOf("</body>"));
							
							this.element.append($(bodyFragment));
							var id = this.element.find(".widget-app:last").attr("id");
							
							var app = new WidgetApp(id, data, _startZIndex);
							app.addEventListener("update", this._onUpdateApp.bind(this));
							app.addEventListener("close", this._onCloseApp.bind(this));
							
							if(this._getByAppId(data.appid) === null) {
								app.element.css("z-index", _startZIndex+this.apps.length).attr("widget-index", (this.apps.length+1));
								data.settings["z-index"] = this.element.find("#"+id).css("z-index");
								this.apps.push(data);
								this.updateConfig();
								this.dispatchEvent({
										type:"opennew",
										appid:data.appid,
										autoInstall: isAutoInstall || false
									});
							}
							else {
								app.element.attr("widget-index", (parseInt(app.element.css("z-index"))-_startZIndex+1));
								this.dispatchEvent({
										type:"open",
										appid:data.appid
									});
							}
							
						}
						.bind(this));
				}
			}, 
			
			/*
			 * closeWidgetApplication:
			 */
			closeWidgetApplication : function (appid) {
				if (!!appid) {
					var len = this.apps.length;
					while(len-- > 0) {
						if(this.apps[len].appid === appid)
						{
							this.apps.splice(len, 1);
							this.updateConfig();
							this.dispatchEvent({
									type:"closefromstage",
									appid:appid,
									target:this
								});
							break;
						}
					}
				}
			}, 
			
			/*
			 * updateWidgetConfig:
			 * Salva/Atualiza a configuração do aplicativo em questão no Cookie:"piraja_apps"
			 */
			updateConfig : function (appconfig) {
				
				if (!!appconfig) {
					var currentAppConfig = this._getByAppId(appconfig.appid);
					if (!!currentAppConfig) 
						$.extend(currentAppConfig, appconfig);
				}
				
				$.cookie("piraja_apps", $.toJSON(this.apps));
			}, 
			
			/*
			 * checkInstalledWidgets:
			 */
			checkInstalledWidgets : function () {
				var delay = 0;
				$.each(this.apps, function (key, val) {
						setTimeout(function(valdata){
							this.openWidgetApplication(valdata);
						}.bindWithArgs(this, val), key*500);
					}
					.bind(this));
			}, 
			
			/*
			 * _getByAppId:
			 * Procurar nos aplicativos instalados
			 */
			_getByAppId : function (appid) {
				var len = this.apps.length;
				while (len-- > 0) {
					if (this.apps[len].appid === appid) 
						return this.apps[len];
				}
				return null;
			}, 
			
			/*
			 *
			 */
			_onUpdateApp : function (evt) {
				this.updateConfig(evt.currentConfig);
			},
			
			_onCloseApp : function (evt) {
				this.closeWidgetApplication(evt.currentConfig.appid);
			}
		}
	});

/*
 * Class WidgetsBar < UI
 * Responsável por carregar e apresentar os apps/widgets contidos no site;
 */
	WidgetsBar = UI.$extend(function () {

	    //private

	    //WIDGETS_DATA: Url do arquivo json de configuração do widgets disponíveis
	    var WIDGETS_DATA = "/util/data/widgets.json?v3"
	    var _opened = false;
	    var _data;
	    var _configData;
	    var _initItems;

	    return {
	        //public
	        toggleButton: null,
	        list: null,
	        carousel: null,
	        toolTip: null,
	        stage: null,

	        __init__: function (id, stage/*:Stage*/) {
	            if (stage instanceof Stage)
	                this.stage = stage;

	            this.$super(id);
	        },

	        createChildren: function () {
	            this.element.append($('<a href="#" class="toggle"><div class="arrow"></div></a>')).append($('<ul class="list"></ul>'));

	            this.toggleButton = this.element.find("a.toggle").click(this.toggle.bind(this));

	            this.list = this.element.find(".list")
	            this.toolTip = this.element.find(".tooltip");

	            this.stage.addEventListener("opennew", this._onOpenNewApp.bind(this));
	            this.stage.addEventListener("closefromstage", this._onCloseApp.bind(this))

	            $.getJSON(WIDGETS_DATA, function (data) {

	                var items = [];

	                _configData = data;
	                _data = data.concat();

	                if (_data.length > 0 /*&& !$.cookie("piraja_openedapp")*/) {
	                    this.toolTip.hide().delay(2000).fadeIn('slow');
	                    var toolTip = this.toolTip;
	                    var animating = function () {
	                        toolTip.animate({ left: "-=15px" }, 400).animate({ left: "+=15px" }, 370, arguments.callee);
	                    }
	                    animating();
	                }

	                var stageApps = this.stage.getApps();

	                if (stageApps) {
	                    var len;
	                    $.each(stageApps, function (key, val) {
	                        len = _data.length;
	                        for (var i = 0; i < len; i++) {
	                            if (val.appid === _data[i].appid) {
	                                _data.splice(i, 1);
	                                break;
	                            }
	                        }
	                    });
	                }

	                var delay = 0;
	                $.each(_data, function (key, val) {
	                    if (val.autoinstall != true) {
	                        if (typeof val.exclude === "undefined") {
	                            //preload action
	                            if ($.isArray(val.preload))
	                                $.each(val.preload, function (index, image) {
	                                    var preloadImage = new Image();
	                                    preloadImage.src = val.root + image;
	                                })

	                            items.push(this._getAppHTMLItem(val));
	                        }
	                    } else {
	                        this.stage.openWidgetApplication(val, true);
	                    }
	                }
							.bind(this));

	                _initItems = items;
	                //console.log('_initItems', _initItems);

	                this.list.html(items.join(''));

	                this.list.jcarousel({
	                    vertical: true,
	                    scroll: 3
	                });

	                this.carousel = this.list.parents(".jcarousel-container-vertical");
	                this.carousel.data('dragapply', function () {
	                    this.find(".app-drag").draggable({
	                        helper: "clone",
	                        revert: "invalid",
	                        opacity: 0.7,
	                        appendTo: "#main",
	                        scope: "apps",
	                        zIndex: 999
	                    });
	                }
							.bind(this.carousel));

	                this.carousel.data('dragapply')();
	                this.stage.element.droppable({
	                    scope: "apps",
	                    accept: ".app-drag",
	                    drop: this._onDropStage.bind(this)
	                });

	                $(window).resize(this._onWindowResize.bind(this));
	                $(window).resize();
	            }
					.bind(this));
	        },

	        toggle: function (e) {
	            e.preventDefault();

	            this.element.animate({
	                width: _opened ? '25px' : '155px'
	            }, 250, null, this._onWindowResize.bind(this));
	            this.toggleButton.toggleClass("selected");

	            this.toolTip.find(".step1").toggleClass("hidden");
	            this.toolTip.find(".step2").toggleClass("hidden");

	            _opened = !_opened;
	        },

	        /*
	        * getData:
	        * $id:String::identificador do aplicativo/widget;
	        */
	        getData: function (appid) {
	            var appdata;
	            var len = _configData.length;
	            while (len-- > 0) {
	                if (_configData[len].appid === appid)
	                    return _configData[len];
	            }
	            return appdata;
	        },

	        /*
	        * _getAppHTMLItem:event
	        */
	        _getAppHTMLItem: function (val) {
	            if (!!val)
	                return '<li><div class="app-drag" id="' + val.appid + '"><img src="' + (val.root + val.icon) + '" alt="' + val.name + '" /><span>' + val.name + '</span></div></li>';

	            return null;
	        },

	        /*
	        * _getAppHTMLItem:event
	        */
	        _checkPreferredPositionIndex: function (index) {
	            var items = this.list.children();
	            var len = items.length;
	            for (var i = 1; i <= len; i++) {
	                appdata = this.getData($(items[i - 1]).find(".app-drag").attr("id"));
	                if (index < appdata.defaultBarIndex)
	                    return i;
	            }
	            return index == len ? index + 1 : index;
	        },

	        /*
	        * _onCloseApp:event
	        */
	        _onCloseApp: function (evt) {
	            var appdata = this.getData(evt.appid);
	            if (appdata) {
	                var newItem = this._getAppHTMLItem(appdata);
	                var currentLength = this.list.find("li").length;
	                var positionIndex = Math.max(1, Math.min(currentLength, appdata.defaultBarIndex));
	               // console.log("caleb teste  ----- > " + _initItems);
	                if (_initItems && _initItems.length == 0) {
	                    this.list.data('jcarousel').add(1, newItem);
	                   _initItems = null;
	                }
	                else {
	                    this.list.data('jcarousel').addAndRedraw(this._checkPreferredPositionIndex(positionIndex), newItem);
	                }
	                this.carousel.data('dragapply')();
	            }
	        },

	        /*
	        * _onOpenNewApp:event
	        */
	        _onOpenNewApp: function (evt) {
	            if (!evt.autoInstall) {
	                //$.cookie("piraja_openedapp", "true");
	                this.toolTip.fadeOut('fast');
	            }
	        },

	        /*
	        * _onDropStage:event
	        */
	        _onDropStage: function (e, ui) {
	            var index = ui.draggable.parent().index() + 1;
	            var appid = ui.draggable.attr("id");

	            setTimeout(function () {
	                this.list.data('jcarousel').removeAndAnimate(index);
	                this.carousel.data('dragapply')();
	            }
					.bind(this), 1);

	            var appconfig = this.getData(appid);
	            appconfig.settings = ui.position;

	            this.stage.openWidgetApplication(appconfig);
	        },

	        /*
	        * _onWindowResize:event
	        */
	        _onWindowResize: function (e) {

	            if (this.carousel)
	                this.carousel.height(this.element.height() - (88 + (parseInt(this.carousel.css("padding-top")) + parseInt(this.carousel.css("padding-bottom")))));

	            if (this.stage)
	                this.stage.element.width(this.element.offset().left);
	        }
	    }
	});

/*
 * Class Content < UI
 * Responsável por carregar conteúdos (arquivos HTML) na página.
 */
Content = UI.$extend(function () {
		
		//private;
		var _currentContent;
		var _file;
		
		//class prototype
		return{
			
			//public
			background : null,
			nav:null,
			close:null,
			contentNoOverlay:false,
			
			__init__:function(id, nav)
			{
				this.nav = nav;
				this.$super(id);
			},
			
			createChildren : function () {
				this.element.append($('<div class="background"></div>').css("opacity", ".9")).hide();
				this.background = this.element.find(".background");
				this.close = this.element.find(".close-content").show();
				$(window).resize(this._onWindowResize.bind(this));
			}, 
			
			/*
			 * setContent:
			 * Controle de troca de página no meio do conteúdo
			 * @file:String url do arquivo HTML
			 */
			setContent : function (file) {
				if (!!file) {
					_file = file;
					
					var noOverlay = this.nav.FilesConfig.NoOverlay && this.nav.FilesConfig.NoOverlay.toArray().join().indexOf(file) > -1;
					
					this.hideContent(function () {
							this.background.addClass("loading");
							this.background.show();
							
							if(noOverlay) {
								this.background.hide();
								this.element.show();
								this.render(this);
							}
							else 
								this.element.delay(500).slideDown('fast', this.render.bind(this));
							
							this.contentNoOverlay = noOverlay;
						}
						.bind(this));
				} else {
					
					try {
						$("title").text($("meta[name='title']").attr("content"));
					} catch (err) {
					}
					
					this.hideContent();
				}
				
				this.dispatchEvent({
						type : "changeContent", 
						currentContent: _currentContent,
						file: _file
					});
			}, 
			
			/*
			 * render:
			 * Mostrar conteúdo deifinitivamente atravez de um iframe;
			 */
			render : function () {
				var self = this;
				this.element.append($("<iframe id='frame-content' name='pirajaframe' allowtransparency='true' class='visuallyhidden' frameborder='0'></iframe>"));
				_currentContent = this.element.find("iframe");
				_currentContent.attr("src", _file).height(this.element.height() - 80).width(this.element.width());
				
				$(_currentContent).load(function () {
				
						self.background.removeClass("loading");
						_currentContent.removeClass("visuallyhidden").delay(500).fadeIn('slow');
						
						try {
							var doc = this.contentWindow ? this.contentWindow.document : (this.contentDocument || this.document);
							if (!!doc) {
								$(doc.body).css("background-color", "transparent");
								$("title").text($(doc).find("head title").text());
							}
							
						} catch (err) {
						}
					});
				
				$("#disable").show();
			}, 
			
			/*
			 * hideContent:
			 * Descarrega o conteúdo existente (caso houver)
			 */
			hideContent : function (callback) {
				if (!!_currentContent) {
					if(this.contentNoOverlay)
					{
						_currentContent.fadeOut('fast', function(){
							_currentContent.remove();
							_currentContent = null;
							this.element.delay(500).slideUp('fast', callback);
						}.bind(this));
					}
					else
					{
						_currentContent.remove();
						_currentContent = null;
						this.element.delay(500).slideUp('fast', callback);
					}
				} else if (callback) {
					callback();
				}
				$("#disable").hide();
			}, 
			
			/*
			 * _onWindowResize:event
			 */
			_onWindowResize : function (e) {
				if (!!_currentContent) 
					_currentContent.height(this.element.height() - 80).width(this.element.width());
			}
			
		}
		
	}) 

/*
 * Class Nav < UI
 * Responsável pelo controle do menu de navegação.
 */
	Nav = UI.$extend(function () {

	    //private
	    var DEFAULT_PAGE = "/home";
	    var _currentPage = DEFAULT_PAGE;
	    var _currentSubNav = null;
	    var _currentPageSubNav = null;
	    var _intervalRollOut = null;
	    var _intervalPageSubNav = null;

	    //classe prototype
	    return {

	        FilesConfig: {},
	        app: null,

	        __init__: function (id, app) {
	            this.app = app;
	            this.$super(id);
	            var _this = this;
	            this.element.find("ul:eq(0)").hide();

	            var linksNoOrvelay = this.element.find("ul li a[rel='nooverlay']");

	            if (linksNoOrvelay.length > 0)
	                this.FilesConfig.NoOverlay = linksNoOrvelay.map(function (key, val) {
	                    return $(val).attr("href").toString();
	                })

	            $.history.init(function (hash) {
	                if (hash != "") {
	                    var query = hash.indexOf("?") > -1 ? hash.substr(hash.indexOf("?")) : "";
	                    var paths = hash.replace(query, "").slice(1).split("/");
	                    var file = _this.element.find("#" + paths.slice(-1) + " a").attr("href") || paths.join("/");

	                    if (file) {

	                        if (file != "#")
	                            file += "/" + query;

	                        file = file.replace("//", "/");

	                        _currentPage = hash;
	                        _this.updateNav(paths);
	                        setTimeout(function () {
	                            _this.loadContent(file);
	                        }, 1);
	                    }
	                } else {
	                    _currentPage = DEFAULT_PAGE;
	                }
	                setTimeout(function () {
	                    _this.element.find("ul:eq(0)").fadeIn('fast');
	                }, 250);
	            }, {
	                unescape: "/"
	            });
	        },
			
			getCurrentPage: function() {
				return _currentPage;
			},

	        //public
	        createChildren: function () {
	            var links = this.element.find("ul:eq(0) > li > a");
	            var _this = this;
	            links.each(function (index, el) {
	                $(el).prepend($("<div class='background'><div class='arrow'></div><div class='border'></div></div>"));
	                $(el).mouseenter(_this._onRollOverNav.bind(_this));
	                $(el).mouseleave(_this._onRollOutNav.bind(_this));
	                $(el).click(_this._onSelectNav.bind(_this));

	                var parent = $(el).parent();
	                parent.find("nav.sub ul:eq(0)").mouseenter(_this._onRollOverSubNav.bind(_this));
	                parent.find("nav.sub ul:eq(0)").mouseleave(_this._onRollOutNav.bind(_this));
	                parent.find("nav.sub ul:eq(0) > li > a").click(_this._onSelectNav.bind(_this))
	            });

	            this.element.find("nav.sub ul li:last-child").addClass("last");
	        },

	        /*
	        * select:
	        * Executa a navegação pelo id como argumento.
	        * @id:Stringid da navegacao
	        */
	        select: function (id) {
	            $.history.load("/" + id);
	        },

	        /*
	        * loadContent:
	        * Carrega um conteúdo de acordo com o arquivo HTML.
	        * @htmlFile:String  url do arquivo HTML.
	        */
	        loadContent: function (htmlFile) {
	            this.dispatchEvent({
	                type: "loadContent",
	                nav: this,
	                file: htmlFile == "#" ? null : htmlFile
	            });
	        },

	        /*
	        * updateNav:
	        * Mantém a navegação de acordo com a página no momento.
	        */
	        updateNav: function (newPaths) {
	            var prev = this.element.find(".current");
	            prev.removeClass("current").find("a .background").fadeOut('fast', function () {
	                prev.removeClass("selected");
	                prev.show();
	            });

	            var len = newPaths.length;
	            while (len-- > 0)
	                this.element.find("#" + newPaths[len]).addClass("current");

	            this._releaseNavLink(this.element.find("#" + newPaths.slice(-1) + " > a")[0]);
	        },

	        /*
	        * _onSelectNav:event
	        */
	        _onSelectNav: function (e) {
	            e.preventDefault();

	            var el = $(e.currentTarget);

	            if (el.attr("rel") === "windowcontent") {
	                var self = this;

	                if (_currentPage != DEFAULT_PAGE) {
	                    this.select(DEFAULT_PAGE.slice(1));
	                    var callback = function () {
	                        self.app.Windows.show(el.attr("class"), { opacity: ".2", data: {id:el.parent().attr("id").toString().toLowerCase()} });
	                        self.removeEventListener("loadContent", callback);
	                    }
	                    this.addEventListener("loadContent", callback);
	                }
	                else {
	                    self.app.Windows.show(el.attr("class"), { opacity: ".2", data: { id: el.parent().attr("id").toString().toLowerCase()} });
	                }
	            }
	            else {
	                var parent = el.parent();
	                var subNav = parent.find("nav.sub");
	                if (subNav.length == 0) {
	                    var id = parent.attr("id");
	                    var path = parent.parents("nav li").attr("id");
	                    path = path != null ? path + "/" + id : id;
	                    this.select(path);
	                }
	            }
	        },

	        /*
	        * _selectNav:
	        */
	        _releaseNavLink: function (element) {
	            if (!element)
	                return;

	            var subNav = $(element).parents("li[id]").find("nav.sub")[0];
	            var parent = $(element).parent();
	            if (!!subNav) {
	                if (!!_currentSubNav && _currentSubNav[0] == subNav[0])
	                    return;

	                _currentSubNav = $(subNav);
	                _currentSubNav.fadeIn("slow");
	                parent = _currentSubNav.parent();
	            }

	            parent.addClass("selected")
	            parent.find("a .background").fadeIn('fast');
	        },

	        /*
	        * _hideSubNav:
	        */
	        _hideSubNav: function (forceHide) {
	            if (!!_currentSubNav) {
	                var parent = _currentSubNav.parent(":not(.current)");

	                if (parent.length) {
	                    parent.find("a .background").fadeOut('fast', function () {
	                        parent.removeClass("selected");
	                        parent.find("a .background").show();
	                    });
	                } else {
	                    parent.removeClass("selected");
	                    parent.find("a .background").show();
	                }

	                _currentSubNav.fadeOut('fast');
	                _currentSubNav = null;

	                if (forceHide != true) {
	                    var paths = _currentPage.slice(1).split("/");
	                    if (paths.length > 1)
	                        this._releaseNavLink(this.element.find("#" + paths.slice(-1) + " > a")[0]);
	                }
	            }
	        },

	        /*
	        * _onRollOverNav:event
	        */
	        _onRollOverNav: function (e) {
	            clearTimeout(_intervalRollOut);

	            var el = $(e.currentTarget);
	            var parent = el.parent();

	            if (!!_currentSubNav && !$.contains(parent[0], _currentSubNav[0]))
	                this._hideSubNav(true);

	            this._releaseNavLink(e.currentTarget);
	        },

	        /*
	        * _onRollOutNav:event
	        */
	        _onRollOutNav: function (e) {
	            if (!!_currentSubNav) {

	                if (_currentSubNav.parents("li[id]").attr("id") != _currentPage.slice(1).split("/")[0]) {
	                    var _this = this;
	                    _intervalRollOut = setTimeout(function () {
	                        _intervalRollOut = null;
	                        _this._hideSubNav();
	                    }, 1000);
	                }
	            } else {
	                var parent = $(e.currentTarget).parent();
	                parent.find("a .background").fadeOut('fast', function () {
	                    parent.removeClass("selected");
	                    parent.find("a .background").show();
	                });

	                var paths = _currentPage.slice(1).split("/");
	                if (paths.length > 1)
	                    this._releaseNavLink(this.element.find("#" + paths.slice(-1) + " > a")[0]);
	            }
	        },

	        /*
	        * _onRollOverSubNav:event
	        */
	        _onRollOverSubNav: function (e) {
	            clearTimeout(_intervalRollOut);
	        }
	    }

	}) 

/*
 * Class Windows < UI:
 * Responsável por apresentar conteúdos sobrepostos, overlays e intervenções na página onde se encontra.
 */
Windows = UI.$extend(function () {
		
		//private
		var _currentWindow;
		var _currentClass;
		var _opacity = ".95"
		var _topMostZIndex = 9999;
		var _defaultZIndex;
		
		//class prototype;
		return{
			
			//public
			background : null, 
			
			createChildren : function () {
				this.element.prepend($('<div class="background"></div>').css('opacity', _opacity));
				this.background = this.element.find(".background");
				_defaultZIndex = this.element.css("z-index");
			}, 
			
			/*
			 * getCurrent:
			 * Obtem a janela visível
			 * return:
			 * currentWindow:Elemento HTML
			 */
			getCurrent : function () {
				return _currentWindow;
			},
			
			/*
			 * getCurrentClass:
			 */
			getCurrentClass : function () {
				return _currentClass;
			}, 
			
			/*
			 * show:
			 * Mostra a janela segundo a classe-html
			 * @windowClass:Stringatributo class de um elemento filho do <Windows>
			 */
			show : function (windowClass, options) {
				
				this.hide();
				
				var settings = {
					opacity:_opacity,
					topMost:false,
					data:{}
				};

	            var settings = $.extend(settings, options);

				this.background.css("opacity", settings.opacity);
				
				if(settings.topMost)
					this.element.css("z-index", _topMostZIndex);
				else 
					this.element.css("z-index", _defaultZIndex);
				
				
				var win = this.element.find("." + windowClass);
				win.data("settings", settings);
				
				if (win.length) {
					_currentClass = windowClass;
					_currentWindow = win;
					_currentWindow.show();
					this.element.hide().fadeIn('fast');
					this.dispatchEvent({
							type : "show", 
							window : _currentClass, 
							current : _currentWindow,
							settings : settings
						});
					this.dispatchEvent({
							type : "show-" + _currentClass, 
							current : _currentWindow,
							settings : settings
						});
				}
			}, 
			
			/*
			 * hide:
			 * Esconde a janela vísivel;
			 */
			hide : function () {
				if (_currentWindow && _currentWindow.length) {
					_currentWindow.hide();
					this.element.fadeOut('slow');
					this.dispatchEvent({
							type : "hide", 
							window : _currentClass, 
							current : _currentWindow
						});
					this.dispatchEvent({
							type : "hide-" + _currentClass, 
							current : _currentWindow
						});
					_currentWindow = _currentClass = null;
				}
			}
			
		};
	});
 
