var ban_data = new Array();

_function={
	'apply':function(as,arg){
		if(!this.arguments && !arg){
			return this.own.call(as?as:this.as);
		}
		if(this.arguments && arg){
			for(var i in arg){
				this.arguments.push(arg[i]);
			}
			return this.own.apply(as?as:this.as,this.arguments);
		}
		return this.own.apply(as?as:this.as,arg?arg:this.arguments);
	},
	'arguments':false,
	'as':false,
	'call':function(as){
		return this.own.call(as?as:this.as);
	},
	'init':function(f,as,args){
		this.own=f;
		this.as=as;
		this.arguments=args;
	},
	'own':false
}
_event={
	'add':function(f){
		this.queue[this.queue.length]=f;
	},
	'init':function(n){
		if(n){
			this.name=n;
		}
	},
	'name':false,
	'queue':[],
	'run':function(as,arg){
		$.each(this.queue,function(q,f){
			f.apply(as,arg);
		});
	}
}

var $utils=(function($){
	if(!$){return;}
	return{
		'attributes':function(o,eh){
			if(typeof(o)=='object'){
//alert('NamedNodeMap: '+this.is(o,'NamedNodeMap')+'\nObject Class: '+this.getClass(o));
				if(this.is(o,'NamedNodeMap')){// NOT IE Compatible
					var map={},ehre=/^on/i;
					for(var i=0;i<o.length;i++){
						if(eh || !eh && !ehre.test(o[i].nodeName)){
							map[o[i].nodeName]=this.typecast(o[i].nodeValue);
						}
					}
					return map;
				}
//alert('Is Object Not NamedNodeMap\n'+o);
//alert(o+'\nnodeType:'+o.nodeType+'\no.toString: '+o.toString()+'\nObject toString: '+Object.prototype.toString.call(o));
//alert('test\n'+(o==Object.prototype.toString.call(o))+'\no.match'+String(o).match(/^\[object\s(.*)\]$/));

				// convert to a DOM Node object and rerun as the attributes
				return this.attributes((o.nodeType===1?o:o[0]).attributes,eh);
			}
			return this.attributes($(o)[0].attributes,eh);
		},
		'getClass':function(o){
			var s=Object.prototype.toString.call(o).match(/^\[object\s(.*)\]$/);
//			if(s[1]=='Object' && o.nodeType===1){
//				return String(o).match(/^\[object\s(.*)\]$/)[1];
//			}
			return s[1];
		},
		'init':function(object,data,fn){
			var instance=$.extend(true,{},object);
			if(!fn){fn='init'}
			if(data && instance[fn]){
				instance[fn].apply(instance,data);
			}
			return instance;
		},
		'is':function(o,c){
			if(this.getClass(c)=='Array'){
				return $.inArray(this.getClass(o),c)>=0;
			}
			return this.getClass(o)==c;
		},
		'log':function(){
			if(window.console&&window.console.log&&window.console.log.apply){
				window.console.log.apply(this,arguments);
			}
		},
		'typecast':function(o){
			if((/(\d*)\.{0,1}(\d+)/).test(o)){
				return isNaN(o)?o:Number(o);
			}else if((/true|false/i).test(o)){
				return o=='true';
			}else if(o=='null' || o=='undefined'){
				return o=='null'?null:undefined;
			}
			return o;
		}
	}
})(typeof(jQuery)!=='undefined'?jQuery:null);

