/**
 * abstract draggable and resizable window class. 
 */
Mui.Window=new Class({
	Implements: [Events, Options],
	options:{
		left:0,
		top:0,
		width:400,
		height:200,
		minWidth:200,
		minHeight:120,
		title:'Mui Window Title',
		closable:true,
		closeType:'hidden',    //hidden or destroy
		resizable:true,
		resizeMask:false,
		moveable:true,	
		modal:false,
		center:true,
		buttons:[]
	},
	initialize: function(options){
		this.setOptions(options);
		
		this.bound = {
			'focus':    this.focus.bind(this),
			'blur':    this.blur.bind(this),
			'moveStart':this.moveStart.bind(this),
			'moving':  this.moving.bind(this),
			'moved' :   this.moved.bind(this),
			'resizing': this.resizing.bind(this),
			'resized': this.resized.bind(this)
		};
		this.initDom();
		this.initModal();
		this.initTools();
		this.initButtons();
		this.initMove();
		this.initResize();
		
		
		this.winFrame.addEvent('mousedown',this.focus.bind(this));	
	
		this.fit(this.options.width,this.options.height);	
		//window manager
		this.wm = this.options.wm || Mui.wm;
		this.wm.register(this);	
		
		this.shadow=new Mui.Shadow(this.winFrame);		
		this.visible=false;	
		this.maxed=false;
	},
		
	initDom:function(){
		this.options.id=Mui.IdFactory.getId();
		//header
		var thisDom='<div class="m-win-tl"><div class="m-win-tr"><div class="m-win-tc"><div id="' + this.options.id + '-header" class="m-win-header"><span class="m-win-header-text">'+this.options.title+'</span></div></div></div></div>';
		//wrapper
		thisDom+='<div  id="' + this.options.id + '-wrap" class="m-win-wrap">';
		//body
		thisDom+='<div id="'+this.options.id+'-body" class="m-win-body"></div>';		
		//footer
		thisDom+='<div id="'+this.options.id+'-footer"></div></div>';
				
		if (this.options.moveable) {
			thisDom += '<div id="' + this.options.id + '-move-handler" class="m-win-move-handler"></div>';			
		}
		thisDom += '<div id="' + this.options.id + '-tool-container"  class="m-tool-container"></div>';
		if (this.options.resizable) {			
			thisDom += '<div id="' + this.options.id + '-resize-handler" class="m-win-resize"></div>';
			thisDom += '<div id="' + this.options.id + '-resize-proxy" class="m-win-resize-proxy"></div>';
		}
	
		new Element('div',{
			'id':this.options.id,
			'class':'m-win',
			'html':	thisDom,
			'styles':{
				'width':this.options.width,
				'height':this.options.height,
				'top':this.options.top,
				'left':this.options.left
			}	
		}).inject($(document.body));
				
		this.winFrame=$(this.options.id);
		this.winWrap=$(this.options.id+'-wrap');
		this.winBody=$(this.options.id+'-body');
		this.winHeader=$(this.options.id+'-header');
		this.winFooter=$(this.options.id+'-footer');
		this.toolContainer=$(this.options.id+'-tool-container');
		
		this.width=this.options.width;
		this.height=this.options.height;
		this.top=this.options.top;
		this.left=this.options.left;
		
		this.headerHeight=this.winHeader.getBoundHeight();
	},

	initTools:function(){		
		if(this.options.closable){
			this.winToolClose = new Element('a', {
				'class': 'm-tool m-tool-close',
				events: {
					'click': function(event){
						event.stop();
						this.options.closeType=='hidden' ? this.hidden(): this.destroy();
					}.bind(this)
				}
				
			}).inject(this.toolContainer);
		}
		if(this.options.resizable){
			this.winToolMax = new Element('a', {
				'class': 'm-tool m-tool-max',
				events: {
					'click': this.maxAndRestore.bind(this)
				}				
			}).inject(this.toolContainer);	
			/*
			this.winToolMin=new Element('a',{
				'class':'m-tool m-tool-min',
				events:{
					'click':this.min.bind(this)
				}
			}).inject(this.toolContainer);	*/	
		}
		//other tools
	},
	initButtons:function(){
		var len=this.options.buttons.length;
		if (len > 0) {
			this.winFooter.set('class','m-win-footer');
			this.winBtnContainer=new Element("div",{
				'class':'m-win-button-container'
			}).inject(this.winFooter);
			for (var i = 0; i < len; i++) {
				var btn = this.options.buttons[i];
				var btnEl = new Element('input', {
					'type': 'button',
					'value': btn.text,
					'class': 'm-win-button',
					events: {
						'click': btn.handler
					}
				}).inject(this.winBtnContainer);
			}
		}else{
			this.winFooter.set('class','m-win-nofooter');
		}
		this.footerHeight=this.winFooter.getBoundHeight();
	},
	initMove:function(){
		if (this.options.moveable) {
			this.winMoveProxy=new Element('div',{
				id:this.options.id + '-move-proxy',
				'class':'m-win-move-proxy',
				width:this.width,
				height:this.height,
				top:this.top,
				left:this.left
			}).inject(this.winFrame,'after');
			
			this.moveHandlerEl = $(this.options.id+'-move-handler');
			this.moveHandlerEl.addClass('unselectable');
			
			this.moveHandlerEl.addEvent('mousedown',this.bound.moveStart);
		}
	},

	moveStart:function(event){	
		event.stop();	
		this.winFrame.setStyle('display', 'none');
		this.shadow.hidden();
		this.moveMaskEl=new Element('div',{
					'id': this.id+'-move-mask',
					'class':'m-win-mask',
					'style':'z-index:'+this.zIndex						
				}).inject(this.winFrame,'before');
		this.winMoveProxy.setStyles({
			'width': this.width,
			'height': this.height-2,
			'top': this.top,
			'left': this.left,
			'display': 'block'
		});
		$(document).addEvents({
			'mousemove': this.bound.moving,
			'mouseup': this.bound.moved
		});
		
		this.movePrePoint = event.page;	
					
	},
	moving:function(event){		
		this.winMoveProxy.setStyles({
			left:this.winMoveProxy.getStyle('left').toInt()+event.page.x-this.movePrePoint.x,
			top:this.winMoveProxy.getStyle('top').toInt()+event.page.y-this.movePrePoint.y
			
		});
		this.movePrePoint = event.page;
		event.stop();
	},
	moved:function(event){		
		this.winMoveProxy.setStyle('display', 'none');
		$(document).removeEvent('mousemove',this.bound.moving);
		$(document).removeEvent('mouseup',this.bound.moved);	
		var top=this.winMoveProxy.getStyle('top');
		var left=this.winMoveProxy.getStyle('left');
		this.setPosition(left,top);		
		
		this.shadow.move();	
		this.winFrame.setStyle('display', 'block');
		this.shadow.show();
		this.moveMaskEl.dispose();
		this.fireEvent('onMove',this.winFrame);
		event.stop();
	},
	
	initResize:function(options){
		if(this.options.resizable){
			this.resizeProxyEl=new Element('div',{
				'class':'m-win-resize-proxy',
				'styles': {
					'top':0,
					'left':0,
					'width': this.options.width,
					'height': this.options.height
				}				
			}).inject(this.winFrame);
			var handlerEl=$(this.options.id+'-resize-handler');
			handlerEl.addEvent('mousedown', function(){
				this.resizeProxyEl.setStyle('display', 'block');
				this.innerResizeMaskEl=new Element('div',{
						'class':'m-win-mask'				
				}).inject(this.winFrame);
				this.outerResizeMaskEl=new Element('div',{
					'id': this.id+'-outer-resize-mask',
					'class':'m-win-mask',
					'style':'z-index:'+this.zIndex						
				}).inject(this.winFrame,'before');
	
				$(document).addEvents({
					'mousemove':this.bound.resizing,
					'mouseup':this.bound.resized
				});

			}.bind(this));
		}
	},
	resizing:function(event){
		var event = new Event(event);
		event.stop();
		this.adjx=Math.max(event.page.x-this.winFrame.getPosition().x,this.options.minWidth);
		this.adjy=Math.max(event.page.y-this.winFrame.getPosition().y,this.options.minHeight);
		this.resizeProxyEl.setStyles({
			width:this.adjx,
			height:this.adjy
		});
	},
	resized:function(){
		this.resizeProxyEl.setStyle('display', 'none');	
		this.setSize(this.adjx,this.adjy);
		this.fit(this.adjx,this.adjy);
		$(document).removeEvent('mousemove',this.bound.resizing);
		$(document).removeEvent('mouseup',this.bound.resized);
		this.innerResizeMaskEl.dispose();
		this.outerResizeMaskEl.dispose();
		this.shadow.resize();
		this.fireEvent('onResize',this.winFrame);
	},
	
	initModal:function(){		
		if(this.options.modal){
			var ws=Mui.getWindowSize();
			this.modalMaskEl=new Element('div',{
				'id':this.options.id+'-mask',
				'class':'m-win-modal-mask'
			}).inject(this.winFrame,'after');
		}
	},

	//adjust the window body height by the window height.
	fit:function(currentWinWidth,currentWinHeight){					
		this.winBody.setStyle('width',currentWinWidth-2);
		this.winBody.setBoundHeight(currentWinHeight-this.headerHeight-this.footerHeight-2);	
	},	
	hidden: function(){
		this.visible=false;	
		this.winFrame.setStyle('display','none');
		if(this.options.modal){
			this.modalMaskEl.setStyle('display','none');
		}
		this.blur();
		this.wm.blur(this);
		
	},
	destroy: function(){
		if(this.modalMaskEl) this.modalMaskEl.destroy();
		if(this.winMoveProxy) this.winMoveProxy.destroy();
		this.shadow.destroy();
		this.winFrame.destroy();
		this.wm.unregister(this);
		for (var z in this) this[z] = null;		
		this.destroyed = true;
	},
	makeCenter:function(){
		var ws=Mui.getWindowSize();
		var left=Math.max((ws.width-this.width)/2,0);
		var top=Math.max((ws.height-this.height)/2,0);
		this.setPosition(left,top);
		if(this.options.modal){			
			this.modalMaskEl.setStyles({
				'width': ws.width,
				'height': ws.height,					
				'display':'block'
			});
            $(window).addEvent('resize', function(e) {
                var ws=Mui.getWindowSize();
                this.modalMaskEl.setStyles({
                    'width': ws.width,
                    'height': ws.height,
                    'display':'block'
                });
            }.bindWithEvent(this));
		}	
		this.fireEvent('onMove',this.winFrame);
	},
	
	show: function(){	
		this.visible=true;	
		this.winFrame.setStyle('display','block');
		if (this.options.center) {
			this.makeCenter();
			this.shadow.move();
		}		
		this.focus();		
	},
	setPosition:function(left,top){
		this.left=left;
		this.top=top;
		this.winFrame.setStyles({
			'top':top,
			'left':left
		});				
	},
	setSize:function(width,height){	
		this.width=width;
		this.height=height;
		this.winFrame.setStyles({
			'width': width,
			'height': height
		});		
	},
	maxAndRestore:function(event){
		if(this.maxed===false){
			var ws=Mui.getWindowSize();
			this.oldRect={
				x:this.left,
				y:this.top,
				width:this.width,
				height:this.height
			};
			this.setPosition(0,0);
			this.setSize(ws.width,ws.height);	
			
			this.winToolMax.removeClass('m-tool-max');
			this.winToolMax.addClass('m-tool-restore');

			this.fit( ws.width,ws.height);
			
			this.shadow.move();
			this.shadow.resize();
			this.shadow.hidden();	
			this.maxed=true;
			if(this.moveHandlerEl)	{
				this.moveHandlerEl.removeEvents('mousedown');	
				this.moveHandlerEl.setStyle('cursor','default');
			}
						
		}else{
			this.setPosition(this.oldRect.x,this.oldRect.y);
			this.setSize(this.oldRect.width,this.oldRect.height);	
			this.winToolMax.removeClass('m-tool-restore');
			this.winToolMax.addClass('m-tool-max');
			this.fit(this.oldRect.width,this.oldRect.height);
			this.maxed=false;			
			this.shadow.move();
			this.shadow.resize();
			this.shadow.show();	
			if (this.moveHandlerEl) {
				this.moveHandlerEl.addEvent('mousedown', this.bound.moveStart);
				this.moveHandlerEl.setStyle('cursor','');
			}					
		}		
		this.fireEvent('onResize',this.winFrame);
		event.stop();	
	},
	min:function(){
	},
	focus:function(event){
		this.winFrame.removeClass('m-win-blur');
		this.wm.focus(this);	//wm may blur the other windows.	
		if (this.maxed===false) {
			this.shadow.updateZIndex();
			this.shadow.show();
		}
		if(this.moveHandlerEl){
			this.moveHandlerEl.removeEvents('mousedown');
			if (this.maxed === false) {
				this.moveHandlerEl.addEvent('mousedown', this.bound.moveStart);
				this.moveHandlerEl.setStyle('cursor', 'move');
			}
		}			
		this.fireEvent('onfocus',this.winFrame);
	},
	blur:function(){
		this.shadow.hidden();
		this.winFrame.addClass('m-win-blur');
		if(this.moveHandlerEl){
			if (this.maxed === false) {
				this.moveHandlerEl.removeEvent('mousedown', this.bound.moveStart);
				this.moveHandlerEl.setStyle('cursor', 'default');
			}
			this.moveHandlerEl.addEvent('mousedown',this.bound.focus);
		}
		this.fireEvent('onblur',this.winFrame);
	},
	setZIndex: function(z){
		this.zIndex = z;
		this.winFrame.setStyle('z-index', z);
		if(this.options.moveable)
			this.winMoveProxy.setStyle('z-index',z);
		if(this.options.modal){
			this.modalMaskEl.setStyle('z-index',z-5);
		}
	}
});

