/* introduce a new "namespace" object */
var FeatureCue=function () {
  
	var blacklist= {
		/* The cookie backend encapsulation of the blacklist */
		idList:new Array(),
  
		init:function() {
			var cookieString=document.cookie;
			var cookieArray=cookieString.split(";");
			for(var i=0;i<cookieArray.length;i++) {
				/* fish out _cueBlackList Cookie */
				if(cookieArray[i].match(/^\s*_cueBlackList/)) {
					cookieString=cookieArray[i];
					var tempArray=cookieString.split("=");
					var cookieValue=tempArray[1];
					/* get all blocked IDs list */
					this.buildIDList(cookieValue);
					break;
				}
			}
		},
		
		buildIDList:function(cookieValue){
			if(!cookieValue || cookieValue.length==0) {  		
				return;
			}
			/* split the cookie value around "," into an array; format is "id,id,id ..."*/
			this.idList=cookieValue.split(",");
		},
		
		addCueId:function(cueId) {
			/* avoid duplicate entries, it's worth the hassle */
			if(!this.isCueIdInList(cueId)) {
				this.idList.push(cueId);
				this.setCookie();
			}
		},
		
		isCueIdInList:function(cueId){
			if(!this.idList||this.idList.length==0) {
				return false;
			}
			var found=false;
			for(var i=0;!found && i<this.idList.length;i++) {
				if(this.idList[i]==cueId) {
					found=true;
				}
			}
			return found;
		},
		
		setCookie:function(){
			var cookieValue=this.idList.join(",");
			var cookie="_cueBlackList="+cookieValue;
			//cookie+=";domain=.kijiji.com";
			cookie+=";expires=";
			/* cookie will get stale in 1 year */
			var stale=new Date();
			stale.setTime(stale.getTime()+365*24*60*60*1000);
			cookie+=stale.toGMTString();
			document.cookie=cookie;
		}
	}; /* End of blacklist object */
	
	var helpers={
		displayBlocked:false,
		getPageCue:function() {
			var cue=$(".featureCue");
			if(cue==null||cue.length==0) {
				throw "No cue on page!";
			}else if(cue.length>1) {
				throw "Contract violation: Exactly one feature per page expected!";
			}
			return cue[0];
		},
		
		getPageCueId:function() {
			return this.getPageCue().getAttribute("id");
		},
		
		dismissCue:function() {
			/* find the one included FC (if any)*/
			var cue=this.getPageCue();
			cue.style.visibility="hidden";
			/* make sure pointers are invisible, too */
			$(".featureCueBottomLPointer")[0].style.visibility="hidden";
			$(".featureCueBottomRPointer")[0].style.visibility="hidden";
			$(".featureCueTopLPointer")[0].style.visibility="hidden";
			$(".featureCueTopRPointer")[0].style.visibility="hidden";
			blacklist.addCueId(cue.getAttribute("id"));
		},
		
		displayCue:function() {
			if(this.displayBlocked) {
				return;
			}
			var cue=this.getPageCue();
			var cueId=cue.getAttribute("id");
			/* Is display permissible ? */
			if(!blacklist.isCueIdInList(cueId)) {
				cue.style.visibility="visible";
			}
		}
	}; /* end of helpers object */
	
	return {
		/*
			Constants for attaching the cue on this page to a widget (element)
		*/	
		ATTACH_TOPRIGHT:1, /* attach cue to the upper right hand corner of the widget */
		ATTACH_TOPLEFT:2, /* attach cue to the upper left hand corner of the widget */
		ATTACH_BOTTOMRIGHT:3, /* guess ... */
		ATTACH_BOTTOMLEFT:4,
		GENERAL_MESSAGE_BOX:5, /* don't attach at all, display it as float */
		
		/* init the cue */
		init:function(){
			blacklist.init();
		},
		
		/* displays the cue on this page, if any */
		display:function() {
			helpers.displayCue();
		},
		/* hides the cue on this page, if any, and remembers it as dismissed */
		hide:function() {
			helpers.dismissCue();
		},
		
		/*
			Attaches the cue on this page to the given widget (element) in the way indicated
			by "attachmode"
		*/
		attachCueToWidget:function(widget,attachmode) {
			/* do nothing if cue is blocked */
			var cue=helpers.getPageCue();
			var cueId=cue.getAttribute("id");
			/* Is display permissible ? */
			if(blacklist.isCueIdInList(cueId)) {
				return;
			}

			/* data structure */
			var Rectangle=function(element) {				
				this.top=0;
				this.left=0;
				if (element) {
					var currentElement=element;
					do {
						this.top=this.top+currentElement.offsetTop;
						this.left=this.left+currentElement.offsetLeft;
						currentElement=currentElement.offsetParent;
					}while (currentElement!=null);
					this.right=this.left+element.offsetWidth;
					this.bottom=this.top+element.offsetHeight;
				}
			}
			/* sanity check */
			if(typeof widget!='undefined'&&widget!=null) {
				var widgetBox=new Rectangle(widget);
			} else if(attachmode!=this.GENERAL_MESSAGE_BOX) {
				/* Note: We know from the previous check that widget is null/undefined. With this check
				we know that originally the cue tried to hook itself up to a widget -> don't show it */
				helpers.displayBlocked=true;
				return;
			} 
			/* position feature cue according to given constant */
			var bodyBox=new Rectangle($("body")[0]);
			/* use the logo as upper view port limitation */
			var logoBox=new Rectangle($(".logo")[0]);
			bodyBox.top=logoBox.bottom;
			switch(attachmode) {
				/*
					Some numbers explained:
						38: Pointers are 55px high, but they overlap the FC by 17 px - 55-17=38
						20: Pointers have an offset of 20 px to the left of the FC box
						10: Pointers are to overlap their parent widget by 10x10 pixels
					Some of the checks explained:
						After setting top and left according to the attachmode a check is performed
						if these coordinates will shift the cue out of the viewport. If so the
						box will be moved to the the opposite side by recursively calling this
						method with the appropriate parameters.
				*/
				case this.ATTACH_TOPRIGHT:
					cue.style.top=(widgetBox.top-38-cue.offsetHeight+10)+"px";
					cue.style.left=(widgetBox.right-20-10)+"px";
					if(cue.offsetLeft+cue.offsetWidth>bodyBox.right) {
						this.attachCueToWidget(widget,this.ATTACH_TOPLEFT);
					} else if (cue.offsetTop<bodyBox.top){
						this.attachCueToWidget(widget,this.ATTACH_BOTTOMRIGHT);
					} else {
						$(".featureCueBottomLPointer")[0].style.visibility="visible";
					}
					break;
				case this.ATTACH_TOPLEFT:
					cue.style.top=(widgetBox.top-38-cue.offsetHeight+10)+"px";
					cue.style.left=(widgetBox.left-cue.offsetWidth+10)+"px";
					if(cue.offsetLeft<0) {
						this.attachCueToWidget(widget,this.ATTACH_TOPRIGHT);
					} else if (cue.offsetTop<bodyBox.top){
						this.attachCueToWidget(widget,this.ATTACH_BOTTOMLEFT);
					} else {
						$(".featureCueBottomRPointer")[0].style.visibility="visible";
					}
					break;
				case this.ATTACH_BOTTOMRIGHT:
					cue.style.top=(widgetBox.top+38+10)+"px";
					cue.style.left=(widgetBox.right-20-10)+"px";
					if(cue.offsetLeft+cue.offsetWidth>bodyBox.right) {
						this.attachCueToWidget(widget,this.ATTACH_BOTTOMLEFT);
					} else if (cue.offsetTop+cue.offsetHeight>bodyBox.bottom){
						this.attachCueToWidget(widget,this.ATTACH_TOPRIGHT);
					} else {
						$(".featureCueTopLPointer")[0].style.visibility="visible";
					}
					break;
				case this.ATTACH_BOTTOMLEFT:
					cue.style.top=(widgetBox.top+38+10)+"px";
					cue.style.left=(widgetBox.left-cue.offsetWidth+10)+"px";
					if(cue.offsetLeft+cue.offsetWidth>bodyBox.right) {
						this.attachCueToWidget(widget,this.ATTACH_BOTTOMRIGHT);
					} else if (cue.offsetTop+cue.offsetHeight>bodyBox.bottom){
						this.attachCueToWidget(widget,this.ATTACH_TOPLEFT);
					} else {
						$(".featureCueTopRPointer")[0].style.visibility="visible";
					}
					break;
				case this.GENERAL_MESSAGE_BOX: /*fall through to default*/
				default: /* display "general message cue" floating in the middle */
					cue.style.top="100px";
					cue.style.left=(document.body.offsetWidth-cue.offsetWidth)/2+"px";
			}
		}
	};
};

var featureCue=new FeatureCue();
