function addLoadEvent(func) {
  var oldonload = window.onload;
  if (typeof window.onload != 'function') {
    window.onload = func;
  } else {
    window.onload = function() {
      if (oldonload) {
        oldonload();
      }
      func();
    }
  }
}

    
    
// this will be used to generate the addresses of XHRs.
var documentHref = new String( document.location.href );
var index = ( documentHref.indexOf( "/class/edit/" ) == -1 ) ? documentHref.indexOf( "/class/view/" ) : documentHref.indexOf( "/class/edit/" ) ;
if ( index )
{
	serverRoot = documentHref.slice( 0, ++index );
} 
// list of all class lavel mappings available. This list should mirror ezexalead.ini[PushAPISettings].ClassLevelMetaNames
var classLevelMappings = new Array( 'summary', 'date' );
var classLevelprefix = 'ContentClass_ezexalead_classlevel_meta_';
// is used to workaround the problem of manipulating the DOM of these drop downs while it is not fully loaded yet
var classLevelLoaded = false;


if (window.addEventListener){
	window.addEventListener("load", provideMappingInterface, false );
} else if (window.attachevent) {
	window.attachevent("onload", provideMappingInterface );
} else {
	addLoadEvent( provideMappingInterface );
	// window.onload=provideMappingInterface;
}

function watchChecked( event )
{
	// onchange event is not properly recognized in IE --> usage of onpropertychange.
	// Secondly, the Event object in IE does not have the same properties as in FF/NS, hence the line below.
	var checkbox = ( event.type == 'propertychange' ) ? event.srcElement :  event.target;
	if ( checkbox.checked )
	{
		appendMappingInterface( checkbox );
		revealAttributeInClassLevelMappingInterface( checkbox );		
	}
	else
	{
		removeMappingInterface( checkbox );
		hideAttributeFromClassLevelMappingInterface( checkbox );		
	}
}

function provideMappingInterface()
{
	var isExplorer = ((navigator.userAgent.toLowerCase().indexOf('msie')!=-1) && (navigator.userAgent.toLowerCase().indexOf('opera') == -1)) ? true : false;
	
	// load mapping interface in edtition mode only during class edition
	if ( documentHref.indexOf( "/class/edit/" ) != -1 )
	{
		var inputs = document.getElementById('ClassEditForm').getElementsByTagName('input');
		initClassLevelMappings( inputs, isExplorer );		
		initCheckboxes( inputs, isExplorer );
		initActionButtons( inputs, isExplorer );
		initRemoveButton( inputs, isExplorer );
	}
	// if viewing the class, display the already established mapping if existing
	else if( documentHref.indexOf( "/class/view/" ) != -1 )
	{
		displayMapping();
		initClassLevelMappings( inputs, isExplorer, 'view' );
	}
}