/*
 * window class which content from a element.
 */
Mui.ElementWindow=new Class({
	Extends: Mui.Window,
	options: {
		el:null
	},
	initialize:function(options){
		this.parent(options);
		this.el=$(this.options.el);
		this.winBody.addClass('m-win-element-body');
		this.winBody.setStyle('height',this.winBody.getStyle('height').toInt()-1);
		this.winBody.adopt(this.el);	
	}
});

/*
 * extended window class which content from a element and can be layout.
 */
Mui.LayoutWindow=new Class({
	Extends: Mui.Window,
	options: {
		el:null,
		layout:'default',
		items:[]
	},
	initialize:function(options){
		this.parent(options);
		this.winBody.adopt($(this.options.el.childNodes));	
		$(this.options.el).dispose();
		
		this.container=new Mui.Container({
			el:this.winBody,
			width:this.winBody.getStyle('width'),
			height:this.winBody.getStyle('height'),
			layout:this.options.layout,
			items:this.options.items
		});
		this.container.render();
		this.addEvent('onResize',this.onResized.bind(this));	
		
	},
	onResized:function(){
		this.container.render();
	}
});
/*
 * extended window class which content from a url.
 */
Mui.IFrameWindow=new Class({
	Extends: Mui.Window,
	options: {
		url:null,
		moveMask:true
	},
	initialize:function(options){
		this.parent(options);
		this.setUrl(this.options.url);
		this.urlChanged=true;
		this.iframeEl=new Element('iframe',{
			id:Mui.IdFactory.getId(),
			name:Mui.IdFactory.getId()+'-name',
			frameborder:0,
			scrolling:'auto'			
		}).inject(this.winBody);
		this.winBody.addClass('m-win-element-body');
		this.winBody.setStyle('overflow','hidden');
		this.winBody.adopt(this.el);
		this.iframeEl.set('width','100%');
		this.iframeEl.set('height','100%');
	},
	show:function(){
		if(this.urlChanged===true)
			this.iframeEl.contentWindow.location=this.url;
		this.urlChanged=false;
		this.parent();	
	},
	setUrl:function(url){
		this.url=url;
		this.urlChanged=true;
	}	
});
/*
 *  abstract extended window clas  for messagebox.
 */
