

var NavSlide = Class.create({
	
	frame: null,
	container: null,
	nodes: null,
	duration : 0.7,
	durationOut : 0.35,
	delayPerLi : 0.1,
	delayPerLiOut : 0.025,
	liId: 'user_jostarkeywordnavigation_pi1_li_',
	ulId: 'user_jostarkeywordnavigation_pi1_ul_',
	rootName: null,
	
	initialize : function(containerId, nodes, rootName) {
		this.rootName = rootName;
		this.frame = $(containerId);
		this.containerId = containerId;
		this.container = $$('#' + containerId + ' .clearfix').first();
		// set nodes
		this.nodes = nodes;
		// observe actual lists
		this.getElems().each(function(ul) {
			this.observeUl(ul);
		}.bind(this));
		// observe back button
		this.backButton = $$('#' + containerId + ' .back', '#' + containerId + ' .back_active').first();
		Event.observe(this.backButton, 'click', this.back.bindAsEventListener(this));
		// get active
		this.active = $$('#' + containerId + ' .clearfix .active');
		if(this.active) this.active = this.active.first();
	},
	
	getElems: function() {
		return $$('#' + this.containerId + ' .clearfix ul');
	},
	
	observeUl: function(ul) {
		$A(ul.getElementsByTagName('a')).each(function(a) {
			if (this.getPidFromLink(a)) {
				Event.observe(a, 'click', this.click.bindAsEventListener(this, a));
			}
		}.bind(this));
	},
	
	getPidFromLink: function(a) {
		// normal urls
		var pid = a.href.match(/\[pid\]=([0-9]+)/);

		if (pid != null) {
			return 'n' + pid.last();
		}
		// cool uri urls
		var pid = a.href.match(/navigator-([0-9]+)/);
		if (pid != null) {
			return 'n' + pid.last();
		}

		return false;
//		return pid == null ? false : pid.last();
	},
	
	create : function(pid) {
		var ul = Builder.node('ul');
		ul.id = this.ulId + pid;
		this.nodes.get(pid).each(function(n){
			var a = Builder.node('a', { href: n.value.href, target: n.value.target }, n.value.keyword);
			if(this.getPidFromLink(a)) a.addClassName('more');
			var li = Builder.node('li', [a]);
			li.id = this.liId + n.value.id;
			ul.appendChild(li);
			
		}.bind(this) );
		this.observeUl(ul);
		return ul;
	},
	
	click: function(e, a) {
		Event.stop(e);
		if (Effect.Queues.get('user_jostarkeywordnavigation_pi1').size() != 0) return;
		
		var uls = this.getElems();
		
		var newUl = this.create(this.getPidFromLink(a));
		Element.setStyle(newUl, { marginTop: Element.cumulativeOffset(a).top - Element.cumulativeOffset(a.parentNode.parentNode.parentNode).top - 1 + 'px' } );
		
		var id = $A(a.parentNode.id.split('_')).last()
		
		if(this.removeSpacer(newUl, a)) return;
		
		if(uls.size() == 1) {
			this.getIn(newUl, a);
		} else {
			if(a.parentNode.parentNode == uls.first()) {
				this.getOut(uls.last(), newUl, a);
			} else {
				this.scrollTo(a.parentNode.parentNode, newUl);
				this.setActive(id);
				this.setRootline(id);
			}
		}
	},
	
	removeSpacer: function(newUl, a) {
		var spacer = $('user_jostarkeywordnavigation_pi1_spacer');
		if(!spacer) return false;
		new Effect.Fade(spacer, {
			queue: {position: 'end', scope: 'user_jostarkeywordnavigation_pi1'},
			duration: 0.3,
			afterFinish : function() {
				spacer.parentNode.removeChild(spacer);
				this.getIn(newUl, a);
			}.bind(this)
			} );
		return true;
	},
	
	getIn: function(elem, a) {
		Element.setStyle(elem, { visibility: 'hidden' });
		a.parentNode.parentNode.parentNode.appendChild(elem);
		var id = $A(a.parentNode.id.split('_')).last();
		var anc = this.getPrevious(elem);
		var oldHeight = Element.getHeight(elem);
		//var slideHeight = Element.getHeight(anc) - parseInt(Element.getStyle(elem, 'marginTop'));
		slideHeight = Element.getHeight(a.parentNode.parentNode) - Element.cumulativeOffset(a.parentNode).top + Element.cumulativeOffset(a.parentNode.parentNode).top;
		if (slideHeight > oldHeight) slideHeight = oldHeight;
		
		new Effect.Move(elem, {
			x: this.frame.offsetWidth/2,
			mode: 'relative',
			transition: Effect.Transitions.sinoidal,
			duration: this.duration,
			queue: {position: 'end', scope: 'user_jostarkeywordnavigation_pi1'},
			beforeSetup : function() {
				this.setRootline(id);
				Element.setStyle(anc, { zIndex: 10 } );
				Element.setStyle(elem, {
					height: slideHeight + 'px',
					overflow: 'hidden',
					zIndex: 1,
					left: -this.frame.offsetWidth/2 + 'px'
					});
				Element.setStyle(elem, { visibility: 'visible' });
				this.setActive(id);
				}.bind(this),
			afterFinish: function() {
				Element.setStyle(anc, { zIndex: 1 } );
				Element.setStyle(elem, { zIndex: 1 } );
				if(slideHeight == oldHeight) return;
				new Effect.Morph(elem, {
					style : "height:" + (oldHeight) + "px;",
					queue: {position: 'end', scope: 'user_jostarkeywordnavigation_pi1'},
					duration : this.delayPerLi * (Element.childElements(elem).size() - Element.childElements(a.parentNode.parentNode).size() + Element.childElements(a.parentNode.parentNode).indexOf(a.parentNode)),
					afterFinish: function() {
						Element.setStyle(elem, { overflow: 'visible' } );
					}.bind(this)
				});
				}.bind(this)
		});
	},
	
	getOut: function(elem, newUl, a) {
		var anc = this.getPrevious(elem);
		// change to slide height
		//var slideHeight = Element.getHeight(anc) - parseInt(Element.getStyle(elem, 'marginTop'));
		var slideHeight = Element.getHeight(anc) - Element.cumulativeOffset(elem).top + Element.cumulativeOffset(anc).top;
		if(slideHeight < Element.getHeight(elem)) {
			Element.setStyle(elem, { overflow: 'hidden' } );
			new Effect.Morph(elem, {
				style : "height:" + (slideHeight) + "px;",
				queue: {position: 'end', scope: 'user_jostarkeywordnavigation_pi1'},
				duration : this.delayPerLiOut * Element.childElements(elem).size()
				});
		}
		// move
		new Effect.Move(elem, {
			x: Element.cumulativeOffset(anc).left - Element.cumulativeOffset(elem).left,
			mode: 'relative',
			transition: Effect.Transitions.sinoidal,
			duration: this.durationOut,
			queue: {position: 'end', scope: 'user_jostarkeywordnavigation_pi1'},
			beforeSetup: function() {
				Element.setStyle(anc, { zIndex: 10 } );
			}.bind(this),
			afterFinish: function() {
				Element.setStyle(anc, { zIndex: 1 } );
				elem.parentNode.removeChild(elem);
				this.getIn(newUl, a);
			}.bind(this)
		});
	},
	
	getPrevious: function(elem) {
		var ce = Element.childElements(elem.parentNode);
		return ce[ce.indexOf(elem)-1];
	},
	
	scrollTo: function(elem, newUl) {
		new Effect.Move(this.container, {
			x: Element.cumulativeOffset(elem.parentNode.parentNode).left - Element.cumulativeOffset(elem).left,
			y: 0,
			mode: 'relative',
			transition: Effect.Transitions.sinoidal,
			duration: this.duration,
			queue: {position: 'end', scope: 'user_jostarkeywordnavigation_pi1'},
			beforeSetup: function() {
				if(newUl) {
					Element.setStyle(newUl, { visibility: 'hidden' });
					elem.parentNode.appendChild(newUl);
				}
				Element.setStyle(elem.parentNode, { width: this.getWidth(elem.parentNode) + 'px' });
				Element.setStyle(newUl, { visibility: 'visible' });
			}.bind(this),
			afterFinish: function() {
				while(elem.parentNode.childNodes[0] != elem) {
					elem.parentNode.removeChild(elem.parentNode.childNodes[0]);
				}
				Element.setStyle(elem.parentNode, { left: 0 + 'px', width: this.getWidth(elem.parentNode) + 'px' });
				this.setBackButton();
			}.bind(this)
		} );
	},
	
	getWidth: function(con) {
		var width = 0;
		Element.childElements(con).each(function(e) { width += this.getWidthElem(e); }.bind(this));
		return width;
	},
	
	getWidthElem: function(e) {
		return parseInt(Element.getStyle(e, 'width')) + parseInt(Element.getStyle(e, 'marginRight')) + parseInt(Element.getStyle(e, 'marginLeft'));
	},
	
	getHeightElem: function(e) {
		return parseInt(Element.getStyle(e, 'height')) + parseInt(Element.getStyle(e, 'marginTop')) + parseInt(Element.getStyle(e, 'marginBottom'));
	},
	
	back: function(e) {
		Event.stop(e);
		var id = $A(this.getElems().first().id.split('_')).last();
		var node = this.getNodeById(id);
		if(!node) return;
		
		var first = this.getElems().first();
		var con = first.parentNode;
		var newUl = this.create(node.key);
		new Effect.Move(con, {
			x: this.getWidthElem(first),
			y: 0,
			mode: 'relative',
			transition: Effect.Transitions.sinoidal,
			duration: this.duration,
			queue: {position: 'end', scope: 'user_jostarkeywordnavigation_pi1'},
			beforeSetup: function() {
				this.setRootline(id);
				Element.insert(first, { 'before': newUl });
				Element.setStyle(con, { width: this.getWidth(con) + 'px', 'left': -this.getWidthElem(first) + 'px' } );
				this.setActive(id);
			}.bind(this),
			afterFinish: function() {
				while(con.childElements().size() > 2) {
					con.removeChild(con.childElements().last());
				}
				Element.setStyle(con, { width: this.getWidth(con) + 'px' });
				this.setBackButton();
			}.bind(this)
		});
	},
	
	getNodeById: function(id) {
		//id = 'n' + id;
		node = false;
		this.nodes.each(function(pair) {
			if(pair.value.get(id)) node = pair;
		} );
		return node;
	},
	
	setActive: function(id) {
		var a = $(this.liId + id);
		if(!a) return;
		if(this.active) this.active.removeClassName('active');
		this.active = a;
		this.active.addClassName('active');
	},
	
	setBackButton: function() {
		var id = $A(this.getElems().first().id.split('_')).last();
		var node = this.getNodeById(id);
		this.backButton.href = node ? node.value.get(id).href : '#';
		Element.removeClassName(this.backButton, node ? 'back' : 'back_active');
		Element.addClassName(this.backButton, node ? 'back_active' : 'back');
	},
	
	setRootline: function(id) {
		var node = this.getNodeById(id);
		var rootline = '';
		var gpid = node.value.get(id).gpid;
		var pid = node.value.get(id).pid;

		while (node) {
			rootline =  ' \\ ' + node.value.get(id).keyword + rootline;
			node = this.getNodeById(pid)
			if (node) {
				id = pid;
				pid = gpid;
				gpid = node.gpid;
			}
		}
		
		$('slideRootline').firstChild.data = this.rootName + rootline;
	}
});