// ############################### CLASSES #####################################

/* ###	RTO Placement Class
		Used to provide structured data for the rtoConfigPlacements array in config_data.js

		positionValue:			string - '01' || '02'
		[Required]				Placement location on a page. Corrosponds to the
								rtoOfferPos_## id of an anchore tag on the page.
								
		offerIdValues:			string - 'offerName'
		[Required]				Array of values that match the offerId string in the 
								offerConfig array. When multiple are assigned, one 
								offer is selected at random among the list. All
								offers have equal weighting.

		pageDescriptorValues:	array[ string || number] - 12345 || '/some/path/filename.html' || or '/some/path/'
		[Required]				An array of strings & numbers that represent asset
								IDs and/or path strings (path strings are strings
								that will be used to match something in window.location.href.
								The latter provides a way to specify more than one
								location based on a url pattern. AssetIds override
								all. If a match occures multiple times in the
								placementConfig array for a given position, the 
								assetId will always win out. If the assetId  or
								path occures multiple times for the same position,
								the last occurence wins specified in the config wins out. 
*/
function RtoPlacementClass ( positionValue, offerIdValues, pageDescriptorValues) {
	this.position= 			positionValue;
	this.offerId=			offerIdValues[ Math.floor( Math.random() * offerIdValues.length ) ];
	this.pageDescriptors=	pageDescriptorValues;
}

/* ###	RTO Offer Class
		Used to provide structured data for the rtoConfigOffers array in config_data.js

		offerIdValue:			string - 'algaward'
		[Required]				Some unique identifier for this offer. Human readable
								values will make it easier to understand the associations
								in the placementConfig array.

		imageNameValue:			string - 'algaward_01.gif'
		[Required]				File name for the offer image. Images will be loaded
								from the path /img/rto/

		linkUrlValue:			string - '/infiniti_today/latest_news/G35_Wins_2005_Residual_Value_Award_from_ALG.html' || 'http://www.somesite.com/some/path/page.html'
		[Required]				Link value for the offer

		targetValue:			string - '_blank' || 'myWindowName'
		[NOT Required]			If the link should pop a new window the provide
								a value for the target attribute of the A tag.
*/
function RtoOfferClass (offerIdValue, imageNameValue, linkUrlValue, targetValue) {
	this.offerId=		offerIdValue;
	this.imageUrl=		getWWWRootPath() + '/img/rto/' + imageNameValue;
	this.linkUrl=		linkUrlValue;
	this.targetValue=	(typeof(targetValue)=='undefined')? '_self' : targetValue;

	function getWWWRootPath() {
		return rtoJsURLPrefix.substring( 0,rtoJsURLPrefix.indexOf('/js/crm/rto/') );
	}
}

