/*
Mif.Menu
*/

if(!window.Mif) var Mif={};

Mif.Menu=new Class({

	Implements: [Events, Options],
	
	options: {
		skin: 'default'
	},

	initialize: function(options, skin){
		this.setOptions(options);
		this.target=this.options.target ? $(this.options.target) : document;
		this.showed=[];
		this.visible=[];
		this.hidden=true;
		if(!skin){
			switch(this.options.skin){
				case 'ART':
				case 'art': skin={
					container: ART.Container, 
					options: {
						className: 'mif-menu-art', 
						offsets:{x:-2, y:-3},
						theme: new ART.Theme({
							normal: {
								
								radius: 4,
								reflection: 0,

								overlayColor: '#fff',
								overlayOpacity: 0.9,
								borderOpacity: 0.2,
								shadow:8
								
							}
						})
					}
				}; break;
				case 'default': 
				default: skin={container: Mif.Menu.Container, options: {className: 'mif-menu-default', offsets:{x:-2, y:0}}};
			};
		};
		if(window.ART && Browser.Engine.trident && skin.container==ART.Container){
			skin.options.morph={duration:0};//because vml opacity with filter opacity=bug
		};
		this.List=Mif.Menu.List(skin);
		
		if(this.options.offsets){
			$extend(this.options.list, this.options.offsets);
		}
		this.list=new this.List(this.options.list, {menu: this});
		
		
		this.bound={
			escape: this.escape.bind(this),
			close: this.close.bind(this)
		};		
		this.addEvent('hide', function(){
			this.closing=false;
			this.hidden=true;
//			document.removeEvent('keyup', this.bound.escape);
//			document.removeEvent('mousedown', this.bound.close);
		}, true);
		this.addEvent('show', function(){
			this.hidden=false;
//			document.addEvent('keyup', this.bound.escape);
//			document.addEvent('mousedown', this.bound.close);
		}, true);
		
		this.initEvents();
	},
	
	close: function(event){
		if(this.$attaching) return;
		if(this.list.visible) this.hide();
	},
	
	initEvents: function(){
	/*	if(this.options.contextmenu){
			this.target.addEvent('contextmenu', function(event){
				this.show(event);
				return false;
			}.bind(this));
		};*/
	},
	
	show: function(obj){
		HideAllMenu(this);
		this.closing=false;
		this.list.show(obj);
		return this.fireEvent('show');
	},
	
	escape: function(event){
		if(event.key!='esc') return;
		var list=this.showed.getLast();
		if(list) list.hide();
	},
	
	hide: function(){
		this.closing=true;
		this.list.hide();
	},
	
	isVisible: function(){
		return !this.hidden;
	},
	
	attachTo: function(el){
		el=$(el);
		el.addEvents({


			'mouseover': function(event){
			//	HideAllMenu(this);
/*				if(!this.isVisible()){
					this.$attaching=true;
					var coords=el.getCoordinates();
					this.show({x: coords.left, y: coords.bottom});
					this.el=el;
				}*/
			}.bind(this),
			
			'mousedown': function(event){
				if(event.rightClick) return;
				if(!this.isVisible()){
					this.$attaching=true;
					var coords=el.getCoordinates();
					this.show({x: coords.left, y: coords.bottom});
					this.el=el;
				}else{
					this.hide();
				}
			}.bind(this),
			
			'mouseup': function(event){
				this.$attaching=false;
			}.bind(this)
			
		});
		return this;
	}
	
});

Mif.Menu.version='1.0';


/*
Mif.Menu.List
*/