Mui.Messagebox=new Class({
	Extends: Mui.Window,
	options:{
		message:'',
		icon:null,
		isPrompt:false,
		closable:true,
		closeType:'destroy',
		moveable:true,
		modal:true,
		resizable:false
	},
	initialize: function(options){
		this.parent(options);
		this.messageEl=new Element('div',{
			'style':'margin:10px'
		}).inject(this.winBody);
		
		var str='';
		if(this.options.icon!=null){
			str+='<div class="'+this.options.icon+'"></div>'
		}
		
		str+='<div>'+this.options.message;
		if(this.options.isPrompt){
			var w=this.winFrame.getStyle('width').toInt()-26;			
			str+='<br/><input id="'+this.options.id+'-prompt" type="text" style="width:'+w+'px;margin-top:4px"/>';			
		}
		str+='</div';
		this.messageEl.set('html',str);
		this.winBody.setStyle('overflow','hidden');
	}	
});

Mui.Messagebox.ICON={
    INFO : 		'm-win-icon m-win-icon-info',
    WARNING : 	'm-win-icon m-win-icon-warning',
    QUESTION : 	'm-win-icon m-win-icon-question',
    ERROR : 	'm-win-icon m-win-icon-error'
}

/*
 * function for generate a alert messagebox.
 */
