/*
Bitman Windows 0.1
 - requires template.js and jQuery/jQuery UI
 
 TODO:
 z-index niet continue ophogen 
*/
(function(undefined){
		  
	var stack;
		  
	/*
    StackManager object - keeps track of active windows
    */
    var StackManager = function(){
       this.stack = [];
       this.startZIndex = 9;
    };
    
       // publicly accessible functions
    StackManager.prototype = {
        release: function(windowRef){
            //fond the position in the stack of the window
            var rowNrToRelease = null;
            $.each(this.stack, function(rowNr){
                if(this === windowRef){
                    rowNrToRelease = rowNr;
                }
            });
            
            //remove the window from the stack
            if(rowNrToRelease !== null){
                this.stack.splice(rowNrToRelease, 1);
            }
            
            this.recalculateZIndices();
        },
       
        push: function(windowRef){
            this.stack.push(windowRef);
            this.recalculateZIndices();
        },
       
        moveToTop: function(windowRef){
            this.release(windowRef);
            this.push(windowRef);
        },
       
        recalculateZIndices: function(){
            var zIndex = this.startZIndex;
            $.each(this.stack, function(){
                var windowRef = this;
                $(windowRef).css('zIndex', zIndex);
                zIndex++;
            });
        },
       
        dump: function(){
            console.log(this.stack);
        }
    };
	
	/*
	Window object
		template - name of the template to be used for this window
	*/
	var Window 			= function(templateName, xPos, yPos, data){ 
		var that		= this;
		
		that.template   = null;
		
		var viewStack = [];
		var shadowLayer;
		
		var settings = {
			templateName: templateName,
			xPos: xPos,
			yPos: yPos,
			closable: false,
			draggable: false,
			forceFocus: false
		};
		
		if(typeof(Template) === 'undefined'){
			throw('windows.js requires template.js!');
		}else{
			that.template 		= new Template(templateName);
			
			// if there's no stack, create it
			if(typeof(windowStack) === 'undefined'){
				windowStack = new StackManager(); 		
			}
			
			// if there's data to show in this window, add it
			if(typeof(data) === 'object'){
				that.template.fill(data);
			}
			
			// make close button invisible by default (setClosable can make it visible again)
			that.template.self().find('.btnClose').hide();
			
			// push this window onto the stack
			windowStack.push(that.template.self());
			
			that.template.self().mousedown(function(){
				windowStack.moveToTop(that.template.self());
			});
			
			var fn = that.template;
			
			// publicly accessible functions
			fn.show =  function(){
				// if no coordinates are given, use center of screen as position
				if(typeof(settings.xPos) !== 'number'){
					settings.xPos = ($(window).width() / 2) - (that.template.self().width() / 2);
				}
				if(typeof(settings.yPos) !== 'number'){
					settings.yPos = ($(window).height() / 2) - (that.template.self().height() / 2);
				}
				
				// move window to right coordinates
				that.template.self().css('left', settings.xPos);
				that.template.self().css('top', settings.yPos);			
				
				// check if rest of GUI needs to be hidden
				if(settings.forceFocus && !shadowLayer){
					// add shadow layer
					shadowLayer = $('<div id="shadowLayer"></div>');
					
					shadowLayer.appendTo($('body'));
					windowStack.push(shadowLayer);
					
                    shadowLayer.click(function(event){
                        event.stopPropagation();
                        event.preventDefault();
                    });
					
				}
				
				//catch events and stop them from propagating down
				that.template.self().click(function(event){
                    event.stopPropagation();
                });
				
				windowStack.moveToTop(that.template.self());
				that.template.self().show();
			};
				
			fn.close = function(){
			    //release all views
                for(i=viewStack.length - 1; i>=0;i--){
                    fn.releaseView(viewStack[i]);
                }
                    
				// check if we can safely close window without losing data!!!
				if(settings.forceFocus){
					// remove shadow layer
					shadowLayer.remove();
					windowStack.release(shadowLayer);
				}
				if(that.template){
				    that.template.self().remove();
				    windowStack.release(that.template.self());
				}
				that.template = null;
				
			};
				
			// make window draggable
			fn.setDraggable = function(trueOrFalse){
				that.template.self().draggable({ handle: '.titleBar', scroll: false });	// check true or false!!!
				that.template.element('titleBar').css('cursor', 'move');
				settings.draggable = trueOrFalse;
			};
			
			// make window closable
			fn.setClosable = function(trueOrFalse){
                if(!settings.closable && trueOrFalse){
                    // make close button visible
                    that.template.self().find('.btnClose').show();
                    
                    // attach event handler
                    that.template.self().find('.btnClose').click(function(event) {
                        event.stopPropagation();
                        fn.close();
                    });
                }
				settings.closable = trueOrFalse;
			};
			
			fn.setForceFocus = function(trueOrFalse){
				settings.forceFocus = trueOrFalse;
			};
			
			
			fn.showView = function(template){
			    for(i in viewStack){
			        viewStack[i].self().remove();
			    }
			    
			    
			    viewStack = [template];
			    template.self().appendTo(that.template.element('contents'));
			    template.self().show();
			    
			};
			
			fn.pushView = function(template){
			    for(i in viewStack){
			        viewStack[i].self().hide();
			    }
			
			    viewStack.push(template);
			    template.self().appendTo(that.template.element('contents'));
			    template.self().show();
			    
			};
			
			fn.releaseView = function(template){
			    if(viewStack[viewStack.length - 1] !== template){
			        throw("Given template is not the top view. Cannot release!");
			    }
			    
			    viewStack.pop();
			    template.self().remove();
			    
			    //if this was the last view, close
			    if(!viewStack.length){
			        fn.close();
			    }else{
			        viewStack[viewStack.length - 1].self().show();
			    }
			    
			    //check if the template has a viewReleased function
			    if(typeof template.viewReleased == 'function'){
			        template.viewReleased();
			    }
			};
			
			return(fn);
		}
	}
	
	// share the Window object with the rest of the world
    window.Window     = Window;
	
	
}());