Mif.Menu.List=function(skin){
	var skins=arguments.callee.skins;
	var lists=arguments.callee.lists;
	if(!skins) {
		skins=[]; 
		lists=[];
	};
	var index=skins.indexOf(skin);
	if(index!=-1) return lists[index];
	
	var List=new Class({

		Implements: [Events, Options],
		
		Extends: skin.container,
		
		options: $merge({
			styles: {
				'z-index': 1,
				position: 'absolute'
			}
		}, skin.options),

		initialize: function(options, structure){
			this.setOptions(options);
			this.parent($merge(this.options, {styles: {position: 'absolute'}}), 'mifmenu');
			this.list=new Element('ul', {'class': 'mif-menu-list'});
					
			this.openChildList=null;
			
			$extend(this, structure);
			$extend(this.options.offsets, this.menu.options.offsets);
			this.items=[];
			this.groups={};
			this.selected=null;
			
			this.initMenu();
			this.drawMenu();
			

			this.initEvents();
			this.container.setStyle('opacity',0);
			
		},
		
		initMenu: function(){
			this.options.items.each(function(options){
				var item=new Mif.Menu.Item(options, {list: this});
				this.list.adopt(item.container);
				if(!['separator', 'description'].contains(item.type)){
					this.items.push(item);
				}
			}, this);
		},
		
		drawMenu: function(){
			this.setContent(this.list).draw();
		},
		
		//private
		setWidth: function(){
			if(!Browser.Engine.trident) return;
			this.container.setStyle('width', 0);
			var width=this.list.offsetWidth;
			this.container.setStyle('width', width);
			this.list.setStyle('width',width);
			this.draw();
		},
		
		append: function(index, item){
			item.container.inject(this.items[index].container, 'after');
			this.items.inject(item, this.items[index], 'after');
		},
		
		initEvents: function(){
			this.container.addEvents({
				'click': this.action.bind(this),
				'mousedown': $lambda(false),
				'selectstart': $lambda(false),
				'mouseover': this.initSelect.bind(this),
				'mouseout': this.initSelect.bind(this)
			});
		},
		
		action: function(){
			var current=this.selected;
			if(!current||current.disabled||current.menu.closing) return false;
			this.menu.hide();
			current.fireEvent('action');
			return false;
		},
		
		hide: function(parents){
			if(this.hiding) return;
			this.hiding=true;
			this.unselect();
			this.menu.showed.erase(this);
			this.morpher.start({opacity: 0}).chain(function(){
				this.container.dispose();
				this.menu.visible.erase(this);
				this.hiding=false;
				if(!this.menu.visible.length) this.menu.fireEvent('hide');
			}.bind(this));
			this.hideChildren();
			if(!parents) return;
			this.hideParents();
		},
		
		hideParents: function(){
			if(this.parentItem) this.parentItem.list.hide(true);
		},
		
		hideChildren: function(){
			var open=this.openChildList;
			if(!open) return;
			open.hide();
			this.openChildList=null;
		},
		
		show: function(coords){
			if(this.menu.showed.contains(this) && !this.hiding) return;
			this.menu.showed.push(this);
			this.menu.visible.push(this);
			this.inject(document.body).draw();
			this.setWidth();
			this.hiding=false;
			this.visible=true;
			this.position(coords);
			this.morpher.start({opacity:1});
			this.showParents();
		},
		
		showParents: function(){
			if(!this.parentItem) return;
			this.parentItem.list.show();
		},
		
		initSelect: function(event){
			var target=event.target;
			if(!target||this.menu.closing) return this;
			if(target && Browser.Engine.trident){
				if(target.scopeName=='v') return this;
			}
			target=$(target);
			var item=target.getAncestorOrSelf('.mif-menu-item');
			
			if(!item){
				if(this.openChildList) return this;
				return this.unselect();
			};
			item=item.retrieve('item');
			if(!this.select(item)) return;
			if(!item.disabled && item.childList){
				item.timer=function(){
					item.childList.show();
					item.list.openChildList=item.childList;
					item.timer=null;
				}.delay(0);
			}
		},
		
		select: function(item){
			if(!item || item==this.selected || this.menu.closing) return false;
			this.unselect();
			item.select();
			this.show();
			this.selectParents(item);
			this.selected=item;
			this.menu.selected=item;
			return this;
		},
		
		selectParents: function(item){
			var parent=item.list.parentItem;
			if(!parent) return;
			parent.list.select(parent);
		},
		
		unselect: function(){
			var selected=this.selected;
			if(!selected) return;
			selected.unselect();
			if(selected.timer){
				$clear(selected.timer);
				selected.timer=null;
				return;
			}
			if(this.openChildList) this.openChildList.hide();
			this.openChildList=null;
			this.unselectChildren();
			this.selected=null;
			this.menu.selected=null;
		},
		
		unselectChildren: function(){
			var child=this.selected.childList;
			if(!child) return;
			child.unselect();
			child.hide();
		},
		
		position: function(coords){
			if(!coords){
			
				var parent=this.parentItem.container;
				position=parent.getPosition();
				
				var size = window.getSize(), scroll = window.getScroll();
				var menu = {x: this.wrapper.offsetWidth, y: this.container.offsetHeight};
				var item = {x: parent.offsetWidth, y: 0};
				var props = {x: 'left', y: 'top'};
				var coords={};
				
				for (var z in props){
					var pos=position[z]+item[z]+this.options.offsets[z];
					if ((pos + menu[z] - scroll[z]) > size[z]) pos = position[z]-menu[z]-this.options.offsets[z];
					coords[z]=Math.max(0, pos);
				}
				
			}else if(coords.event){
			
				var size = window.getSize(), scroll = window.getScroll(), event=coords;
				var menu = {x: this.container.offsetWidth, y: this.container.offsetHeight};
				var props = {x: 'left', y: 'top'};
				var coords={};
				for (var z in props){
					var pos = event.page[z] + this.options.offsets[z];
					if ((pos + menu[z] - scroll[z]) > size[z]) pos = event.page[z] - this.options.offsets[z] - menu[z];
					coords[z]=Math.max(0, pos);
				}
				
			}
						
			return this.setPosition(coords);
		}

	});
	
	skins.push(skin);
	lists.push(List);

	return  List;
}


/*
Mif.Menu.Item
*/