Mui.Messagebox.alert=function(options){
	var dialog=new Mui.Messagebox({
		title:options.title || '',
		message:options.message||'',
		icon:options.icon,
		width:options.width,
		height:options.height,
		buttons:[{
			text: 'Ok',
			handler: function(){
				dialog.destroy();
				return 'ok'
			}
		}
		]
	});
	dialog.show();
}
/*
 * function for generate a confirm messagebox.
 */
Mui.Messagebox.confirm=function(options){
	var dialog=new Mui.Messagebox({
		title:options.title || '',
		message:options.message||'',
		icon:options.icon,
		width:options.width,
		height:options.height,
		buttons:[{
			text: 'Yes',
			handler: function(){
				dialog.destroy();
				options.handler(true);
			}
		},{
			text: 'No',
			handler: function(){
				dialog.destroy();
				options.handler(false);
			}			
		}
		]
	});
	dialog.show();
}
/*
 * function for generate a prompt messagebox.
 */
Mui.Messagebox.prompt=function(options){
	var dialog=new Mui.Messagebox({
		title:options.title || '',
		message:options.message||'',
		icon:options.icon,
		width:options.width,
		height:options.height,
		isPrompt:true,
		buttons:[{
			text: 'Ok',
			handler: function(){
				var returnValue=$(dialog.options.id+'-prompt').get('value');
				dialog.destroy();				
				options.handler(returnValue);
			}
		},{
			text: 'Cancel',
			handler: function(){
				dialog.destroy();
				options.handler(null);
			}			
		}
		]
	});
	dialog.show();
}

