/**
 * Marketplace Namespace. All Marketplace specific classes will extend
 * this Namspace in order to avoid namspace conflicts with other libraries
 * on Adobe.com
 */
adobe.marketplace = function(){};

//CONSTANTS
/**
 * Address for AJAX requests
 */
adobe.marketplace.AJAXURL = "/cfusion/marketplace/remote/uiWidgetsService.cfc";

//GLOBAL LOAD EVENTS
document.observe("dom:loaded",function(){
	/* Hide any elements with a class of "initialHide" */
	$$('.initialHide').each(function(item){
		item.style.display="none";
		item.removeClassName('initialHide');
	});
	
	/* Resize HTML alt/non-sIFR text for publisher name */
	if (!($$('html')[0].hasClassName('sIFR-hasFlash'))) {
		$$('.pubName').each(function(item){
			item.style.fontSize = '12px';
		})
	}
	
	/* add counters to all textarea's with a maxlength attribute */
	//$$('textarea').each(function(inputelem){
		adobe.marketplace.CountdownTextareaManager.getInstance().findNew();
		//new adobe.marketplace.CountdownTextarea(inputelem);
	//});
});

//OBJECT CLASSES
/**
 * Class for creating Generic Data Objects for storing data
 * @constructor
 */
adobe.marketplace.DataObject = Class.create({
	/**
	 * Initializes Data Object
	 */
	initialize: function(){

	},
	/**
	 * Prepares and provides data formatted for submssion via POST or GET
	 * @return String of formatted data.
	 * @type String
	 */
	getQueryString: function(){
		// Function included for potential future use
		// Perhaps use DO id as identifier in each field?
		// example: "IDsomefield=somefieldValue&IDsomeotherfield=someotherfieldValue&..."
		// or use prototype's toJSON() method
//		var returnStr = "";
//		for(prop in this){
//			if (this.hasOwnProperty(prop)) {
//		  	returnStr += (returnStr != "") ? "," : "";
//		  	returnStr += '"' + prop + '":"' + this[prop] + '"';
//		  }
//		}
//		returnStr = "{"+returnStr+"}";
//		return returnStr;
	}
});

/**
 * Mixin for adding form text field default text clearing/replacement on focus/blur.
 *
 * @param {Object} inputField Text input html element.
 */
adobe.marketplace.InputClearMixin = {
	setupInputClear: function(inputField){

		this.replaceText = inputField.value;
		Event.observe(inputField,'focus',function(){
			inputField.value = (inputField.value == this.replaceText) ? "" : inputField.value;
		}.bind(this,inputField));
		Event.observe(inputField,'blur',function(){
			inputField.value = (inputField.value == "") ? this.replaceText : inputField.value;
		}.bind(this,inputField));
	}
}
/**
 * Generic input field object with InputClearMixin mixed in.
 */
adobe.marketplace.InputClear = Class.create(adobe.marketplace.InputClearMixin,{
	initialize: function(){

	}
});
/**
 * Find all textareas and input[type="text"] fields with a maxlength set and create user feedback for remaining character count
 * Lazy instantiated singleton
 * @see adobe.marketplace.CountdownTextarea()
 */
adobe.marketplace.CountdownTextareaManager = (function(){
	var _instance = null; //Singleton storage
	var _textAreas = new Array(); //Storage for observed _textAreas
	return {
		// singleton instance retriever
		getInstance: function(){
			// if singleton hasn't been created, initialize, else return instance.
			if(!_instance){
				_instance = new (Class.create({		
					// create counter for input element
					makeCounter: function(inputelem){
						// check to see if the input element has already been processed.
						if (!$A(_textAreas).find(function(txtArea){
							return txtArea.elem == inputelem;
						})) {
							// Create CountdownTextarea counter
							var _counter = new adobe.marketplace.CountdownTextarea(inputelem);
							// Store input reference and counter reference
							_textAreas.push({
								"elem" : inputelem,
								"counter" : _counter
							});
						} else {
							//Element has already been processed, so it may need to be updated
							$A(_textAreas).find(function(txtArea){return txtArea.elem == inputelem;}).counter.update();
						}
					},
					/**
					 * Locate all elements to make counters for
					 * @param {Element} targetElem Optional When present will limit the scope of findNew to the targetElem.  Default is entire document
					 */
					findNew: function(targetElem){
						// Get all textareas
						var _targetElemTextAreas = ($(targetElem)) ? $(targetElem).select('textarea') : $$('textarea');
						_targetElemTextAreas.each(function(inputelem){
							this.makeCounter(inputelem);
						}.bind(this));
						// Get all input[type="text"]
						var _targetElemTextInputs = (targetElem) ? $(targetElem).select('input[type="text"]') : $$('input[type="text"]');
						_targetElemTextInputs.each(function(inputelem){
							this.makeCounter(inputelem);
						}.bind(this)); 
					}
				}))();//immediate execution
			}
			return _instance;
		}
	}
})();//immediate execution