Mif.Menu.Item=new Class({

	Implements: [Events, Options],
	
	options: {
		type: 'default',
		checked: false,
		disabled: false,
		name: ''
	},

	initialize: function(options, structure){
		if(typeof options == 'string'){
			options={type: 'separator'};
		}
		this.setOptions(options);
		
		$extend(this, this.options);
		
		this.list=structure.list;
		this.menu=this.list.menu;
		
		this.draw();
		
		if(['description', 'separator'].contains(this.type)) return;
		
		if(this.disabled) {
			this.disabled=false;
			this.disable();
		}
		
		if(this.options.list) this.initChildList();
		
		if(this.type=='checkbox'){
			this.initCheckbox();
		}
		if(this.type=='radio'){
			this.initRadio();
		}
	},
	
	draw: function(){
		switch(this.type){
			case 'description': 
				this.container=new Element('li', {'class':'mif-menu-description mif-menu-name', html: this.options.name});
				break;
			case 'separator':
				this.container = new Element('li', {'class': 'mif-menu-separator mif-menu-name'});
				break;
			case 'default':
			case 'radio':
			case 'checkbox':
				this.dom={
					wrapper: new Element('div', {'class': 'mif-menu-item-wrapper'}),
					icon: new Element('span',{'class':'mif-menu-icon '+$pick(this.options.icon,''), html: Mif.Utils.zeroSpace}),
					name: new Element('span',{'class':'mif-menu-name', html: this.options.name})
				};
				this.container=new Element('li',{'class': 'mif-menu-item'}).adopt(
					this.dom.wrapper.adopt(this.dom.icon, this.dom.name)
				);
				this.container.store('item', this);
		}
	},
	
	setState: function(state){
		if(this.disabled!=state){
			this.container[(state ? 'add' : 'remove') + 'Class']('mif-menu-disabled');
			this.disabled=state;
		}
		return this;
	},
	
	disable: function(){
		return this.setState(true);
	},
	
	enable: function(){
		return this.setState(false);
	},
	
	initChildList: function(){
		this.container.addClass('mif-childList');
		var options=$merge(this.options.list, {styles: {'z-index': this.list.options.styles['z-index']+1}});
		this.childList=new this.menu.List(options, {parentItem: this, menu: this.menu});
	},
	
	select: function(){
		var cls=this.disabled ? 'mif-menu-selected-disabled' : 'mif-menu-selected';
		this.container.addClass(cls);
		return this.fireEvent('select');
	},
	
	unselect: function(){
		var cls=this.disabled ? 'mif-menu-selected-disabled' : 'mif-menu-selected';
		this.container.removeClass(cls);
		return this.fireEvent('unSelect');
	},
	
	check: function(state){
		if(this.type=='checkbox'){
			if($defined(state)){
				if(this.checked==state) return this;
				this.checked=state;
			}else{
				this.checked=!this.checked;
			}
			if(this.checked){
				this.dom.icon.removeClass('mif-menu-unchecked').addClass('mif-menu-checked');
			}else{
				this.dom.icon.removeClass('mif-menu-checked').addClass('mif-menu-unchecked');
			}
			this.list.fireEvent('check', [this, this.checked]);
		}
		if(this.type=='radio'){
			var checked=$defined(state) ? state : true;
			if(this.checked==checked) return this;
			this.checked=checked;
			this.list.groups[this.group].each(function(item){
				if(item==this && this.checked){
					item.checked=true;
					item.dom.icon.addClass('mif-menu-radio-checked').removeClass('mif-menu-radio-unchecked');
					item.list.fireEvent('radioCheck', [this, true]);
					return;
				}else{
					item.checked=false;
					item.dom.icon.addClass('mif-menu-radio-unchecked').removeClass('mif-menu-radio-checked');
					item.list.fireEvent('radioCheck', [this, false]);
				}
			}, this);
		}
		return this;
	},
	
	initCheckbox: function(){
		this.dom.icon.addClass('mif-menu-'+(this.checked ? 'checked' : 'unchecked'));
		this.addEvent('action',this.check.bind(this));
	},
	
	initRadio: function(){
		this.list.groups[this.group]=(this.list.groups[this.group]||[]).include(this);
		this.dom.icon.addClass('mif-menu-radio-' + (this.checked ? 'checked' : 'unchecked'));
		this.addEvent('action',this.check.bind(this));
	}
	
});


/*
Mif.Menu.Menu
*/

if(!window.Mif) var Mif={};
if(!Mif.Utils) Mif.Utils={};

Mif.Utils.zeroSpace=Browser.Engine.trident ? '&shy;' : (Browser.Engine.webkit ? '&#8203' : '');

Element.implement({

	getAncestorOrSelf: function(match){
		var parent=this;
		while(parent){
			if(parent.match(match)) return parent;
			parent=parent.getParent();
		}
		return false;
	},
	
	setContent: function(content){
		return (typeof content == 'string') ? this.set('html', content) : this.adopt(content);
	}
	
});

Array.implement({
	
	inject: function(added, current, where){//inject added after or before current;
		var pos=this.indexOf(current)+(where=='before' ? 0 : 1);
		for(var i=this.length-1;i>=pos;i--){
			this[i+1]=this[i];
		}
		this[pos]=added;
		return this;
	}
	
});

if(Browser.Engine.presto){

	Element.Events.extend({

		contextmenu: {
			base: 'click',
			condition: function(event){ return event.alt;}
		}
		
	});
	
}


/*
Mif.Menu.Container
*/