var $CycleRotation=(function($){
	if(!$){return;}

	var $ActiveCallbacks={
			'after':null,
			'before':null,
			'end':null,
			'onPagerEvent':null,
			'onPrevNextEvent':null,
			'pagerAnchorBuilder':null,
			'timeoutFn':null,
			'updateActivePagerLink':null
		},
		$AutorunResult=false,
		$Configuration={
			'autorun':true,
			'autostart':true,
			'datakey':'cyclerotation',
			'global':false,
			'slideCallbacks':['after','before','end','onPagerEvent','onPrevNextEvent']
		},
		$Options={
			'autorun':$Configuration.autorun,
			'autostart':true,
			'animation':false,
			'callbacks':false,
			'type':false,
			'selector':false
		},
		$RegisteredItems={},
		$UnregisteredItems=[]
	;

	var $lib={
			'getSlideNode':function(name){
				var slidemap={
					'after':0,
					'before':0,
					'end':false,
					'onPagerEvent':1,
					'onPrevNextEvent':2,
					'pagerAnchorBuilder':false,
					'timeoutFn':0,
					'updateActivePagerLink':false
				};
				return slidemap[name];
			},
			'transformObject':function(object){
				var items={},
					argumentList=object.arguments
				;
				if(object.functions){
					$.each(object.functions,function(k,v){
						items[k]=$utils.init(_function,[v,false,false]);
						if(argumentList && argumentList[k]){
							items[k].arguments=argumentList[k];
						}
					});
				}
				return items;
			}
		}
	;

	// initialize all callbacks with an _event object
	$.each($ActiveCallbacks,function(n,v){
		$ActiveCallbacks[n]=$utils.init(_event,[n]);
	});

	$.fn.cyclerotation=function(id){
		if($RegisteredItems[id]){
			var item=$RegisteredItems[id];
			if(!item.active){
				var self=false,
					options=$.extend(true,{},$Options,item.parameters),
					callbacks={}
				;
				if(options.onBefore && $.isFunction(options.onBefore)){
					options.onBefore.apply(item);
				}
				item.active=true;
				$.each($Configuration.slideCallbacks,function(k,v){
					callbacks[v]=function(){
						if($ActiveCallbacks[v].queue.length){
							// runs all callback function add using CycleRotation::bind().
							$ActiveCallbacks[v].run(this,arguments);
						}
						// check to make sure the callback allows the slide node element to be passed into the function.
						// this will prevent an error when retrieving the element data
						var slideNodeIndex=$lib.getSlideNode(v);
						if(slideNodeIndex!==false){
							var data=$(arguments[slideNodeIndex]).data($Configuration.datakey),
								globalResult=false,
								hasScopedCallback=item.scopedCallbacks && item.scopedCallbacks[v],
								hasSlideCallback=item.slideCallbacks[data['slide-index']] && item.slideCallbacks[data['slide-index']][v]
							;
							if(hasScopedCallback){
								var parameters=false;
								if(hasSlideCallback){
									parameters=$.merge(item.slideCallbacks[data['slide-index']][v].arguments,arguments);
								}
								// runs the callback specified in the events object of the register properties.
								globalResult=item.scopedCallbacks[v].apply(this,parameters?parameters:arguments);
							}
							if(hasSlideCallback && item.slideCallbacks[data['slide-index']][v].own){
								var parameters=[globalResult];
								for(var i in arguments){
									parameters.push(arguments[i]);
								}
								// runs the slide specific callback function.
								item.slideCallbacks[data['slide-index']][v].apply(this,parameters);
							}
						}
					}
				});

				self=item.item.empty().each(function(i,o){
					$(o).append(item.slides[i]);
				}).cycle($.extend(true,options.animation,callbacks));
				if((!$Configuration.autostart && !options.autostart)||($Configuration.autostart && !options.autostart)){
					self.cycle('pause');
					item.paused=true;
				}
				delete item.clone;

				if(options.controls){
					if(options.controls.next){
						$(options.controls.next).click(function(){
							self.each(function(k,v){
								var me=self.eq(k);
								if(me.is(':visible')){
									me.cycle('next');
								}
							});
							return false;
						});
					}
					if(options.controls.prev){
						$(options.controls.prev).click(function(){
							self.each(function(k,v){
								var me=self.eq(k);
								if(me.is(':visible')){
									me.cycle('prev');
								}
							});
							return false;
						});
					}
				}

				if(options.onAfter && $.isFunction(options.onAfter)){
					options.onAfter.apply(item,[self]);
				}
				return self;
			}
			if(item.paused){
				item.item.cycle('resume');
			}
		}
		return this;
	}

	var $Self={
			// add an event callback handler to the global callback scope.
			// * in order for callback function bound to fire on the first slide when autorun is enabled,
			//   the call MUST be placed outside of a DOM ready callback function.
			'bind':function(type,callback){
				if(typeof($ActiveCallbacks[type])!=='undefined'){
					$ActiveCallbacks[type].add(callback);
					return true;
				}
				return false;
			},
			// returns the active items
			//
			// - returns:
			//   - an array of the desired items
			//
			// @asObject       [boolean]   false   returns the items as objects instead of the id
			// @invert         [boolean]   false   returns the inactive items instead of the active items.
			'getActiveItems':function(asObject,invert){
				var items=[];
				$.each($RegisteredItems,function(k,v){
					if((v.active && !invert) || (!v.active && invert)){
						items.push(asObject?v:k);
					}
				});
				return items;
			},
			'getAutorunResult':function(){
				return $AutorunResult;
			},
			// returns the internal value used for storing by the data jQuery function.
			'getDataKey':function(){
				return $Configuration.datakey;
			},
			// return the internal array of allowed callbacks for each slide in the rotation.
			'getSlideCallbacks':function(){
				return $Configuration.slideCallbacks;
			},
			// returns the unregistered items that were requested using $CycleRotation.run()
			'getUnregisteredItems':function(){
				return $UnregisteredItems;
			},
			'pause':function(id){
                $RegisteredItems[id].item.cycle('pause');
            },
            'play':function(id){
                $RegisteredItems[id].item.cycle('resume');
            },
			// register a new item to be placed in the queue of CycleRotation objects.
			//
			// @id             [string]            The id to use to reference the registered item.
			// @parameters
			//  - animation    [object]            the object of parameters that gets passed directly
			//                                     to the jQuery Cycle plugin.
			//  - autorun      [boolean]   true    control if this rotation should autorun. this setting will
			//                                     override the global configuration autorun setting
			//  - autostart    [boolean]   true    this will control if this rotation should start after the
			//                                     rotation has been initialized
			//  - callbacks    [array]             an array of objects where the index of the object cooresponds
			//                                     with the index of the rotation items. each object has only two
			//                                     properties, "functions" and "arguments", where each property is
			//                                     an object of the callback functions and their argument values
			//  - events       [object]            object of callback handlers to execute each time the specified
			//                                     callback function is triggered within the scope of the registered
			//                                     CycleRotation item. the possible callback handlers are the same a
			//                                     the allowed handlers for the slide callback handlers.
			//  - type         [string]            [== not active ==]
			//  - selector*    [string]            the jQuery selector of the container to use. each child of the
			//                                     container become an individual rotating slide
			//  - onBefore     [function]          callback function to fire before the item is run
			//  - onAfter      [function]          callback function to fire after the item is run
			'register':function(id,parameters){
				var object=$(parameters.selector),
					clone=object.clone(true,true),
					callbacks=[]
					slides=[]
				;
				object.children(':gt(0)').remove();

				clone.each(function(i,o){
					slides[i]=$(o).children().each(function(k,v){
						$(v).data($Configuration.datakey,{'id':id,'slide-index':i,'cycle-index':k});
					});
				});

				// convert callback objects into object of _function objects
				if(parameters.callbacks && $.isArray(parameters.callbacks)){
					$.each(parameters.callbacks,function(k,v){
						callbacks[k]=$lib.transformObject(v);
					});
				}
				$RegisteredItems[id]={
					'active':false,
					'autorun':parameters['autorun']===undefined || (parameters['autorun']!==undefined && parameters.autorun),
					'clone':clone,
					'scopedCallbacks':parameters.events,
					'id':id,
					'item':object,
					'parameters':parameters,
					'paused':false,
					'slides':slides,
					'slideCallbacks':callbacks
				}
			},
			// run/initialize all of the queued/registered items
			//
			// - returns:
			//   - an object if the DOM is ready
			//     ex. {'hasRegisteredItems':true,'hasUnregisteredItems':false,'hasInactiveItems':false}
			//   - false if the DOM is not ready
			//
			// @id             [string,array]
			//
			// * will ONLY execute if the DOM is ready.
			'run':function(id){
				var hasRegisteredItems=false,
					hasUnregisteredItems=false,
					hasInactiveItems=false;
				if($.isReady){
					id=id?($utils.is(id,'Array')?id:id.split(',')):false;
					$.each($RegisteredItems,function(k,v){
						if(!v.active){
							if(!id || (id && $.inArray(k,id)>=0)){
								if(v.autorun || $AutorunResult){
									hasRegisteredItems=true;
									v.item.cyclerotation(k);
									return true;
								}
								return hasInactiveItems=true;
							}
							hasUnregisteredItems=true;
						}
					});
					if(hasUnregisteredItems){
						for(var k in id){
							if(!$RegisteredItems[id[k]]){
								$UnregisteredItems.push(id[k]);
							}
						}
					}
					return {'hasRegisteredItems':hasRegisteredItems,'hasUnregisteredItems':hasUnregisteredItems,'hasInactiveItems':hasInactiveItems}
				}
				return false;
			},
			// sets the CycleRotation to run all of the queued/registered items upon DOM ready.
			//
			// * must be called outside of a DOM ready callback in order to prevent all queued/registered items
			//   from being intialized and executed.
			'setAutorun':function(a){
				$Configuration.autorun=a;
			},
			// set the CycleRotation to start the rotation for all of the queued/registered items upon DOM ready
			'setAutostart':function(a){
				$Configuratoin.autostart=a;
			},
			// sets the internal value used for storing by the data jQuery function.
			//
			// - returns:
			//   - a boolean true upon completion of the process.
			//   - a boolean false if items have already been registered
			//
			// * this can only be called prior to any items being registered.
			'setDataKey':function(dk){
				if($.isEmptyObject($RegisteredItems)){
					$Configuration.datakey=dk;
					return true;
				}
				return false;
			}
		}
	;

	$(function(){
		if($Configuration.autorun){
			$AutorunResult=$Self.run();
		}
	});

	return $Self;
})(typeof(jQuery)!=='undefined'?jQuery:null);
