if(window.Ext) {
	if(!CI) Ext.namespace('CI');
	if(!CI.util) Ext.namespace('CI.util');
	/**
	* @namespace
	* @name CI.util.Coremetrics
	*/
	Ext.namespace('CI.util.Coremetrics');
} else {
	// allow the ability to include this util without Ext
	if(!CI) var CI = {};
	CI.util = /** @ignore */ {
		Coremetrics : {}
	};
}

/**
* IE does not have the native method indexOf for Arrays
*/
if(!Array.prototype.indexOf) {
  Array.prototype.indexOf = function(obj){
    for(var i=0; i<this.length; i++){
      if(this[i]==obj){
        return i;
      }
    }
    return -1;
  }
}

/**
* This is a straight delegator to the coremetrics create conversion event tag
* @singleton
*/
CI.util.Coremetrics = {
	/*
	* Creates a Conversion Event Tag
	* @params {String} eventID See the Coremetrics documentation
	* @params {String} actionType See the Coremetrics documentation
	* @params {String} categoryID See the Coremetrics documentation
	* @params {String} points See the Coremetrics documentation
	* @params {Array|String} An arbitrary collection of additional data to pass along with the conversion event. Expected format is a specially formatted String. If an Array is passed in, the Array will be converted into a correctly formatted String.
	*/
	conversionEventTag : function(eventID, actionType, categoryID, points, attributes) {
		if(attributes && typeof attributes != 'string') attributes = attributes.join('-_-');
		cmCreateConversionEventTag(eventID, actionType, categoryID, points, attributes);
	},
	/**
	* Creates a page view tag.
	* Also handles queing the tag to be thrown at a later time.
	* Note: When throwing a tag with an options object, the options object does not have to be the 5th parameter to the function. The options object just needs to be the last parameter passed in. This method will correctly parse out the object from the arguments list.
	* @function
	* @params {String} pageID The name of the tag to throw
	* @params {String} categoryID See the Coremetrics documentation
	* @params {String} searchString See the Coremetrics documentation
	* @params {String} searchResults See the Coremetrics documentation
	* @params {Object} options An object containing additional options to control how the tag is thrown
	* @example
	* Usage:
	* CI.util.pageViewTag('myTag') // Throws the CM tag 'myTag'
	* CI.util.pageViewTag('myTag', { after:'startTag' }) // Throws the CM tag 'myTag' only after another tag, 'startTag', has been thrown.
	* CI.util.pageViewTag('startTag') // Throws the CM tag 'startTag' and the queued tag 'myTag'
	*
	* If a tag is to be queued off another tag that has already been thrown, the queued tag will be immediately thrown.
	* For example:
	* CI.util.pageViewTag('masterTag') // Throws the CM tag 'masterTag'
	* CI.util.pageViewTag('childTag', { after:'masterTag' }) // Since 'masterTag' has already been thrown, 'childTag' is thrown immediately
	*/
	pageViewTag : function() {
		/**
		* Contains a list of tags that are awaiting creation based upon the throwing of another tag.
		* The object key is the tag name to look wait for before throwing the queued tags ("master tag")
		* The object value is an array of tag parameters to use to create new page view tags ("child tag")
		* @private
		* @type Object
		*/
		var _TAG_QUEUES = {},
		/**
		* A collection of thrown tags to keep track of so that queued tags don't wait around forever.
		* @type Array
		*/
		_THROWN_TAGS = [];
		return function(pageID, categoryID, searchString, searchResults, options) {
      if(typeof pageID != 'string' && pageID.length > 0) {
        if(pageID.length > 1) {
          cmStartTagSet();
        }
        for(var i = 0; i < pageID.length; i++) {
          this.pageViewTag.apply(this, (typeof pageID[i] == 'string') ? [pageID[i]] : pageID[i]);
        }
        if(pageID.length > 1) {
          cmSendTagSet();
        }
        return;
      }

			options = options || {};
			// Find the options object in the arguments list (it should always be the last parameter)
			var args = Array.prototype.slice.call(arguments, 0).reverse();
			if(typeof args[0] == 'object') {
				options = args.shift() || {}; // Handles args[0] being NULL;
			}
			args.reverse();

			// Handle tag queueing
			if(options.after) {
				// If the dependent tag has not been thrown yet, queue it
				if(_THROWN_TAGS.indexOf(options.after) == -1) {
					// If the tag queue does not exist for the desired master tag, then create it
					if(_TAG_QUEUES[options.after] == undefined) _TAG_QUEUES[options.after] = [];
					return _TAG_QUEUES[options.after].push(args);
				}
			}

			// If we are not queuing the tag or the master tag has already been thrown, then throw the tag normally
			cmCreatePageviewTag.apply(this, args);

			// Mark the tag as being thrown
			if(_THROWN_TAGS.indexOf(pageID) == -1) _THROWN_TAGS.push(pageID);

			// Check to see if there are any queued tags awaiting this pageID to be thrown and throw them
			if(typeof _TAG_QUEUES[pageID] == 'object') {
				this.pageViewTag.apply(this, _TAG_QUEUES[pageID]);
				delete _TAG_QUEUES[pageID];
			}
		}
	}(),
	/**
	* Creates a Shop Action 5 Tag
	*/
	createShopAction5Tag : function(productID,productName,productQuantity,productPrice,categoryID,attributes) {
		cmCreateShopAction5Tag.apply(this, arguments);
	},
	/**
	* Displays the Shop Action 5 Tags
	*/
	displayShop5s : function() {
		cmDisplayShop5s();
	}
};