Mif.Menu.Container=new Class({

	Implements: Options,
	
	options:{
		morph: {link: 'cancel'},
		offsets:{//max 6
			t: -5,
			r: 5,
			b: 5,
			l: -5
		},
		opacity: 1,
		styles:{
			position: 'relative'
		}
	},

	initialize: function(options){
		this.setOptions(options);
		this.offsets=this.options.offsets;
		this.container = new Element('div').setStyles(options.styles);
		if (options.id) this.container.set('id', options.id);
		if (options.className) $splat(options.className).each(function(cn){
			this.container.addClass(cn);
		}, this);
		this.morpher = new Fx.Morph(this.container, this.options.morph);
		
		
		this.shadow=new Element('div', {'class': 'mif-shadow'});
		if(Browser.Engine.trident){
			this.shadow.addClass('mif-shadow-ie');
			this.shadow.style.filter="progid:DXImageTransform.Microsoft.alpha(opacity="+this.options.opacity*100+") progid:DXImageTransform.Microsoft.Blur(pixelradius=3)";
		}else{
			var sides=['tl','tr','br','bl','l','r','t','b','c'];
			var sideEls={};
			sides.each(function(side){
				el=new Element('div', {'class': 'mif-shadow-'+side}).setStyle('opacity', this.options.opacity);
				sideEls[side]=el;
				this.shadow.adopt(el);
			}, this);
			this.sideEls=sideEls;
		};
		this.center=new Element('div').setStyle('overflow', 'hidden');
		this.wrapper=new Element('div',{'class': 'mif-menu-wrapper', 'styles':{position: 'absolute', zIndex: 10}}).adopt(this.center);
		this.wrapper.style.filter="progid:DXImageTransform.Microsoft.alpha(opacity=100)";
		this.container.adopt(this.shadow, this.wrapper);
	},
	
	setStyle: function(style, value){
		this.container.setStyle(style, value);
		return this;
	},
	
	setStyles: function(styles){
		this.container.setStyles(styles);
		return this;
	},
	
	setContent: function(content){
		this.center.setContent(content);
		return this;
	},
	
	inject: function(element, how){
		this.container.inject(element, how);
		return this.draw();
	},
	
	draw: function(){
		this.shadow.setStyles({
			width:0,
			heigth:0
		});
		this.container.style.width='100%';
		var width=this.center.offsetWidth;
		var height=this.center.offsetHeight;
		var left=this.offsets.l;
		var top=this.offsets.t;
		var right=this.offsets.r;
		var bottom=this.offsets.b;
		this.shadow.setStyles({
			left: Math.max(-left, 0),
			top: Math.max(-top, 0)
		});
		var wrapperLeft=Math.max(left, 0);
		var wrapperTop=Math.max(top, 0);
		var wrapperRight=Math.max(right, 0);
		var wrapperBottom=Math.max(bottom, 0);
		this.offsetLeft=wrapperLeft;
		this.offsetTop=wrapperTop;
		this.wrapper.setStyles({
			left: wrapperLeft,
			top: wrapperTop
		});
		this.container.setStyles({
			width: width+wrapperLeft+wrapperRight,
			height: height+wrapperTop+wrapperBottom
		});
		var shadowWidth=width+left+right;
		var shadowHeight=height+top+bottom;
		if(Browser.Engine.trident){
			this.shadow.setStyles({
				width: Math.max(0, shadowWidth-6),
				height: Math.max(0, shadowHeight-6)
			});
		}else{
			this.sideEls.l.setStyle('height', shadowHeight-12);
			this.sideEls.r.setStyle('height', shadowHeight-12);
			this.sideEls.t.setStyle('width', shadowWidth-12);
			this.sideEls.b.setStyle('width', shadowWidth-12);
			this.sideEls.c.setStyles({
				width: shadowWidth-12,
				height: shadowHeight-12
			});
			this.shadow.setStyles({
				width: shadowWidth,
				height: shadowHeight
			});
		}
		return this;
	},
	
	setPosition: function(position){
		this.container.position({
			x: position.x-this.offsetLeft,
			y: position.y-this.offsetTop
		});
		return this;
	}

});


/*mootools-art*/

/* ART Element */

var ART = {};

Element.implement({
	
	setContent: function(content){
		return (typeof content == 'string') ? this.set('html', content) : this.adopt(content);
	},
	
	forceFocus: function(){
		this.blur();
		this.focus();
	},
	
	forceBlur: function(){
		this.focus();
		this.blur();
	}
	
});

ART.Element = new Class({
	
	Implements: [Events, Options],
	
	options: {
		/* onInject: $empty,
		onDispose: $empty,
		onGrab: $empty,*/
		subject: null,
		grabber: null
	},
	
	initialize: function(options){
		this.setOptions(options);
		this.subject = $(this.options.subject);
		this.grabber = (this.options.grabber) ? $(this.options.grabber) : this.subject;
	},
	
	inject: function(element, how){
		this.subject.inject(element, how);
		this.fireEvent('onInject', [element, this.subject]);
		return this;
	},
	
	grab: function(element, how){
		this.grabber.grab(element, how);
		this.fireEvent('onGrab', [element, this.grabber]);
		return this;
	},
	
	replaces: function(element){
		this.subject.replaces(element);
		return this;
	},
	
	adopt: function(){
		Array.flatten(arguments).each(function(element){
			this.grab(element);
		}, this);
		return this;
	},
	
	dispose: function(){
		this.fireEvent('onDispose', this.subject);
		this.subject.dispose();
		return this;
	},
	
	setStyle: function(style, value){
		this.subject.setStyle(style, value);
		return this;
	},
	
	setStyles: function(properties){
		this.subject.setStyles(properties);
		return this;
	},
	
	resize: function(size){
		this.subject.height = size.height;
		this.subject.width = size.width;
		return this;
	}

});

/* ART Ink */