adobe.marketplace.CountdownTextarea = Class.create({
	initialize: function(input){
		this.FEEDBACK_STRING = "Remaining: "; //Prepended string for user feedback
		if(!$(input).readAttribute('maxlength')) return; //max length not set, exiting
		if(parseFloat($(input).readAttribute('maxlength')) > 8000) return; //max length not set on a text input (defaults to large value in IE)
		this.input = $(input); // store input for future use
		this.max = parseFloat(input.readAttribute('maxlength')); // convert maxlength into a number for later math
		// Create DOMnode to show remaining characters
		this.counter = adobe.marketplace.createElem({
			"tag" : "SPAN",
			"attribs" : {
				"class" : "txtCounter"
			},
			"innerHTML" : this.FEEDBACK_STRING + this.max
		});
		$(this.input).insert({"after": this.counter}); //insert DOMnode after textfield being observed
		this.input.observe("keyup", function(){this.update()}.bind(this)); //update the counter on keyup
		this.update(); //call an update to ensure proper value displayed on an Edit state of form
	},
	update:  function(){
		try { // IE6 has proven to throw errors for some input fields, this does not affect functionality and therefore we can safely catch with no error.
			this.remainingChar = (this.max) - ($F(this.input).length); // Find out how many characters are left for the user
			if (this.remainingChar < 0) {
				//this.input.value = this.input.value.substring(0,this.max); // Force user to input no more than maxlength
				//this.remainingChar = this.max - (this.input.value.length); // correct remaining character count after force length
				//$(this.input).addClassName("tooLong");  //add class to input field for error state
				$(this.counter).addClassName("tooLong");  //add class to counter for error state
			}
			else {
				//$(this.input).removeClassName("tooLong");  //remove input field error state
				$(this.counter).removeClassName("tooLong");  //remove counter error state
			}
			$(this.counter).innerHTML = this.FEEDBACK_STRING + this.remainingChar; //update counter text
		}catch(e){
			return true; //fail silently
		}
	}
});

//UTILITY FUNCTIONS
/**
 * Generic style class swap.  Toggles between "-over" and "" suffix.
 * @param {Object} item2swap Object reference to toggle class on
 * @param {String} class2swap Class to swap (passed in to handle class overload situations)
 */
adobe.marketplace.swapOver = function(item2swap,class2swap){
	if(item2swap.hasClassName(class2swap)){
		item2swap.removeClassName(class2swap)
		item2swap.addClassName(class2swap + "-over");
		item2swap.style.cursor = "pointer";
	} else {
		item2swap.removeClassName(class2swap + "-over")
		item2swap.addClassName(class2swap);
	}
}
/**
 * Generic form submit call for use in standard sidebar component or other generic form controls.
 * Should be overwritten or onsubmit even captured, in the local scope if pre-submit logic necessary
 */
adobe.marketplace.formSubmit = function(){
	$('marketplaceForm').submit();
}
/**
 * Generic form reset call for use in standard sidebar component or other generic form controls.
 * Should be overwritten or onreset even captured, in the local scope if pre-reset logic necessary or
 * alternate confirm message desired
 */
adobe.marketplace.formReset = function(){
	if (confirm("Are you sure you want to discard all form edits?")) {
  	$('marketplaceForm').reset();
  }
}

adobe.marketplace.toggleDisplay = function(item2toggle){
	if (item2toggle) {
		item2toggle.style.display = (item2toggle.style.display == "none") ? "" : "none";
	}
}
adobe.marketplace.toggleLink = function(link2toggle){
	if(!link2toggle) return; //There's nothing to toggle - exiting
	if(Element.hasClassName(link2toggle,"disable")) {
  	link2toggle.onclick = link2toggle.oldClick;
		link2toggle.removeClassName("disable");
  } else {
  	var oldClick = document.createAttribute("oldClick");
  	if(!link2toggle.oldClick) link2toggle.setAttributeNode(oldClick);
  	link2toggle.oldClick = link2toggle.onclick;
  	link2toggle.onclick = function(){
  		return false;
  	};
  	link2toggle.addClassName("disable");
  }
}

adobe.marketplace.getUrlParam = function( name )
{
	name = name.toUpperCase();
  name = name.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");
  var regexS = "[\\?&]"+name+"=([^&#]*)";
  var regex = new RegExp( regexS );
	var href = window.location.href.toUpperCase();
  var results = regex.exec( href );
  if( results == null )
    return "";
  else
    return results[1];
}

/**
 * Utility method for creating DOMnodes
 * @param {ObjectLiteral} oblit Simple notation for creating element and setting desired attributes.  Example:
 * 	{
 * 		"tag" : "DIV", //Should be capitalized for IE support
 * 		"attribs" : {
 * 			"id" : "someID",
 * 			"class" : "someClass",
 * 			"etc" : "..."
 * 		},
 * 		"innerHTML" : "String content for inclusion in created element.  May contain <strong>html</strong>."
 * 	}
 */