/*
 * window manage class.
 */
Mui.WindowManager=new Class({
	Implements: [Events, Options],
	options:{
		lastZIndex:10000,
		step:10		
	},
	focused:null,
	initialize: function(options){
		this.hash = [];
		this.setOptions(options);
	},	

	generateZIndex: function(){
		return this.options.lastZIndex+=this.options.step;
	},
	
	getVisibleMaxZIndexWin: function(windows,exclude){
		if (!windows.length) return null;
		var maxWin=null;
		if (windows.length > 0) {
			var seed=0;
			for (var i = 0, j = windows.length; i < j; i++) {
				if (windows[i].zIndex > seed && windows[i] !== exclude && windows[i].visible === true) {
					maxWin = windows[i];
					send=maxWin.zIndex;
				}
			}
		}
		return maxWin;
	},
	register: function(win){
		win.setZIndex(this.generateZIndex());
		this.hash.push(win);
		this.fireEvent('onRegister', win);
	},

	unregister: function(win){
		this.hash.remove(win);
		if (this.focused === win) this.focused = null;		

		this.fireEvent('onUnregister', win);
		
		//focus the max index win
		var maxZIndexWin=this.getVisibleMaxZIndexWin(this.hash);
		if(maxZIndexWin)
			maxZIndexWin.focus();
	},

	focus: function(win){
		if (win === this.focused) 
			return this;
		if(this.focused)
			this.focused.blur();
		this.focused = win;
		win.setZIndex(this.generateZIndex());
		this.fireEvent('onFocus', win);
	},
	
	blur: function(win){
		if(win===this.focused){
			this.focused=null;
			var maxZIndexWin=this.getVisibleMaxZIndexWin(this.hash,win);
			if(maxZIndexWin)
				maxZIndexWin.focus();
		}
	}
});

Mui.wm=new Mui.WindowManager();