ART.Ink = new Class({
	
	Extends: ART.Element,

	initialize: function(props){
		props = props || {};
		props.id = props.id || 'ART_Box_' + Native.UID++;
		var element = new Element('canvas', props);
		if (window.G_vmlCanvasManager) element = G_vmlCanvasManager.initElement(element);
		this.paint = element;
		this.canvas = this.paint.getContext('2d');
		this.parent({subject: this.paint});
		this.save();
	},
	
	save: function(){
		this.canvas.save();
		return this;
	},
	
	restore: function(){
		this.canvas.restore();
		return this;
	},

	begin: function(p){
		this.canvas.beginPath();
		this.canvas.moveTo(p.x, p.y);
		return this;
	},

	close: function(){
		this.canvas.closePath();
		return this;
	},

	translate: function(p){
		this.canvas.translate(p.x, p.y);
		return this;
	},

	line: function(p){
		this.canvas.lineTo(p.x, p.y);
		return this;
	},

	curve: function(p, c){
		this.canvas.quadraticCurveTo(c.x, c.y, p.x, p.y);
		return this;
	},

	box: function(options){
		options = $extend({radius: 5, height: 200, width: 200}, options);
		
		var radius = options.radius, height = options.height, width = options.width, fill = options.fill;

		var tl = options['top-left-radius'];
		var tr = options['top-right-radius'];
		var bl = options['bottom-left-radius'];
		var br = options['bottom-right-radius'];

		tl = $pick(tl, radius);
		tr = $pick(tr, radius);
		bl = $pick(bl, radius);
		br = $pick(br, radius);

		this.begin({x: 0, y: height - tl});
		this.line({x: 0, y: tl}).curve({x: tl, y: 0}, {x: 0, y: 0});
		this.line({x: width - tr, y: 0}).curve({x: width, y: tr}, {x: width, y: 0});
		this.line({x: width, y: height - br}).curve({x: width - br, y: height}, {x: width, y: height});
		this.line({x: bl, y: height}).curve({x: 0, y: height - bl}, {x: 0, y: height});

		this.close();
		
		return this.fill(fill, height);
	},
	
	arc: function(center, radius, start, end, fill){
		this.canvas.arc(center.x, center.y, radius, Math.radians(start), Math.radians(end), false);
		return this.fill(fill, radius * 2);
	},
	
	block: function(options){
		this.fill(options.fill, options.height);
		this.canvas.fillRect(0, 0, options.width, options.height);
		return this;
	},
	
	draw: function(instructions){
		for (var method in instructions) this[method].run(instructions[method], this);
		return this;
	},

	fill: function(color, height){
		if (typeof color != 'string'){
			var gradient = this.canvas.createLinearGradient(0, 0, 0, height);
			var len = color.length;
			color.each(function(color, i){
				gradient.addColorStop(i / (len - 1), color);
			});
			color = gradient;
		}
		this.canvas.fillStyle = color;
		this.canvas.fill();
		return this;
	}

});

Math.radians = function(degrees){
	return degrees * (Math.PI / 180);
};

/* ART Paint */

ART.Paint = new Class({
	
	Extends: ART.Ink,
	
	options: {
		id: false
	},
	
	initialize: function(options){
		this.setOptions(options);
		this.parent({id: this.options.id});
	},
	
	colorize: function(color, alpha){
		
		var rgba = function(rgb, a){
			rgb = rgb.hexToRgb(true);
			return 'rgba(' + rgb[0] + ',' + rgb[1] + ',' + rgb[2] + ',' + (a).round(5) + ')';
		};
		
		switch ($type(color)){
			case 'string': return rgba(color, alpha);
			case 'array': return color.map(function(c){
				return rgba(c, alpha);
			});
		}
		
		return '#000';
	},
	
	draw: function(style){
		
		if ($type(style) != 'art:style') style = ART.Style(style);
		
		this.resize({height: style.outerHeight, width: style.outerWidth});
		
		var tl = style.topLeftRadius, tr = style.topRightRadius, bl = style.bottomLeftRadius, br = style.bottomRightRadius;
		
		var shadow = style.shadow, border = style.border, radius = style.radius, height = style.height, width = style.width;
		
		var s2 = shadow * 1.5;
		
		var trs = tr + s2, tls = tl + s2, brs = br + s2, bls = bl + s2;
		
		//shadow
		
		if (style.drawShadow) (shadow).times(function(i){
			var alpha = Fx.Transitions.Quad.easeIn(i / shadow) / shadow * style.shadowOpacity;
			this.box({
				'width': style.outerWidth - i * 2,
				'height': style.outerHeight - i * 2,
				'top-left-radius': tls - i,
				'top-right-radius': trs - i,
				'bottom-left-radius': bls - i,
				'bottom-right-radius': brs - i,
				'fill': this.colorize(style.shadowColor, alpha)
			});
			this.translate({x: 1, y: 1});
		}, this);
		else this.translate({x: shadow, y: shadow});
		
		this.translate({x: (style.shadowOffsetX > 0) ? 0 : style.shadowOffsetX, y: (style.shadowOffsetY > 0) ? 0 : style.shadowOffsetY});
		
		//border
		
		if (style.border) this.box({
			'width': style.innerWidth ,
			'height': style.innerHeight,
			'top-left-radius': tl + border,
			'top-right-radius': tr + border,
			'bottom-left-radius': bl + border,
			'bottom-right-radius': br + border,
			'fill': this.colorize(style.borderColor, style.borderOpacity)
		}).translate({x: border, y: border});
		
		//main overlay
		
		if (style.overlay){
			
			if (!style.title && style.reflection){
				this.box({
					'width': width,
					'height': height,
					'top-left-radius': tl,
					'top-right-radius': tr,
					'bottom-left-radius': bl,
					'bottom-right-radius': br,
					'fill': this.colorize(style.reflectionColors[0], style.overlayOpacity)
				}).translate({x: 0, y: style.reflection});
			}
			
			var mh = (!style.title) ? style.reflection : 0;

			this.translate({x: 0, y: style.title}).box({
				'width': width,
				'height': height - mh,
				'bottom-left-radius': style.status ? 0 : bl,
				'bottom-right-radius': style.status ? 0 : br,
				'top-left-radius': style.title ? 0 : tl,
				'top-right-radius': style.title ? 0 : tr,
				'fill': this.colorize(style.overlayColor, style.overlayOpacity)
			}).translate({x: 0, y: -style.title});

		}
		
		if (style.title){
			
			if (style.reflection) this.box({
				'width': width,
				'height': style.title,
				'top-left-radius': tl,
				'top-right-radius': tr,
				'bottom-left-radius': 0,
				'bottom-right-radius': 0,
				'fill': this.colorize(style.reflectionColors[0], style.titleOpacity)
			}).translate({x: 0, y: style.reflection});
					
			this.box({
				'width': width,
				'height': style.title - style.reflection,
				'top-left-radius': tl,
				'top-right-radius': tr,
				'bottom-left-radius': 0,
				'bottom-right-radius': 0,
				'fill': this.colorize(style.titleColor, style.titleOpacity)
			}).translate({x: 0, y: -style.reflection});
			
			if (style.line) this.translate({x: 0, y: style.title - style.line}).box({
				'width': width,
				'height': style.line,
				'radius': 0,
				'fill': this.colorize(style.lineColors[0], style.titleOpacity)
			}).translate({x: 0, y: - style.title + style.line});
			
		}
		
		if (style.status){
		
			this.translate({x: 0, y: height + style.title}).box({
				'width': width,
				'height': style.status,
				'bottom-left-radius': bl,
				'bottom-right-radius': br,
				'top-left-radius': 0,
				'top-right-radius': 0,
				'fill': this.colorize(style.statusColor, style.statusOpacity)
			});
			
			if (style.line){
				
				this.box({
					'width': width, 'height': style.line, 'radius': 0, 'fill': this.colorize(style.lineColors[1], style.statusOpacity)
				});
				
				if (style.reflection) this.translate({x: 0, y: style.line}).box({
					'width': width, 'height': style.reflection, 'radius': 0, 'fill': this.colorize(style.reflectionColors[1], style.statusOpacity)
				});
				
			}
		}
		
		return this;
	}
	
});


