/**
 * This class will create rotating banners. It will make an AJAX call to @ajaxURL.
 * It then will write the banner to @writeToElementId and will change based on
 * the @timer. The @id is used to track the object back in global scope for the interval.
 *
 * @param writeToElementId - id tag of element which we are going to place the banners in.
 * @param ajaxURL - url to controller that is responsible for creating the list of banners.
 * @param timer - this timer is assumed to be in seconds and will be converted into milliseconds.
 * @param id - this must match the var name for the object used to instantiate this class. We do this
 * 			   so we can track the original object in global scope, since we utilize setInterval,
 * 			   which has no understanding of 'this' and thus needs the id to track down the proper object.
 * @return NA.
 */
function Banners(writeToElementId, ajaxURL, timer, id) {
	this._id = id;
	this._banners = new Array(0);
	this._bannersLength = -1;
	this._currentBannerIndex = -1;

	this._ajaxURL = ajaxURL;
	this._timer = timer;

	this._hasError = false;
	this._errorMessage = "";
	this._interval = null;
	this._defaultWidth = 800;
	this._defaultHeight = 150;
	this.bndesc = "";

	/**
	 * Initial function called to create the AJAX request, when it succeeds, it calls
	 * first, which will determine if we have any banners and set the counter to the
	 * appropriate starting banner. Once our request is complete, we call create, which
	 * will write the new banner to the DOM.
	 */
	this.init = function() {
		var _nocache = new Date();
		new Ajax.Request(ajaxURL, {
			method: "post",
			parameters: "nocache=" + _nocache.getTime(),
			//Get First Banner
			onSuccess: this.first.bindAsEventListener(this),
			//Write Banner to DOM
			onComplete: this.create.bindAsEventListener(this),
			onFailure: function(transport) {
				this._hasError = true;
				this._errorMessage = "Failure in init - ajax call.";
			},
			onException: function(transport) {
				this._hasError = true;
				this._errorMessage = "Exception in init - ajax call.";
			}
		});
	};

	/**
	 * This method will write the current banner to the dom.
	 */
	this.create =  function(evt) {
		if(this._bannersLength > 0) {
			//Grab current banner
			var _copartBanner = this._banners[this._currentBannerIndex];
            //set bndesc
			this.bndesc = _copartBanner.bndesc;
			//Set container width
			$(writeToElementId).style.width = this.finalWidth(_copartBanner.w) + "px";
			//Set Container height
			$(writeToElementId).style.height = this.finalHeight(_copartBanner.h) + "px";
			//Set display
			$(writeToElementId).style.display = "block";
			//Set overflow
			$(writeToElementId).style.overflow = "hidden";
			var anchor;

			//Check if the current banner is supposed to hyperlink
			if(_copartBanner.url.length > 0) {
				//Check if the hyperlink should open a new window
				if(_copartBanner.newWindow == "true") {
					//Create the link tag for the banner for new window
					anchor = $E({ tag: 'a', href: _copartBanner.url, target: "_blank", id: writeToElementId + 'Link' });
				}
				else {
					//Create the link tag for the banner
					anchor = $E({ tag: 'a', href: _copartBanner.url, target: "_self", id: writeToElementId + 'Link' });
				}
			}
			else {
				//There is no hyperlink for the banner
				anchor = $E({ tag: 'a', href: '', target: "_self", id: writeToElementId + 'Link' });
			}
			//Create the image tag for the banner
			var img = $E({
				tag:	'img',
				src:	this.createBannerPath(_copartBanner.path),
				id:		writeToElementId + 'Img'
			});

			//Give the banner image a function to start the timer
			img.setAttribute("onload", id+".startTimer();");
		    img.onload = function(){
		    	var obj = eval(id);
		        obj.startTimer();
		    };
		    // Send BnDesc to Omniture Tagging when the user click on Image.
		    img.setAttribute("onClick", id+".sendBnDescToOmnitureTag();");
		    img.onClick= function(){
		    	var obj = eval(id);
		    	obj.sendBnDescToOmnitureTag();
		    };

		    //Add the Image to the hyperlink tag
			anchor.appendChild(img);
			//Add the hyperlink tag to the element specified
			$(writeToElementId).appendChild(anchor);
		}
	};

	// Send BnDesc to Omniture Tagging when the user click on Image.
	this.sendBnDescToOmnitureTag = function() {
		s.tl(this,'o',this.bndesc);
	};

	/**
	 * This method is used to update the banner, once it has been written to the DOM.
	 */
	this.update = function(evt) {
		//Get the object from Global Scope
		var obj = eval(evt);
		//Get banner collection
		var i_banners = obj.getBanners();
		//Get the current banner index
		var i_index = obj.getCurrentBannerIndex();
		//Get the current banner
		var _copartBanner = i_banners[i_index];
		//set bndesc
		this.bndesc = _copartBanner.bndesc;
		//Reset the banner container size to match that of the current banner.
		$(writeToElementId).style.width = this.finalWidth(_copartBanner.w) + "px";
		$(writeToElementId).style.height = this.finalHeight(_copartBanner.h) + "px";
		$(writeToElementId).style.display = "block";
		$(writeToElementId).style.overflow = "hidden";

		//Remove the onload method, since the timer is now active.
		$(writeToElementId+'Img').removeAttribute("onload");
		$(writeToElementId+'Img').onload = null;
		
		// Send BnDesc to Omniture Tagging when the user click on Image.
		$(writeToElementId+'Img').setAttribute("onClick", id+".sendBnDescToOmnitureTag();");
		$(writeToElementId+'Img').onClick= function(){
	    	var obj = eval(id);
	    	obj.sendBnDescToOmnitureTag();
	    };

		//If the banner has a blank URL property, we remove the links href and target attributes
		if(_copartBanner.url.length < 1) {
			$(writeToElementId+'Link').removeAttribute("href");
			$(writeToElementId+'Link').removeAttribute("target");
		}
		else {
			//We have a URL, so update it
			$(writeToElementId+'Link').setAttribute("href", _copartBanner.url);
			if(_copartBanner.newWindow == "true") {
				//Set the hyperlink to open in a new window
				$(writeToElementId+'Link').setAttribute("target", "_blank");
			}
			else {
				$(writeToElementId+'Link').setAttribute("target", "_self");
			}
		}
		//Update the banners image
		$(writeToElementId+'Img').src = this.createBannerPath(_copartBanner.path);
	};

	/**
	 * This method will set up the counter for the next banner to show.
	 */
	this.next = function(evt) {
		//Get the object from Global scope
		var obj = eval(evt);
		//Get the current banner's index and increment it to the next one
		var iCounter = obj.getCurrentBannerIndex();
		iCounter++;
		//Make sure that the counter isn'g larger than our collection

		var bannersCount = obj.getBannersLength();

		if(Prototype.Browser.IE) {
			bannersCount = obj.getBannersLength() - 1;
		}

		if(iCounter >= bannersCount) {
			//It is, so reset it to the beginning.
			iCounter = 0;
		}

		//Update the object with the new current banner
		this.setCurrentBannerIndex(iCounter);
		//Now call the update function to add the banner to the DOM
		this.update(this.getId());
	};

	/**
	 * This method will read the AJAX response and extract the JSON object. This method sets
	 * the banner count and collection. If no banners exist or the node that we are going to
	 * populate with the banners does not exist, we set the error.
	 */
	this.first = function(transport) {
		//Eval the AJAX Response and get the JSON object
		var jsonBanners = transport.responseText.evalJSON();
		//Set banners count
		this._bannersLength = jsonBanners.banners.length;
		//Instantiate banners collection
		this._banners = new Array(this._bannersLength);
		for(var i = 0; i < this._bannersLength; i++) {
			//Add banner to collection
			this._banners[i] = jsonBanners.banners[i];
		}

		//No Banners.
		if (this._bannersLength < 1) {
			this._hasError = true;
			this._errorMessage = "There are no banners to display.";
		}
		//Element to write to is null.
		else if ($(writeToElementId) === null || $(writeToElementId) === undefined) {
			this._hasError = true;
			this._errorMessage = "Element with id: " + writeToElementId + " doesn't exist.";
		}
		else {
			// We're good, start at the first banner.
			this._currentBannerIndex = 0;
		}
	};

	this.finalWidth = function(bannerWidth) {
		if(bannerWidth != null) {
			return bannerWidth;
		}
		else {
			return this._defaultWidth;
		}
	};

	this.finalHeight = function(bannerHeight) {
		if(bannerHeight != null) {
			return bannerHeight;
		}
		else {
			return this._defaultHeight;
		}
	};

	this.createBannerPath = function(bannerPath) {
		if(bannerPath != null) {
			var normalizedPath = bannerPath.toUpperCase();
			if(normalizedPath.indexOf('HTTP://') >= 0) {
				return bannerPath;
			}
			else {
				return global.contextRoot + bannerPath;
			}
		}
	}

	/**
	 * Timer to rotate the banners. This method depends on the @id, which we eval to get the object
	 * from global scope.
	 */
	this.startTimer = function() {
		var _self = eval(this._id);
		this._interval = window.setInterval( function() { _self.next(_self.getId()); }, this._timer*1000);
	};

	 /**
	  * This method allows us to cancel the interval, stopping the banners from rotating.
	  */
	this.stop = function() {
		window.clearInterval(this._interval);
	};

	/**
	 * This method will let you know if we have an error and what it was.
	 *
	 * @return Error -  hasError (boolean) and errorMsg (String).
	 */
	this.error = function() {
		return { hasError: this._hasError, errorMsg: this._errorMessage };
	};

	//////////////////////////
	// Getters and Setters
	//////////////////////////
	this.getId = function() {
		return this._id;
	};

	this.getCurrentBannerIndex = function() {
		return this._currentBannerIndex;
	};

	this.setCurrentBannerIndex = function(val) {
		this._currentBannerIndex = val;
	};

	this.getBannersLength = function() {
		return this._bannersLength;
	};

	this.getBanners = function() {
		return this._banners;
	};

}
