
var AscDialog = new Class({
	options: {
		strs: {
			'close': 'Click to close'
		},
		speed: 500,
		maskOpacity: 0.3,
		maskColor: '#000000',
		isModal: false,
		useArrows: false,
		addCloseBtn: true,
		popOpacity: 1,
		cornerRadius: 10,
		classPrefix: 'Modal',
		place: {
			'ss': { target:'window', io:1, align:'n', offset:0, margin:0 }, // show start
			'se': { trans:'fly', target:'window', io:-1, align:'c', offset:0, margin:0 }, // show end
			'he': { trans:'fly', target:'window', io:1, align:'n', offset:0, margin:0 } // hide end
		},
		onHide: Class.empty,
		onShow: Class.empty,
		transition: Fx.Transitions.Quad.easeInOut
	},
	initialize: function(options){
		this.setOptions(options);
		this.isShowing = false;
		this.mask = false;
		this.pop = false;
		this.isIE = (navigator.userAgent.match(/MSIE/));

		this.fx_dir = 0; // track whether showing/hiding
		this.fx_in_process = false;

		window.addEvent('keyup', function(e){ 
			this.esc(e);
		}.bind(this));			
		window.addEvent('resize', function(e){ 
			this.update(e);
		}.bind(this));			
		window.addEvent('scroll', function(e){ 
			this.update(e);
		}.bind(this));		

		this.init();
	},
	init: function(){
		if (this.pop) {
			this.pop.remove();
		}
		this.add_pop();
		
		if (this.options.isModal) {
			this.add_mask();
			var fxels = [this.pop,this.mask];
		} else {
			var fxels = [this.pop];
		}
		this.fx = new Fx.Elements(fxels, {
			wait: false, 
			duration: this.options.speed, 
			transition: this.options.transition,
			onStart: function() {
				this.fx_in_process = true;
			}.bind(this), 
			onComplete: function() {
				switch (this.fx_dir) {
					case 1:
						this.isShowing = true;
						this.pop.focus(); 
				this.pop.addEvent('focus', function(e){ 
		this.fx.stop();
		}.bind(this));	
				
	this.pop.addEvent('mouseover', function(e){ 
		this.fx.stop();
		}.bind(this));	
	
				this.pop.addEvent('mouseout', function(e){ 
			this.hide();
		}.bind(this));			
						
						
						// to activate pop close by ESC, the ESC keydown for window doesn't work in IE
						break;
					case 0:
						this.isShowing = false;
						this.pop.setStyles({
							'visibility':'hidden',
							'display': 'none'
						});
						if (this.options.isModal) {
							this.mask.setStyle('display', 'none');
						}
						break;				
				}
				this.fx_in_process = false;
			}.bind(this)
		});
	},
	add_mask: function(){
		if (!this.mask)	{
			if (this.isIE){
				// need to use IFRAME for IE in order to cover SELECT elements
				this.mask = new Element('iframe', {
					'class':this.options.classPrefix+'Mask',
					'src':"about:blank",
					'frameborder':0,
					'src':"about:blank"
				}).inject(document.body);
			} else {
				// make mask a div for other browsers
				this.mask = new Element('div', {
					'class':this.options.classPrefix+'Mask'
				}).inject(document.body);
			}
			this.mask.setStyles({
				'position':'absolute',
				'top': 0,
				'left': 0,
				'opacity': 0,
				'z-index': 9999,
				'background-color':this.options.maskColor,
				'display': 'none'
			});
		}
	},
	add_pop: function(){

				this.pop = new Element('div', {
			'class':this.options.classPrefix+'Pop',
			'styles':{
				'position': 'absolute',
				'visibility': 'hidden',
				'top': -1000,
				'left': 0,
				'z-index': 10000,
				'display': 'none'
			}
		}).inject(document.body);

		this.pop.addEvent('keydown', function(e){ 
			this.esc(e);
		}.bind(this));

		// add table for pop with border graphics
		this.poptbl = new Element('table',{ 'class':'grid' }).injectInside(this.pop);
		this.poptbody = new Element('tbody').injectInside(this.poptbl);

		[['nw', 'north', 'ne'],['sw', 's', 'se']].each(function(tds) {
			this.insertPopTblRow(tds);
		}.bind(this));
		// assign td class "north" as contents block of pop
		this.popc = this.poptbl.getElement('td[class=north]');

		if (this.options.useArrows)	{
			this.addPopArrows();
		}

		if (this.options.addCloseBtn) {
			this.close = new Element('div',{
				'class':this.options.classPrefix+'Close'
			}).injectInside(this.pop);
			var close_a = new Element('a', {
				'href':'#',
				'title':this.options.strs.close,
				'events':{
					'click':this.hide.bindWithEvent(this)
				}
			}).injectInside(this.close);
			close_a.addEvent('click', function(e){ 
				if(e) e = new Event(e).stop();
				this.hide();
			}.bind(this));	
		}
	},
	insertPopTblRow: function(tds){
		var tr = new Element('tr').injectInside(this.poptbody);
		tds.each(function(cls) {
			var td = new Element('td',{ 'class':cls }).injectInside(tr);
		});
	},
	addPopArrows: function(){
		// insert pop arrows into pop if they don't already exist
		var an = this.pop.getElement('div[class$=p]');
		if (!an) {
			['n','s','e','w'].each(function(d) {
				var arrw = new Element('div',{ 'class':'a'+d+' p', 'styles': { 'visibility':'hidden'} }).injectInside(this.pop);
				switch (d) {
					case 'n':
						arrw.setStyle('bottom', 1 - arrw.getStyle('height').toInt());
						break;
					case 's':
						arrw.setStyle('top', 1 - arrw.getStyle('height').toInt());
						break;
					case 'e':
						arrw.setStyle('left', 1 - arrw.getStyle('width').toInt());
						break;
					case 'w':
						arrw.setStyle('right', 1 - arrw.getStyle('width').toInt());
						break;				
				}
			}.bind(this));
		}
	},
	show_arrow: function(io, align) {
		var arrw,p={top:0,left:0},a={},nsew='';

		switch (io) {
			case 1:
				nsew = align.substr(0,1);
				break;
			case -1:				
				switch (align) {
					case 'n':
						nsew = 's';
						break;
					case 'w':
						nsew = 'e';
						break;
					case 'e':
						nsew = 'w';
						break;
					case 's':
						nsew = 'n';
						break;				
				}
				break;
		}
		['n','s','e','w'].each(function(d) {
			var arrow = this.pop.getElement('div[class^=a' + d + ']');
			if (arrow) {
				if (nsew == d){
					arrow.setStyle('visibility','visible');
					arrw = arrow;
				} else {
					arrow.setStyle('visibility','hidden');
				}
			}
		}.bind(this));

		if (arrw) {

			switch (io) {
				case 1:
					// outside 
					switch (align) {
						case 'nw': 
						case 'sw':
							a = {
								'left': this.options.cornerRadius,
								'right': 'auto'
							};
							break;
						case 'n':
						case 's':
							a = {
								'left': this.popsize.x/2 - arrw.scrollWidth/2,
								'right': 'auto'
							};
							break;
						case 'ne':
						case 'se':
							a = {
								'left': 'auto',
								'right': this.options.cornerRadius
							};
							break;
						case 'wn':
						case 'en':
							a = {
								'top': this.options.cornerRadius,
								'bottom': 'auto'
							};
							break;
						case 'w':
						case 'e':
							a = {
								'top': this.popsize.y/2 - arrw.scrollHeight/2,
								'bottom': 'auto'
							};
							break;
						case 'ws':
						case 'es':
							a = {
								'top': 'auto',
								'bottom': this.options.cornerRadius
							};
							break;			
					}
					
					switch (align) {
						case 'nw': 
						case 'n':
						case 'ne':
							p.top = -arrw.scrollHeight;
							break;
						case 'wn':
						case 'w':
						case 'ws':
							p.left = -arrw.scrollWidth;
							break;
						case 'en':
						case 'e':
						case 'es':
							p.left = arrw.scrollWidth;
							break;
						case 'sw':
						case 's':
						case 'se':
							p.top = arrw.scrollHeight;
							break;				
		
					}
					break;
				case -1:
					// inside 
					switch (align) {
						case 'n':
						case 's':
							a = {
								'left': this.popsize.x/2 - arrw.scrollWidth/2,
								'right': 'auto'
							};
							break;
						case 'w':
						case 'e':
							a = {
								'top': this.popsize.y/2 - arrw.scrollHeight/2,
								'bottom': 'auto'
							};
							break;
					}
					
					switch (align) {
						case 'n':
							p.top = arrw.scrollHeight;
							break;
						case 'w':
							p.left = arrw.scrollWidth;
							break;
						case 'e':
							p.left = -arrw.scrollWidth;
							break;
						case 's':
							p.top = -arrw.scrollHeight;
							break;				
					}						
					break;

			}
			arrw.setStyles(a);
			return p;
		}
	},
	set_contents: function(msg, cls) {

		if (($type(cls)=='undefined') || (cls=='')) {
			cls = 'n';
		}
		if (this.popc) {
			this.popc.className = 'north ' + cls;
		}
		if (this.popc) {
			this.popc.empty();

			switch($type(msg)) {
				case 'element':
					var msg_cl = msg.clone().injectInside(this.popc);
					break;
				case 'string':
					this.popc.setHTML(msg);
					break;
			}
		}

		// determine the width/height of the pop after adding new content to pop

		var was_dn = false;
		if (this.pop.getStyle('display') == 'none') {
			was_dn = true;
			this.pop.setStyle('display', 'block');
		}
		this.popsize = this.pop.getSize().size;
		if (was_dn) {
			this.pop.setStyle('display', 'none');
		}

	},
	get_key_code: function(e){
		if (!e) {e = window.event;}
		var kc;
		if (e.keyCode)	{
			kc = e.keyCode;
		}
		return kc;
	},
	esc: function(e){
		if (this.isShowing)	{
			var kc = this.get_key_code(e);
			if (kc == 27) {
				this.hide();
			}
		}
	},
	show: function() {
		if(!this.isShowing){

			// set the starting position of the pop

			var start = {
				'visibility':'visible',
				'display': 'block',
				'opacity': 0
			};

			// both fade and fly trans fades in
			var fx = {
				'0': { 
					'opacity': this.options.popOpacity
				}
			};

			var end_xy = this.coord(this.options.place.se.target, this.options.place.se.io, this.options.place.se.align, this.options.place.se.offset, true);

			if ((this.options.place.se.trans == 'fly')) {

				fx['0'].top = end_xy.top;
				fx['0'].left = end_xy.left;
				fx['0'].margin = this.options.place.se.margin;

				if ((typeof(this.options.place.ss) == 'object') && (this.options.place.ss.target !==''))
				{
					var start_xy = this.coord(this.options.place.ss.target, this.options.place.ss.io, this.options.place.ss.align, this.options.place.ss.offset, false);
					if (start_xy) {
						fx['0'].top = [start_xy.top,end_xy.top];
						fx['0'].left = [start_xy.left,end_xy.left];
					}
				}


			} else {
				// just fade into the end coords
				start.top = end_xy.top;
				start.left = end_xy.left;
			}
			this.pop.setStyles(start);

			// show fx for pop

			if (this.options.isModal) {
				this.add_mask(); // only adds one if it doesn't exist
				this.mask.setStyles({
					'height': window.getScrollHeight(),
					'width': window.getScrollWidth(),
					'display': 'block'
				});
				// fx for mask
				fx['1'] = { 'opacity': this.options.maskOpacity };
			}
			this.fx_dir = 1;
			this.fx.start(fx);
			this.fireEvent('onShow');
		}
	},
	hide: function() {
		if(!this.isShowing) {
			return false;
		}
		this.fireEvent('onHide');
		this.fx.stop();
		this.fx_dir = 0;
		// fx for pop
		var fx = {
			'0': { 
				'opacity': 0
			}
		};
		if (this.options.place.he.trans == 'fly') {

			var start_xy = this.coord(this.options.place.se.target, this.options.place.se.io, this.options.place.se.align, this.options.place.se.offset, false);

			var end_xy = this.coord(this.options.place.he.target, this.options.place.he.io, this.options.place.he.align, this.options.place.he.offset, false);

			fx['0'].top = [start_xy.top,end_xy.top];
			fx['0'].left = [start_xy.left,end_xy.left];
			fx['0'].margin = this.options.place.he.margin;
		}
		if (this.options.isModal) {
			// fx for mask
			fx['1'] = { 'opacity': 0 };
		}
		this.fx.start(fx);
	},
	update: function(e) {
//		if(e) e = new Event(e).stop();
		if (this.isShowing) {
			if (this.options.isModal) {
				// resize the mask to the new size of the window
				var size = window.getSize();
				this.mask.setStyles({
					'height': (size.size.y > size.scrollSize.y)?size.size.y:size.scrollSize.y,
					'width': size.size.x
				});
			}
			if ((this.options.place.se.target == 'window') && (this.options.place.se.io==-1)) {
				// if the pop is inside the window
				this.fx.stop();

				var coord = this.coord('window', -1, this.options.place.se.align, this.options.place.se.offset, false);

				// move pop to the center of visible screen
				this.fx.start({
					'0': { 
						'top': coord.top,
						'left': coord.left,
						'margin': this.options.place.se.margin
					}
				});
			}
		}
	},
	movePop: function(target, io, align, offset, margin) {
		var coord = this.coord(target, io, align, offset, true);
		if (coord)
		{
			this.pop.setStyles({
				'top': coord.top,
				'left': coord.left,
				'margin': margin
			});
		}
	},
	coord: function(target, io, align, offset, arr_mode) {
		var top=0,left=0,tdim=0;

		if (target == 'window') {
			top = window.getScrollTop();
			left = window.getScrollLeft();
			tdim = { x:window.getWidth(), y:window.getHeight() };
		} else {
			if (typeof(target)=='string') {
				var t = $(target);
			} else {
				var t = target;
			}
			if (t) {
				var tpos = t.getPosition();
				if (tpos) {
					top = tpos.y;
					left = tpos.x;
					tdim = { x:t.scrollWidth, y:t.scrollHeight };
				}
			}
		}
		if (tdim) {
			switch (io) {
				case 1:
					// outside 
					switch (align) {
						case 'nw': // above target, left aligned
							top -= (this.popsize.y + offset);
							break;
						case 'n': // above target, centered
							top -= (this.popsize.y + offset);
							left += (tdim.x/2 - this.popsize.x/2);
							break;
						case 'ne': // above target, right aligned
							top -= (this.popsize.y + offset);
							left += (tdim.x - this.popsize.x);
							break;
						case 'wn': // left of target, top aligned
							left -= (this.popsize.x + offset);
							break;
						case 'w': // left of target, middle aligned
							top += (tdim.y/2 - this.popsize.y/2);
							left -= (this.popsize.x + offset);
							break;
						case 'ws': // left of target, bottom aligned
							top += (tdim.y - this.popsize.y);
							left -= (this.popsize.x + offset);
							break;
						case 'en': // right of target, top aligned
							left += (tdim.x + offset);
							break;
						case 'e': // right of target, middle aligned
							top += (tdim.y/2 - this.popsize.y/2);
							left += (tdim.x + offset);
							break;
						case 'es': // right of target, bottom aligned
							top += (tdim.y - this.popsize.y);
							left += (tdim.x + offset);
							break;
						case 'sw': // below target, left aligned
							top += (tdim.y + offset);
							break;				
						case 's': // below target, middle aligned
							top += (tdim.y + offset);
							left += (tdim.x/2 - this.popsize.x/2);
							break;				
						case 'se': // below target, right aligned
							top += (tdim.y + offset);
							left += (tdim.x - this.popsize.x);
							break;				
					}
					break;
				case -1:
					// inside 
					switch (align) {
						case 'nw':
							top += offset;
							left += offset;
							break;
						case 'n':
							top += offset;
							left += (tdim.x/2 - this.popsize.x/2);
							break;
						case 'ne':
							top += offset;
							left += (tdim.x - this.popsize.x - offset);
							break;
						case 'w':
							top += (tdim.y/2 - this.popsize.y/2);
							left += offset;
							break;
						case 'c':
							top += (tdim.y/2 - this.popsize.y/2);
							left += (tdim.x/2 - this.popsize.x/2);
							break;
						case 'e':
							top += (tdim.y/2 - this.popsize.y/2);
							left += (tdim.x - this.popsize.x - offset);
							break;
						case 'sw':
							top += (tdim.y - this.popsize.y - offset);
							left += offset;
							break;				
						case 's':
							top += (tdim.y - this.popsize.y - offset);
							left += (tdim.x/2 - this.popsize.x/2);
							break;				
						case 'se':
							top += (tdim.y - this.popsize.y - offset);
							left += (tdim.x - this.popsize.x - offset);
							break;				
					}
					break;

			}
			if (arr_mode && this.options.useArrows) {
				var p = this.show_arrow(io, align);
				if (p) {
					top += p.top;
					left += p.left;
				}
			}
			return { 'top': top, 'left': left };
		}
		return false
	},
	destroy: function() {
		if (this.mask) {
			this.mask.remove();
		}
		this.pop.remove();
	}

});
AscDialog.implement(new Options, new Events);