/* ART Theme */

ART.Style = function(properties){
	
	var style = $merge(ART.Styles, {$family: {name: 'art:style'}}, properties);
	
	if (!style.shadow){
		style.shadowOffsetY = 0;
		style.shadowOffsetX = 0;
	}

	style.innerHeight = style.height + style.status + style.title + (style.border * 2);
	style.innerWidth = style.width + (style.border * 2);

	style.outerHeight = (style.shadow * 2) - Math.abs(style.shadowOffsetY) + style.innerHeight;
	style.outerWidth = (style.shadow * 2) - Math.abs(style.shadowOffsetX) + style.innerWidth;

	var tl = style.topLeftRadius, tr = style.topRightRadius, bl = style.bottomLeftRadius, br = style.bottomRightRadius;

	style.topLeftRadius = $pick(tl, style.radius);
	style.topRightRadius = $pick(tr, style.radius);
	style.bottomLeftRadius = $pick(bl, style.radius);
	style.bottomRightRadius = $pick(br, style.radius);

	return style;
	
};

ART.Styles = {
	
	radius: 0,

	title: 0,
	titleColor: '#CCC',
	titleOpacity: 1,

	status: 0,
	statusColor: '#CCC',
	statusOpacity: 1,

	overlay: true,
	overlayColor: '#FFF',
	overlayOpacity: 1,

	shadow: 10,
	shadowOffsetX: 0,
	shadowOffsetY: -2,
	shadowColor: '#000',
	shadowOpacity: 0.5,
	drawShadow: true,

	border: 1,
	borderColor: '#000',
	borderOpacity: 0.4,

	reflection: 1,
	reflectionColors: ['#FFF', '#FFF'],

	line: 1,
	lineColors: ['#AAA', '#AAA']
	
};

ART.Theme = function(properties){
	
	properties = $unlink(properties);
	
	this.normal = properties.normal;
	
	delete properties.normal;
	
	for (var p in properties) this[p] = $merge(this.normal, properties[p]);
	
};

ART.Themes = new Hash;

/* ART Container */

ART.Container = new Class({
	
	Extends: ART.Element,
	
	options: {
		id: null,
		className: null,
		
		title: null,
		content: null,
		status: null,
		
		styles: {
			height: 'auto',
			width: 'auto',
			position: 'relative',
			overflow: 'hidden'
		},
		
		theme: null,
		morph: {link: 'cancel'}
	},
	
	initialize: function(options, component){
		this.component = (component) ? ' art-' + component : '';
		this.setOptions(options);
		options = this.options;
		this.theme=options.theme.normal;//hack
		var absZero = {position: 'absolute', top: 0, left: 0};
		
		this.container = new Element('div', {'class': 'art-container' + this.component}).setStyles({
			position: options.styles.position, top: 0, left: 0
		});
		
		if (!this.component) this.component = 'art-container';
		
		if (options.id) this.container.set('id', options.id);
		if (options.className) $splat(options.className).each(function(cn){
			this.container.addClass(cn);
		}, this);
		
		this.paint = new ART.Paint().setStyles(absZero).inject(this.container);
		
		this.wrapper = new Element('div').setStyles(absZero).inject(this.container);

		this.top = {offsetHeight: 0};
		this.bottom = {offsetHeight: 0};
		this.center = new Element('div').inject(this.wrapper);
		
		this.center.setStyles({width: options.styles.width, height: options.styles.height, overflow: options.styles.overflow});
		
		if (options.title) this.setTitle(options.title);
		if (options.content) this.setContent(options.content);
		if (options.status) this.setStatus(options.status);
		
		this.morpher = new Fx.Morph(this.container, this.options.morph);
		
		this.parent({
			subject: this.container,
			onInject: this.onInject
		});
		
	},
	
	wraps: function(element){
		element = $(element);
		if (!element) return this;
		this.container.replaces(element);
		this.setContent(element);
		this.draw();
		return this;
	},
	
	replaces: function(element){
		this.parent(element);
		return this.draw();
	},
	
	setTitle: function(content){
		if ($type(this.top) != 'element') this.top = new Element('div').inject(this.wrapper, 'top');
		this.process('title', content, this.top);
		return this;
	},
	
	setContent: function(content){
		this.process('content', content, this.center);
		this.grabber = this.content;
		return this;
	},
	
	setStatus: function(content){
		if ($type(this.bottom) != 'element') this.bottom = new Element('div').inject(this.wrapper, 'bottom');
		this.process('status', content, this.bottom);
		return this;
	},
	
	onInject: function(){
		this.draw();
	},

	process: function(name, part, container){
		var where = this[name];
		if (where) where.dispose();
		if (!part) return;
		where = new Element('div', {'class': this.component + '-' + name}).inject(container);
		where.setContent(part);
		this[name] = where;
	},
	
	draw: function(theme){
		
		theme = $unlink(theme || {});
		
		this.container.setStyles({width: '100%'});
		
		var height = theme.height, width = theme.width;
		
		if ($chk(height)) this.center.setStyles({height: height});
		if ($chk(width)) this.center.setStyles({width: width});
		theme = $merge(this.theme, theme, {
			title: this.top.offsetHeight,
			status: this.bottom.offsetHeight,
			height: this.center.offsetHeight,
			width: this.center.offsetWidth
		});
		
		theme = ART.Style(theme);
		
		this.container.setStyles({height: theme.outerHeight, width: theme.outerWidth});
		var shadow = theme.shadow, border = theme.border;
		
		this.offsets = {
			x: shadow + ((theme.shadowOffsetX > 0) ? 0 : theme.shadowOffsetX),
			y: shadow + ((theme.shadowOffsetY > 0) ? 0 : theme.shadowOffsetY)
		};
		
		this.wrapper.setStyles({left: this.offsets.x + border, top: this.offsets.y + border});
		
		this.paint.draw(theme);
		return this;
	},
	
	setPosition: function(position){
		this.container.position({x: position.x - this.offsets.x, y: position.y - this.offsets.y});
		return this;
	}
	
});