adobe.marketplace.createElem = function(oblit){
	// Create Element
	var _newNode = document.createElement(oblit.tag);
	if(oblit.attribs){
	// Iterate attribs and create attributes with values
		for(var attrib in oblit.attribs){
			var _newAttrNode = document.createAttribute(attrib);
			_newAttrNode.nodeValue = oblit.attribs[attrib];
			_newNode.setAttributeNode(_newAttrNode);
		}
	}
	if(oblit.innerHTML){
		// Set innerHTML
		_newNode.innerHTML = oblit.innerHTML;
	}
	// Return newly created Element for insertion into DOM
	return _newNode;
}

/**
 * Redirect user to login, with return url set to current location.
 */
adobe.marketplace.login = function(){
	window.location.href = "/cfusion/entitlement/index.cfm?e=marketplace&returnUrl="+escape(window.location.href);
}


/***
 * Browser detection
 */
var BrowserDetect = {
	init: function () {
		this.browser = this.searchString(this.dataBrowser) || "An unknown browser";
		this.version = this.searchVersion(navigator.userAgent)
			|| this.searchVersion(navigator.appVersion)
			|| "an unknown version";
		this.OS = this.searchString(this.dataOS) || "an unknown OS";
	},
	searchString: function (data) {
		for (var i=0;i<data.length;i++)	{
			var dataString = data[i].string;
			var dataProp = data[i].prop;
			this.versionSearchString = data[i].versionSearch || data[i].identity;
			if (dataString) {
				if (dataString.indexOf(data[i].subString) != -1)
					return data[i].identity;
			}
			else if (dataProp)
				return data[i].identity;
		}
	},
	searchVersion: function (dataString) {
		var index = dataString.indexOf(this.versionSearchString);
		if (index == -1) return;
		return parseFloat(dataString.substring(index+this.versionSearchString.length+1));
	},
	dataBrowser: [
		{
			string: navigator.userAgent,
			subString: "Chrome",
			identity: "Chrome"
		},
		{ 	string: navigator.userAgent,
			subString: "OmniWeb",
			versionSearch: "OmniWeb/",
			identity: "OmniWeb"
		},
		{
			string: navigator.vendor,
			subString: "Apple",
			identity: "Safari",
			versionSearch: "Version"
		},
		{
			prop: window.opera,
			identity: "Opera"
		},
		{
			string: navigator.vendor,
			subString: "iCab",
			identity: "iCab"
		},
		{
			string: navigator.vendor,
			subString: "KDE",
			identity: "Konqueror"
		},
		{
			string: navigator.userAgent,
			subString: "Firefox",
			identity: "Firefox"
		},
		{
			string: navigator.vendor,
			subString: "Camino",
			identity: "Camino"
		},
		{		// for newer Netscapes (6+)
			string: navigator.userAgent,
			subString: "Netscape",
			identity: "Netscape"
		},
		{
			string: navigator.userAgent,
			subString: "MSIE",
			identity: "Explorer",
			versionSearch: "MSIE"
		},
		{
			string: navigator.userAgent,
			subString: "Gecko",
			identity: "Mozilla",
			versionSearch: "rv"
		},
		{ 		// for older Netscapes (4-)
			string: navigator.userAgent,
			subString: "Mozilla",
			identity: "Netscape",
			versionSearch: "Mozilla"
		}
	],
	dataOS : [
		{
			string: navigator.platform,
			subString: "Win",
			identity: "Windows"
		},
		{
			string: navigator.platform,
			subString: "Mac",
			identity: "Mac"
		},
		{
			string: navigator.platform,
			subString: "Linux",
			identity: "Linux"
		}
	]

};
BrowserDetect.init();
/**
*
*  AJAX IFRAME METHOD (AIM)
*  http://www.webtoolkit.info/
*
**/

AIM = {

    frame : function(c) {

        var n = 'f' + Math.floor(Math.random() * 99999);
        var d = document.createElement('DIV');
        d.innerHTML = '<iframe style="display:none" src="about:blank" id="'+n+'" name="'+n+'" onload="AIM.loaded(\''+n+'\')"></iframe>';
        document.body.appendChild(d);

        var i = document.getElementById(n);
        if (c && typeof(c.onComplete) == 'function') {
            i.onComplete = c.onComplete;
        }

        return n;
    },

    form : function(f, name) {
        f.setAttribute('target', name);
    },

    submit : function(f, c) {
        AIM.form(f, AIM.frame(c));
        if (c && typeof(c.onStart) == 'function') {
            return c.onStart();
        } else {
            return true;
        }
    },

    loaded : function(id) {
        var i = document.getElementById(id);
        if (i.contentDocument) {
            var d = i.contentDocument;
        } else if (i.contentWindow) {
            var d = i.contentWindow.document;
        } else {
            var d = window.frames[id].document;
        }
        if (d.location.href == "about:blank") {
            return;
        }

        if (typeof(i.onComplete) == 'function') {
					if (typeof(d.getElementById('response')) != 'undefined') {
						i.onComplete(d.getElementById('response').value);
					} else {
						i.onComplete(d.body.innerHTML);
					}
        }
    }

}