function initClassLevelMappings( inputs, isExplorer, mode )
{
	var controlBarDiv = YAHOO.util.Dom.getElementsByClassName( 'controlbar' , 'div' , document );
	
	// first retrieve any content class attribute ID
	var testMethod = ( mode == 'view' ) ? isViewAttributeRowHeader : isEditAttributeRowHeader;
	var elements = YAHOO.util.Dom.getElementsBy( testMethod, 'th', document );
	if ( elements.length > 0 )
	{
		var content = new String( elements[0].innerHTML );
			
		if ( content.search( /\(id:/g ) >= 0 )
		{
			var contentClassAttributeID = content.slice( content.search( /\(id:/g ) + 4, content.length - 1  );
		}
		
		for( var i = 0; i < classLevelMappings.length ; i++ )
		{
			var serverURL = serverRoot + "ezexalead/metatypes/" + contentClassAttributeID + "/(meta_category)/" + classLevelMappings[i];
			if ( mode == 'view' )
			{
				serverURL += "/(mode)/view/";
			}
			var serverURL = encodeURI( serverURL );
					
			var handleSuccess = function( o ){ 
			    if( o.responseText !== undefined )
			    {
			    	var textdiv = document.createElement( "div" );
			    	textdiv.innerHTML += "" + o.responseText;
			    	YAHOO.util.Dom.insertBefore( textdiv , YAHOO.util.Dom.getFirstChild( controlBarDiv[0] ) );
			    	if ( i == classLevelMappings.length )
			    	{
			    		classLevelLoaded = true;
			    	}
			    }
			}
			
			var handleFailure = function(o){
				if( o.responseText !== undefined ){}
			}
			
			var callback =
			{
			  success:handleSuccess,
			  failure:handleFailure
			};
			
			var request = YAHOO.util.Connect.asyncRequest( 'GET', serverURL, callback );
		}
	}
}

function initRemoveButton( inputs, isExplorer )
{
	for (var i = 0; i < inputs.length; i++)
	{
		var name = new String( inputs[i].name );
	    if ( inputs[i].type == 'submit' &&  ( inputs[i].name == 'RemoveButton' ) ) 
	    {
	    	YAHOO.util.Event.addListener( inputs[i], "click", removeMapping );
	    }
	}
}

function displayMapping()
{
	YAHOO.util.Dom.getElementsBy( isViewAttributeRowHeader, 'th', document, fetchMappingForDisplay );
}

function fetchMappingForDisplay( element )
{
	var content = new String( element.innerHTML );
	if ( content.search( /\(id:/g ) >= 0 )
	{
		var classAttributeID = content.slice( content.search( /\(id:/g ) + 4, content.length - 1  );
		var serverURL = encodeURI( serverRoot + "ezexalead/metatypes/" + classAttributeID + "/(mode)/view" );
		
		var handleSuccess = function( o ){ 
		    if( o.responseText !== undefined )
		    {
		    	element.innerHTML += " " + o.responseText;
		    }
		}
		
		var handleFailure = function(o){
			if( o.responseText !== undefined ){
				element.innerHTML += " " + "Error in retrieving mapping";
			}
		}
		
		var callback =
		{
		  success:handleSuccess,
		  failure:handleFailure
		};
		var request = YAHOO.util.Connect.asyncRequest('GET', serverURL, callback );
	}	
}

// identifies if the element is the class attribute table header
function isViewAttributeRowHeader( element )
{
	if( typeof( element.getAttribute( 'colspan' )) == "number" || element.hasAttribute( 'colspan' )  )
	{
		if( element.getAttribute( 'colspan' ) == 3 )
		{
			return true;
		}
	}
	return false;
}

function isEditAttributeRowHeader( element ) 
{ 
	if( typeof( element.getAttribute( 'className' )) == "string" || element.hasAttribute( 'class' )  )
	{
		if( element.getAttribute( 'className' ) == "wide" || element.getAttribute( 'class' ) == "wide" )
		{
			return true;
		}
	}
	return false;
}

function initCheckboxes( inputs, isExplorer  )
{
	var checkboxes = new Array();
	for (var i = 0; i < inputs.length; i++)
	{
	    if (inputs[i].type == 'checkbox' && inputs[i].name == 'ContentAttribute_is_searchable_checked[]')
	    {
	        if( isExplorer == false )
			{
				inputs[i].onchange = watchChecked;
				// need to trigger the event manually here, while IE does it automatically at page load.
  				var evt = document.createEvent( "HTMLEvents" );
				evt.initEvent( 'change',false, false );
				inputs[i].dispatchEvent(evt);
	        }
	        else
	        {
	        	inputs[i].onpropertychange =  function(){ watchChecked( event ); };
	        }
	    }
	}
}

function initActionButtons( inputs, isExplorer )
{
	var buttons = new Array();
	for (var i = 0; i < inputs.length; i++)
	{
		var name = new String( inputs[i].name );
	    if ( ( inputs[i].type == 'image' &&  ( name.search( /Move/g ) >= 0 )) || ( inputs[i].name == 'RemoveButton' ) || ( inputs[i].name == 'NewButton' ) || ( inputs[i].name == 'ApplyButton' ) ) 
	    {
	    	YAHOO.util.Event.addListener( inputs[i], "click", storeMapping, '' );
	    }
	    if ( inputs[i].name == 'StoreButton'  )
	    {
	    	YAHOO.util.Event.addListener( inputs[i], "click", storeMapping, 'and_publish' );
	    }
	    if ( inputs[i].name == 'DiscardButton'  )
	    {
	    	YAHOO.util.Event.addListener( inputs[i], "click", storeMapping, 'and_discard' );
	    }
	}	
}

function storeMapping( e, additional_action )
{
	// 'this' represents the DOM element on which the event was performed.
	//alert(  this.name + ' was clicked' );
	if ( additional_action != '' )
	{
		additional_action = '/' + additional_action;
	}
	
	// retrieve any class attribute ID
	var elements = YAHOO.util.Dom.getElementsBy( isEditAttributeRowHeader, 'th', document );
	if ( elements.length > 0 )
	{
		var content = new String( elements[0].innerHTML );
			
		if ( content.search( /\(id:/g ) >= 0 )
		{
			var contentClassAttributeID = content.slice( content.search( /\(id:/g ) + 4, content.length - 1  );
		}
	
	
		var selects = document.getElementsByTagName( 'select' );
		var serverURL = encodeURI( serverRoot + "ezexalead/storemapping" + additional_action + "/(class_attribute_id)/" + contentClassAttributeID );
		var postData = "";
		
		for ( var i = 0; i < selects.length; i++ )
		{
			var name = new String( selects[i].name );
			if ( name.search( /ContentClass_ezexaleadmeta/g ) >= 0 || name.search( /ContentClass_ezexalead_classlevel_meta/g ) >= 0 )
			{
				postData +=	selects[i].name + '=' + selects[i].options[ selects[i].selectedIndex ].value + '&'; 
			}				
		}
		postData = encodeURI( postData );
		
		var handleSuccess = function(o){
			/* if(o.responseText !== undefined){ alert('success !'); } */
		}
	
		var handleFailure = function(o){
			/*if(o.responseText !== undefined){ alert('failure !'); }*/
		}
		
		var callback =
		{
		  success:handleSuccess,
		  failure:handleFailure
		};
		var request = YAHOO.util.Connect.syncRequest( 'POST', serverURL, callback, postData ); 
	}
}

function removeMapping( e )
{
	YAHOO.util.Dom.getElementsBy( isRemoveCheckbox, 'input', document, processMappingRemoval );
}

function isRemoveCheckbox( element )
{
	if( typeof( element.getAttribute( 'name' )) == "string" || element.hasAttribute( 'name' )  )
	{
		if( ( element.getAttribute( 'name' ) == 'ContentAttribute_id_checked[]' ) && element.checked == true )
		{
			return true;
		}
	}
	return false;
}

function processMappingRemoval( element )
{
	console.log( 'removing mapping' );
	var contentClassAttributeID = element.value;
	var serverURL = encodeURI( serverRoot + "ezexalead/removemapping/" + contentClassAttributeID );
	
	var handleSuccess = function( o ){ 
	    if( o.responseText !== undefined )
	    {
	    }
	}
	
	var handleFailure = function(o){
		if( o.responseText !== undefined )
		{
	    }
	}
	
	var callback =
	{
	  success:handleSuccess,
	  failure:handleFailure
	};
	
	var request = YAHOO.util.Connect.syncRequest('GET', serverURL, callback );
}

function appendMappingInterface( checkbox )
{
	var attributeCell = checkbox.parentNode.parentNode.parentNode;
	var inputs = attributeCell.getElementsByTagName('input');
	var contentClassAttributeID = -1;
	
	for (var i = 0; i < inputs.length; i++)
	{
	    if (inputs[i].type == 'hidden' && inputs[i].name == 'ContentAttribute_id[]')
	    {
			contentClassAttributeID = inputs[i].value;    	
	    	break;
	    }
	}
	
	var mappingInterfaceDiv = document.createElement( "div" );
	mappingInterfaceDiv.setAttribute("id", "ezexalead_mapping_interface[]");	
	var serverURL = encodeURI( serverRoot + "ezexalead/metatypes/" + contentClassAttributeID );
	
	var handleSuccess = function( o ){ 
	    if( o.responseText !== undefined )
	    {
	    	var textdiv = document.createElement( "div" );
	    	textdiv.innerHTML += "" + o.responseText;
			mappingInterfaceDiv.appendChild( textdiv );
			attributeCell.appendChild( mappingInterfaceDiv );
	    }
	}
	
	var handleFailure = function(o){
		if( o.responseText !== undefined ){
	    	var textdiv = document.createElement( "div" );
	    	textdiv.innerHTML += "<em>Error in retrieving available meta data types</em>";
			mappingInterfaceDiv.appendChild( textdiv );
			attributeCell.appendChild( mappingInterfaceDiv );
		}
	}
	
	var callback =
	{
	  success:handleSuccess,
	  failure: handleFailure
	};
	
	var request = YAHOO.util.Connect.asyncRequest('GET', serverURL, callback);
}

function removeMappingInterface( checkbox )
{
	var attributeCell = checkbox.parentNode.parentNode.parentNode;
	var childrenDivs = attributeCell.getElementsByTagName("div");
	for (var i = 0; i < childrenDivs.length; i++)
	{
		if( childrenDivs[i].id == 'ezexalead_mapping_interface[]' )
		{
			childrenDivs[i].parentNode.removeChild( childrenDivs[i] );
		}
	}
}

function revealAttributeInClassLevelMappingInterface( checkbox )
{
	// @TODO : handle the 'selected' attribute
	if ( classLevelLoaded == true )
	{
		for( var i = 0; i < classLevelMappings.length ; i++ )
		{
			var select = document.getElementById( classLevelprefix + classLevelMappings[i] );
			if ( typeof(select.length) != 'undefined' )
			{
				// create a new option with the approriate value
				var newOption = document.createElement( "option" );
				newOption.setAttribute( "value", checkbox.value );
				var ancestorRow = YAHOO.util.Dom.getAncestorByTagName( checkbox , 'tr' );
				
				var nameAttribute = YAHOO.util.Dom.getElementsBy( function( element ){ 
																	if( typeof( element.getAttribute( 'name' )) == "string" || element.hasAttribute( 'name' )  )
																	{
																		if ( ( element.getAttribute( 'name' ) == 'ContentAttribute_name[]' ) )
																		{
																			return true;
																		}
															  		}
															  		return false;
															  	 }, 
											  'input', 
											  ancestorRow 
											  ); 
				newOption.innerHTML = nameAttribute[0].value + ' (' + checkbox.value + ')';
				if ( select.length > 0 )
				{
					YAHOO.util.Dom.insertAfter( newOption , select.options[ select.length -1  ] );
				}
				else
				{
					select.appendChild( newOption );
				}
			}
		}
	}	
}

function hideAttributeFromClassLevelMappingInterface( checkbox )
{
	// @TODO : move the 'selected' attribute to another option if the removed one was selected
	if ( classLevelLoaded == true )
	{
		for( var i = 0; i < classLevelMappings.length ; i++ )
		{
			var select = document.getElementById( classLevelprefix + classLevelMappings[i] );
			if ( select.length > 0 )
			{
				for( var j = 0; j < select.options.length; j++ )
				{
					if ( select.options[j].value == checkbox.value )
					{
						select.removeChild( select.options[j] );
						break;
					}
				}
			}
		}
	}
}

YAHOO.namespace('ezexalead'); 
YAHOO.ezexalead.YUIConnectExtension = function () {

    // public methods
    return {
		/**
		 * @description Method for initiating a synchronous request via the XHR object.
		 * @method syncRequest
		 * @public
		 * @static
		 * @param {string} method HTTP transaction method
		 * @param {string} uri Fully qualified path of resource
		 * @param {callback} callback User-defined callback function or object
		 * @param {string} postData POST body
		 * @return {object} Returns the connection object
		 */ 
        syncRequest : function ( method, uri, callback, postData ) {
			var o = (this._isFileUpload)?this.getConnectionObject(true):this.getConnectionObject();
		
			if(!o){
				YAHOO.log('Unable to create connection object.', 'error', 'Connection');
				return null;
			}
			else{
		
				// Intialize any transaction-specific custom events, if provided.
				if(callback && callback.customevents){
					this.initCustomEvents(o, callback);
				}
		
				if(this._isFormSubmit){
					if(this._isFileUpload){
						this.uploadFile(o, callback, uri, postData);
						return o;
					}
		
					// If the specified HTTP method is GET, setForm() will return an
					// encoded string that is concatenated to the uri to
					// create a querystring.
					if(method.toUpperCase() == 'GET'){
						if(this._sFormData.length !== 0){
							// If the URI already contains a querystring, append an ampersand
							// and then concatenate _sFormData to the URI.
							uri += ((uri.indexOf('?') == -1)?'?':'&') + this._sFormData;
						}
						else{
							uri += "?" + this._sFormData;
						}
					}
					else if(method.toUpperCase() == 'POST'){
						// If POST data exist in addition to the HTML form data,
						// it will be concatenated to the form data.
						postData = postData?this._sFormData + "&" + postData:this._sFormData;
					}
				}
					
				// a 'false' value here as 3rd parameter makes this XHR synchronous, meaning that the script will not be processed on until the XHR is completed
				o.conn.open(method, uri, false );
				//this.processTransactionHeaders(o);
		
				// Each transaction will automatically include a custom header of
				// "X-Requested-With: XMLHttpRequest" to identify the request as
				// having originated from Connection Manager.
				if(this._use_default_xhr_header){
					if(!this._default_headers['X-Requested-With']){
						this.initHeader('X-Requested-With', this._default_xhr_header, true);
						YAHOO.log('Initialize transaction header X-Request-Header to XMLHttpRequest.', 'info', 'Connection');
					}
				}
		
				if(this._isFormSubmit || (postData && this._use_default_post_header)){
					this.initHeader('Content-Type', this._default_post_header);
					YAHOO.log('Initialize header Content-Type to application/x-www-form-urlencoded for POST transaction.', 'info', 'Connection');
					if(this._isFormSubmit){
						this.resetFormState();
					}
				}
		
				if(this._has_default_headers || this._has_http_headers){
					this.setHeader(o);
				}
		
				this.handleReadyState(o, callback);
				o.conn.send(postData || null);
		
				// Fire global custom event -- startEvent
				this.startEvent.fire(o);
		
				if(o.startEvent){
					// Fire transaction custom event -- startEvent
					o.startEvent.fire(o);
				}
		
				return o;
			}
        }
    }
}(); // Execute the function, returning the object literal

// Augment YAHOO.util.Connect with the YUIConnectExtension methods
YAHOO.lang.augmentObject(
    YAHOO.util.Connect,
    YAHOO.ezexalead.YUIConnectExtension );