/*
Mif.Menu.CanvasContainer

Based on mootools-art http://code.google.come/p/mootools-art and Canvas Underlayer http://fantactuka.net/canvasul/
*/


Mif.Menu.CanvasContainer=new Class({

	Implements: Options,
	
	options:{
		morph: {link: 'cancel'},
		opacity: 1,
		styles:{
			position: 'relative'
		},
		
		x: 0,
		y: 0,
		glow: 0,
		shadow: 5,
		border: 0,
		width: 100,
		height: 100,
		corners: [4, 4, 4, 4],
		borderStartColor: '#a7a7a7',
		borderStartOpacity: 0.5,
		borderStopColor: '#a7a7a7',
		borderStopOpacity: 0.5,
		bodyStartColor: '#edebeb',
		bodyStartOpacity: 1,
		bodyStopColor: '#aea6a4',
		bodyStopOpacity: 1,
		glowColor: '#000',
		glowOpacity: 1,
		shadowColor: '#000',
		shadowOpacity: 0.3,
		gradientMode: 'vertical'
	},

	initialize: function(options){
		this.setOptions(options);
		
		this.container = new Element('div').setStyles(options.styles);
		if (options.id) this.container.set('id', options.id);
		if (options.className) $splat(options.className).each(function(cn){
			this.container.addClass(cn);
		}, this);
		this.morpher = new Fx.Morph(this.container, this.options.morph);
		
		
		this.canvas = new Canvas({
			'class': 'mif-menu-canvas',
			styles: {
				position: 'absolute',
				'z-index': 0
			}
		});
		
		this.container.adopt(this.canvas);
		
		this.center=new Element('div').setStyle('overflow', 'hidden');
		this.wrapper=new Element('div',{'class': 'mif-menu-wrapper', 'styles':{position: 'absolute', zIndex: 10}}).adopt(this.center);
		//this.wrapper.style.filter="progid:DXImageTransform.Microsoft.alpha(opacity=100)";
		this.container.adopt(this.shadow, this.wrapper);
	},
	
	setStyle: function(style, value){
		this.container.setStyle(style, value);
		return this;
	},
	
	setStyles: function(styles){
		this.container.setStyles(styles);
		return this;
	},
	
	setContent: function(content){
		this.center.setContent(content);
		return this;
	},
	
	inject: function(element, how){
		this.container.inject(element, how);
		return this.draw();
	},
	
	draw: function(){
		
		this.container.style.width='100%';
		var width=this.center.offsetWidth;
		var height=this.center.offsetHeight;
		
		this.offsets={
			x: this.options.glow+this.options.border,
			y: this.options.glow+this.options.border
		}
				
		var size={
			width: width+this.options.glow + Math.max(this.options.glow, this.options.shadow)+this.options.border,
			height: height+this.options.glow + Math.max(this.options.glow, this.options.shadow)+this.options.border
		}
		
		this.canvas.width=size.width;
		this.canvas.height=size.height;
		
		this.container.setStyles({
			width: size.width,
			height: size.height
		});
		
		this.wrapper.setStyles({
			left: this.offsets.x,
			top: this.offsets.y
		});

		/* Glow drawing. */
		if(this.options.glow > 0) {
			for(var i = 0; i < this.options.glow; i ++) {
				
				opacity = Fx.Transitions.Quad.easeIn(i / this.options.glow) / this.options.glow * this.options.glowOpacity;
				
				this.drawRectangle({
					x: i,
					y: i,
					width: size.width -i*2,
					height: size.height -i*2,
					gradientStartColor: this.options.glowColor,
					gradientStartOpacity: opacity,
					gradientStopColor: this.options.glowColor,
					gradientStopOpacity: opacity
				});
			}
		}
		
		/* Shadow drawing. */
		if(this.options.shadow > 0) {
			for(var i = 0; i < this.options.shadow; i ++) {
				opacity = this.options.shadowOpacity * (1 - i / this.options.shadow);
				this.drawRectangle({
					x: this.options.glow + i,
					y: this.options.glow + i,
					width: width,
					height: height,
					gradientStartColor: this.options.shadowColor,
					gradientStartOpacity: opacity,
					gradientStopColor: this.options.shadowColor,
					gradientStopOpacity: opacity
				});
			}
		}		
		
		/* Border drawing. */
		if(this.options.border > 0) {
			this.drawRectangle({
				x: this.options.glow,
				y: this.options.glow,
				width: width+2*this.options.border,
				height: height+2*this.options.border,
				gradientStartColor: this.options.borderStartColor,
				gradientStartOpacity: this.options.borderStartOpacity,
				gradientStopColor: this.options.borderStopColor,
				gradientStopOpacity: this.options.borderStopOpacity
			});
		}
		
		/* Body drawing. */
		this.drawRectangle({
			x: this.options.glow + this.options.border,
			y: this.options.glow + this.options.border,
			width: width,
			height: height,
			gradientStartColor: this.options.bodyStartColor,
			gradientStartOpacity: this.options.bodyStartOpacity,
			gradientStopColor: this.options.bodyStopColor,
			gradientStopOpacity: this.options.bodyStopOpacity
		});

		return this;
	},
	
	drawRectangle: function(options) {
		var o = $merge(this.options, options);
		var c = this.canvas.getContext('2d');
		
		c.translate(o.x, o.y);
		
		
		c.beginPath();
		
		
		c.moveTo(o.corners[0], 0);
		
		c.lineTo(o.width - o.corners[1], 0);
		
		c.quadraticCurveTo(o.width, 0, o.width, o.corners[1]);
		
		c.lineTo( o.width, o.height - o.corners[2]);
		
		c.quadraticCurveTo( o.width, o.height, o.width - o.corners[2], o.height);
		
		c.lineTo( o.corners[3], o.height);
		
		c.quadraticCurveTo(0, o.height, 0, o.height - o.corners[3]);
		
		c.lineTo(0, o.corners[0]);
		
		c.quadraticCurveTo(0, 0, o.corners[0], 0);
		
		c.closePath();
		
		if(o.gradientMode == 'vertical') { 
			this.fillStyle = c.createLinearGradient(0, 0, 0, o.height); 
		} else { 
			this.fillStyle = c.createLinearGradient(0, 0, o.width, 0); 
		}
		this.fillStyle.addColorStop(0, this.colorize(o.gradientStartColor, o.gradientStartOpacity));
		this.fillStyle.addColorStop(1, this.colorize(o.gradientStopColor, o.gradientStopOpacity));
		c.fillStyle = this.fillStyle;
		c.fill();
		
		c.translate(-o.x, -o.y);
		
		
	},
	
	colorize: function(color, alpha){
		
		var rgba = function(rgb, a){
			rgb = rgb.hexToRgb(true);
			return 'rgba(' + rgb[0] + ',' + rgb[1] + ',' + rgb[2] + ',' + (a).round(5) + ')';
		};
		
		switch ($type(color)){
			case 'string': return rgba(color, alpha);
			case 'array': return color.map(function(c){
				return rgba(c, alpha);
			});
		}
		
		return '#000';
	},
	
	setPosition: function(position){
		this.container.position({
			x: position.x - this.offsets.x,
			y: position.y - this.offsets.y
		});
		return this;
	}

});