/* ###	RTO Data Object for offers
		Creates the main data object that holds associated offer and placement
		data. The object is empty by default until its init function is called.
*/
function RtoDataObjClass () {
// ###	Private vars
	var offers=[];						//array: holds the offers arry passed in on init
	var placments=[];					//array: holds the placements array passed in on init
	var defaultPlacements=[]			//array: holds the default placements array passed in on init
	var offersByPath=[];				//array: holds offer info organized by path
	var offersByAssetId=[];				//array: holds offer info organized by assetId
	var isInitialized = false;			//boolean: has the init function been called
	var assetId= ( $('metaAssetId') )? $('metaAssetId').content : ( (typeof(crmPageId)!='undefined')?crmPageId:null );
										//number: grab the assetId for the page from the metatag. On failure, use crmPageId. On failure assign null.
// ###	Private functions
	
	//	Returns an offer object based on offer ID.
	//	if offers array dosent exist, or no offer found for offerId it returns null
	function getOfferDataByOfferId (offerIdValue) {
		if (!offers) return null;
		for (var offerIndex in offers) {
			var offer = offers[offerIndex];
			if (offer.offerId == offerIdValue)
				return offer;
		}
		return null;
	}
	
	//	Compares param with browser path.
	//	Returns true if param is found in browser location, otherwise false
	function pathsMatch (pathValue) {
		if ( location.href.indexOf(pathValue) > -1 )
			return true;
		return false;
	}
	
	//	Returns all the key values as an array for a given array
	function getKeys (inputArray) {
		var keyArray=[];
		for(var key in inputArray)
			keyArray.push(key);
		return keyArray;
	}
	
	//	Bubble sorts an inputArray based on array values
	function bubbleSort(inputArray) {
		var start = 0;
		var rest = inputArray.length - 1;
		for (var i = rest - 1; i >= start;  i--) {
			for (var j = start; j <= i; j++) {
				if (inputArray[j+1] < inputArray[j]) {
					var tempValue = inputArray[j];
					inputArray[j] = inputArray[j+1];
					inputArray[j+1] = tempValue;
			     }
			}
		}
		return inputArray;
	}
	
	//	Sorts an offer object by its Keys, which actually the position values
	function sortOffers(offers) {
		var sortedOffers=[];
		var sortedPositions = bubbleSort( getKeys(offers) );
		for (var i in sortedPositions)
			sortedOffers[sortedPositions[i].toString()] = offers[sortedPositions[i]];
		return sortedOffers;
	}

// ###	Public functions
	
	//	Returns the initialized state (whether init function has been called or not) for this objects instance
	this.getIsInitialized = function(){return isInitialized;}
	
	//	Returns an array of offer objects for the current page.
	//	Does all the lookup work, and sorting. The returned offer array key values
	//	are the offer positions
	this.getMyOffers = function () {
		var offersArray=[];
		//	Lookup offers by path
		for (var pageDescriptor in offersByPath) {
			if ( pathsMatch(pageDescriptor) ) {
				var offers = offersByPath[pageDescriptor];
				for (var offerPosition in offers) {
					if ( offers[offerPosition] ) { //	check to make sure its a valid. putting a bad offerIdValue in rtoConfigPlacements would make this null
						offersArray[offerPosition.toString()] = offers[offerPosition];
						offersArray[offerPosition.toString()].pageDescriptor = pageDescriptor; //	Tack on a pageDescriptor prop to embed as image attribute for debugging
					} else { crmDebug('RTO ERROR:\nOffer object returned was invalid (null). Use the following\ninformation to check the config_data file to verify that\nthe offerId is correct.\n\nLocation: rtoDataObj.getMyOffers()\nRegion: Lookup offers by path\npageDescriptor: '+pageDescriptor+'\nofferPosition: '+offerPosition) }
				}
			}
		}
		//	Lookup offers by assetId (aka pageId).
		//	Do this last to override any offer positions that we found for path. AssetIds always win
		if (typeof( assetId ) != 'undefined') {
			if ( offersByAssetId[ assetId ] != 'undefined' ) {
				var offers = offersByAssetId[ assetId ];
				for (var offerPosition in offers) {
					if ( offers[offerPosition] ) { //	check to make sure its a valid. putting a bad offerIdValue in rtoConfigPlacements would make this null
						offersArray[offerPosition.toString()] = offers[offerPosition];
						offersArray[offerPosition.toString()].pageDescriptor = assetId; //	Tack on a pageDescriptor prop to embed as image attribute for debugging
					} else { crmDebug('RTO ERROR:\nOffer object returned was invalid (null). Use the following\ninformation to check the config_data file to verify that\nthe offerId is correct.\n\nLocation: rtoDataObj.getMyOffers()\nRegion: Lookup offers by assetId\npageDescriptor: '+assetId+'\nofferPosition: '+offerPosition) }
				}
			}
		}
		//	Apply any defaults that were not covered by the placement config
		for(var defaultPlacementIndex in defaultPlacements) {
			var match = false;
			var defaultPlacement = defaultPlacements[defaultPlacementIndex];
			for (var position in offersArray) {
				if (position == defaultPlacement.position) {
					match = true;
					break;
				}
			}
			if (!match) {
				if ( getOfferDataByOfferId(defaultPlacement.offerId) ) { //	check to make sure its a valid. putting a bad offerIdValue in rtoConfigPlacements would make this null
					offersArray[defaultPlacement.position.toString()] = getOfferDataByOfferId(defaultPlacement.offerId);
					offersArray[defaultPlacement.position.toString()].pageDescriptor = 'default_placement';
				} else { crmDebug('RTO ERROR:\nOffer object returned was invalid (null). Use the following\ninformation to check the config_data file to verify that\nthe offerId is correct.\n\nLocation: rtoDataObj.getMyOffers()\nRegion: Apply defaults\npageDescriptor: default_placement\nofferPosition: '+defaultPlacement.position) }
			}
		}
		return sortOffers(offersArray);
	}

	/*	init (offersArray, placementsArray)
		RtoDataObjClass objects are empty be default. Init function initializes
		the data from the config arrays so that offer information will become
		available via other RtoDataObjClass object functions
		
		offersArray:			Array
		[Required]				An array of RtoOfferClass objects
		
		placementsArray:		Array
		[Required]				An array of RtoPlacementClass objects

		defaultPlacementsArray:	Array
		[Required]				An array of RtoPlacementClass objects
	 */
	this.init = function (offersArray, placementsArray, defaultPlacementsArray) {
		offers = offersArray;
		placements = placementsArray;
		defaultPlacements = defaultPlacementsArray;
		for (var placementIndex in placements) {
			var placement = placements[placementIndex];
			for (var pageDescriptorIndex in placement.pageDescriptors) {
				var pageDescriptor = placement.pageDescriptors[pageDescriptorIndex];
				//	For each pageDescriptor, check to see if its number or path and assign to the appropriate array
				if ( typeof(pageDescriptor)=='number' ) { 
					if ( typeof(offersByAssetId[pageDescriptor]) == 'undefined') offersByAssetId[pageDescriptor]=[];
					offersByAssetId[pageDescriptor][placement.position.toString()] = getOfferDataByOfferId(placement.offerId);
				} else {
					if ( typeof(offersByPath[pageDescriptor]) == 'undefined') offersByPath[pageDescriptor]=[];
					offersByPath[pageDescriptor][placement.position.toString()] = getOfferDataByOfferId(placement.offerId);
				}	
			}
		}
		isInitialized = true;
	}
}

// ############################## INITIALIZE ###################################

// ###	Create empty data object. this object is referenced in config_data.js and display_handler.js
var rtoDataObj = new RtoDataObjClass();

// ###	Include config data and handler files
var rtoJsURLPrefix =  $('rtoInit').src.substring( 0,$('rtoInit').src.indexOf('/init.js')+1 ); // the '/' in '/init.js' seems to be required for collage preview to work
document.write('<scr'+'ipt src="' + rtoJsURLPrefix + 'config_data.js" language="JavaScript" type="text/javascript"></scr'+'ipt>\n');
document.write('<scr'+'ipt src="' + rtoJsURLPrefix + 'display_handler.js" language="JavaScript" type="text/javascript"></scr'+'ipt>\n');