/*
Mif.Menu.KeyNav
*/

Mif.Menu.KeyNav=new Class({
	
	initialize: function(menu){
		this.menu=menu;
		this.bound={
			attach: this.attach.bind(this),
			detach: this.detach.bind(this),
			keyaction: this.keyaction.bind(this)
		};
		this.keyevent=Browser.Engine.presto ? 'keypress' : 'keydown';
		menu.addEvent('show', this.bound.attach);
		menu.addEvent('hide', this.bound.detach);
	},
	
	attach: function(){
		document.addEvent(this.keyevent, this.bound.keyaction);
	},
	
	detach: function(){
		document.removeEvent(this.keyevent, this.bound.keyaction);
	},
	
	keyaction: function(event){
		if(!['down','left','right','up','enter'].contains(event.key)) return;
			var list=this.menu.showed.getLast();
			if(!list.selected){
				if(event.key=='down'){
					list.select(list.items[0]);
				};
				if(event.key=='up'){
					list.select(list.items[list.items.length-1]);
				};
			}else{
				var current=list.selected;
				switch (event.key){
					case 'down': this.goForward(current);break;  
					case 'up': this.goBack(current);break;   
					case 'left': this.goLeft(current);break;
					case 'right': this.goRight(current);break;
					case 'enter': this.action(current);
				}
				return false;
			}
	},

	goForward: function(current){
		
		var list=current.list;
		var items=list.items;
		var pos=items.indexOf(current)+1;
		if(pos>items.length-1) pos=0;
		list.select(items[pos]);
	},
	
	goBack: function(current){
		var list=current.list;
		var items=list.items;
		var pos=items.indexOf(current)-1;
		if(pos<0) pos=items.length-1;
		list.select(items[pos]);
	},
	
	goLeft: function(current){
		if(current.list.parentItem){
			current.list.hide();
		};
	},
	
	goRight: function(current){
		var child=current.childList;
		if(child){
			child.show();
			child.select(child.items[0]);
		};
	},
	
	action: function(current){
		current.list.action();
	}
});


