/*
 * A class responsible for the distribution of the HTML Elemente,serves also 
 * the  JS SDKs requests and  the requests to TYPO3 eID classes(asynchron).
 * Social Network == SN,Facebook == FB , Twitter == Tw
 * 
 * @param 	String   caller 		 the SN class name that need SN activity
 * @param 	JSON     dynCont 		 the options properties to be represented on certain events
 * @param 	JSON     statCont 	 	 the options properties to be represented static,on plugin rendering
 * @param 	JSON     commonCont 	 the common properties for each kind of option
 */
naviki.main.SNElementCoordinator=function(caller,dynCont,statCont,commonCont){
	/*
	 * the SN options that are to be represented static
	 */
	this.statCont = statCont;
	
	/*
	 * the SN options to be represented on certain events
	 */
	this.dynCont = dynCont;
	
	/*
	 * the SN properties common to dynamic and static options(Ex.:scope,SN label)
	 */
	this.commonCont = commonCont;
	
	/*
	 * the name of the class that need SN activity
	 */
	this.caller =caller;
	
	/*
	 * Events subscribe
	 */
	eventMgr.getLoginFacebook.subscribe(this.getLoginFacebook, this);
	eventMgr.getLoginTwitter.subscribe(this.getLoginTwitter, this);
	eventMgr.collectInput.subscribe(this.collectInput, this);
};


/*
 *Event handler that handles the dynamic representation of SN options
 */
naviki.main.SNElementCoordinator.prototype.representDynamic = function(type,e,me){
	for(var i=0 ;i < me.dynCont['opts'].length ; i++){
		//if the event configuration option is not uncommented
		if(type == me.dynCont['opts'][i]['event']){
			var parent_divs = me.dynCont['opts'][i]['plugins'][me.caller]['representation']['parent_divs'];
			for(var j=0,lngh=parent_divs.length ;j < lngh ; j++){
				var div_id = parent_divs[j];
				var tableBody = document.getElementById(div_id+'_tblBody');
				if(tableBody == null){
					me.buildTabel(div_id);
					tableBody = document.getElementById(div_id+'_tblBody');
				}
				var opt_tr = me.buildRow(me.dynCont['opts'][i]);
				tableBody.appendChild(opt_tr);
			}
		}
		
	}
};


/*
 * A method that handles the 'static' representation of the SN options.
 * Becouse the 'static' options will be rendered on plugin rendering,it doesn't need 
 * to act on certain events.
 */
naviki.main.SNElementCoordinator.prototype.representStatic = function(){
	for(var v=0,l=this.statCont['divs_unique'].length; v < l ; v++){
		var div_id = this.statCont['divs_unique'][v];
		for(var j=0,lng=this.statCont['opts'].length ; j < lng;j++){
			var opt = this.statCont['opts'][j];
			var rep_divs =opt['plugins'][this.caller]['representation']['parent_divs'];
			for(var k=0,lngh=rep_divs.length; k < lngh;k++){
				if(rep_divs[k] == div_id){
					var tableBody = document.getElementById(div_id+'_tblBody');
					if(tableBody === null){
						//if there is no table untill now ,then build new one
						this.buildTabel(div_id);
						tableBody = document.getElementById(div_id+'_tblBody');		
					}
					//add a rown to the existing or newly created table
					var opt_tr = this.buildRow(opt);
					tableBody.appendChild(opt_tr);
				}
			}
		}
	}
};

/*
 * Build the table, append the "Social Networks" label.DOM operations
 * @param String div_id  The div where the table will be rendered.
 */
naviki.main.SNElementCoordinator.prototype.buildTabel = function(div_id){
		var div_el = document.getElementById(div_id);
		var table = document.createElement('table');
		var tbody =document.createElement('tbody');
		var label_tr = document.createElement('tr');
		var label_th = document.createElement('th');
		var label = document.createElement('label');
		label_th.className ="nui-label";
		label_th.setAttribute('colSpan',6);
		var label_txt = document.createTextNode(this.commonCont['sn_label']+':');
		label_th.appendChild(label_txt);
		label_tr.appendChild(label_th);
		tbody.appendChild(label_tr);
		tbody.setAttribute('id',div_id+'_tblBody');
		table.appendChild(tbody);
		div_el.appendChild(table);
};




/*
 * Build a row in the table.
 */
naviki.main.SNElementCoordinator.prototype.buildRow = function(opt){
	var el = document.getElementById(opt['machine_name']);
	var caller_opt = opt['plugins'][this.caller];
	if(el !== null){
	  //the checkbox ,if element already there,dont need it twice
	  var parent = el.parentNode.parentNode.parentNode;
		for(var z = 0 , lng = caller_opt['representation']['parent_divs'].length; z < lng ;z++){
			if(parent.id == caller_opt['representation']['parent_divs'][z]+'_tblBody'){
				//there is already an element with this machine name(id) in this div
				return'';
			}
		}
	}
	
	// start creating new element
	var opt_tr 	= document.createElement('tr');
	var td_1 	= document.createElement('td');
	td_1.width 	= '15px';
	switch(caller_opt['representation']['type']){
		case"checkbox":{
			//represent it as checkbox
			var td_1_el 		= document.createElement('input');
			td_1_el.type		= 'checkbox';
			td_1_el.id   		= opt['machine_name'];
			td_1_el.value		= YAHOO.lang.JSON.stringify({'args':opt['parameters'][opt['sdk']]['args'],'elems':caller_opt['elems']});
			td_1_el.name		= "["+caller_opt['representation']['sn']+"]["+opt['key']+"]";//[Facebook][fb_wwowu][elems]
			td_1_el.className	= 'sn_opts';
			td_1_el.style.border = 'none';
			td_1_el.onclick		= function(){
										if(this.checked && opt['sdk'] == 'php'){
											switch(caller_opt['representation']['sn']){
												case'Facebook':eventMgr.getLoginFacebook.fire(this);break;
												case'Twitter':eventMgr.getLoginTwitter.fire(this);break;
											}
											if(opt['parameters'][opt['sdk']]['args'] == "user_defined"){
												eventMgr.collectInput.fire(this);
											}
										}
								};
			td_1.appendChild(td_1_el);
			opt_tr.appendChild(td_1);
			var td_2 			= document.createElement('td');
			var opt_text 		= document.createTextNode(caller_opt['representation']['text']);
			td_2.appendChild(opt_text);
			var usr_input 		= document.createElement('input');
			usr_input.type		= 'hidden';
			usr_input.name		= caller_opt['representation']['text'];
			usr_input.id		= opt['machine_name']+'_usrInput';
			usr_input.value		= YAHOO.lang.JSON.stringify(opt['parameters'][opt['sdk']]['arguments']);
			opt_tr.appendChild(usr_input);
			opt_tr.appendChild(td_2);
			break;
		}
		case"link":{
			//represent it as link,useful for usng the JS SDK
			var td_1_el 		= document.createElement('input');
			td_1_el.type 		= 'hidden';
			td_1_el.id   		= opt['machine_name'];
			td_1_el.value		= YAHOO.lang.JSON.stringify(caller_opt['elems']);
			td_1_el.name		= "["+caller_opt['representation']['sn']+"]["+opt['key']+"]";
			td_1_el.className	= 'sn_opts';
			td_1.appendChild(td_1_el);
			opt_tr.appendChild(td_1);
			var td_2 			= document.createElement('td');
			var td_2_el 		= document.createElement('a');

			td_2_el.id   		= opt['machine_name']+'_link';
			td_2_el.setAttribute('href',caller_opt['representation']['href']);
			var txt 			= document.createTextNode(caller_opt['representation']['text']);
			td_2_el.appendChild(txt);
			td_2.appendChild(td_2_el);
			var usr_input 		= document.createElement('input');
			usr_input.type		= 'hidden';
			usr_input.id		= opt['machine_name']+'_usrInput';
			usr_input.value		= YAHOO.lang.JSON.stringify(opt['parameters']['js']['arguments']);
			opt_tr.appendChild(usr_input);
			opt_tr.appendChild(td_2);
			break;
		}
	}
	// the last <td> is the SN icon
	var td_3 = document.createElement('td');
	var opt_img = document.createElement('img');
	opt_img.setAttribute('src','../../typo3conf/ext/naviki/pi_socialnetworks/static/icons/'+caller_opt['representation']['sn']+'.png');
	td_3.appendChild(opt_img);
	opt_tr.appendChild(td_3);
	opt_tr.appendChild(document.createElement('td'));
	
	return opt_tr;
};


/*
 * Handles the  JS SDK communication with the server.
 * Presents a dialog where user must always authenticate  himself.
 * @param String socNtwrk  the SN
 * @param String optKey The key that distinguishes this option from all the options for this SN
 * @param String dynStat  In which array is  the option - static or dynamic
 */
naviki.main.SNElementCoordinator.prototype.serveFBJSRequest= function(socNtwrk,optKey,dynStat){
	//temporary object for the option to be served.
	var toBeServed ={};
	switch(dynStat){
		case'dyn':
			for(var i = 0, lng = this.dynCont['opts'].length ; i < lng ; i++){
				var opt = this.dynCont['opts'][i];
				if(opt['key'] == optKey && opt['plugins'][this.caller]['representation']['sn'] == socNtwrk){
					toBeServed = opt;
				}
			}
			
			break;
		case'stat':
			for(var i = 0, lng = this.statCont['opts'].length ; i < lng ; i++){
				var opt = this.statCont['opts'][i];
				if(opt['key'] == optKey && opt['plugins'][this.caller]['representation']['sn'] == socNtwrk){
					toBeServed = opt;
				}
			}
			
			break;
	
	}
	
	/*
	 * prepare the option parameters.For every core api the options are others.
	 */
	var pars = this.getParsReadyJS(toBeServed);
	switch(toBeServed['parameters']['js']['core_api']){
	case'FB.ui':
		FB.ui(pars);
		break;
	case'FB.api':
		FB.api(pars);
	}	
};


/*
 * Prepares the SN option's parameters,for prepending to the query string,if the input is user defined
 * @param HTML-element element The HTML Element that represents the option and was selected from user
 * @param JSON values  An object with key-value properties that hold  the user input,
 * 						usually the parsed content of the '.._usrInput' div
 * @return String ret The concatenated string to be appended to the request string
 */
naviki.main.SNElementCoordinator.prototype.getParsReady= function(element,values){
	var ret = "";
	var obj = YAHOO.lang.JSON.parse(values);
	for(var val in obj){
		ret +="&SN"+element.name+"["+element.id+"][params]["+val+"]="+obj[val]['cont'];
	}
	return ret;
};



/*
 * Prepares the parameters for the request using the JS SDK of the social network.
 * Makes  replacements of the placeholders with user input if any and builds the method 
 * and arguments as expected from the SN for a given core api(FB.ui,FB.api..)
 * @param JSON element The JSON object that represents the SN option.
 * @return JSON ret  An object that tells the SN the method and its arguments  to be served . 
 */
naviki.main.SNElementCoordinator.prototype.getParsReadyJS= function(element){
	var ret = {};
	var replcmnts = {};
	var tmp_elem = element['plugins'][this.caller]['elems'];
	//collect the replacements for the elems in the arguments
	for(var elem in tmp_elem){
		if(tmp_elem[elem]['who'] == 'client'){
			var val;
			if(tmp_elem[elem]['id'].indexOf('window.location') >= 0){
				switch(tmp_elem[elem]['id']){
					case'window.location.host':
						val = window.location.host;
						break;
				}
			}else{
				val = document.getElementById(tmp_elem[elem]['id'])?document.getElementById(tmp_elem[elem]['id']).value:0;
			}
			replcmnts[tmp_elem[elem]['alias']] = val ;
		}
	}
	//method is always there
	ret['method'] = element['parameters']['js']['method'];
	//replace the elems in the arguments
	for(var parName in element['parameters']['js']['arguments']){
		if(parName == 'attachment'){
			//FB.ui stream.publish has the attachment under-array,deviation from rules
			ret['attachment']={};
			for(var attName in element['parameters']['js']['arguments']['attachment']){
				var content = element['parameters']['js']['arguments']['attachment'][attName]['cont'];
				if(content){
					//content is not empty == there is sth. to replace
					ret['attachment'][attName]='';
					for(var replc in replcmnts){
						var search = new RegExp(replc,"g");
						var replcd = content.replace(search,replcmnts[replc]);
						ret['attachment'][attName] = replcd ;
					}
				}
			}
		}else{
			//follow the scheme as given in option's configurations
			var content = element['parameters']['js']['arguments'][parName]['cont'];
			if(content != ""){
				//content is not empty == there is sth. to be replaced
				for(var replc in replcmnts){
					var search = new RegExp(replc,"g");
					if(content.indexOf(replc) >= 0){
						ret[parName] = content.replace(search,replcmnts[replc]);
						// an item has been replace, content has been changed,make replacements to the new content
						content		 = ret[parName];
					}
				}
			} 
			
		}
	}
	
	return ret;
};
/*
 * This method checks the SN options the user has just selected,forms a parameter string
 * and returns it.This string will be later append to the query string.
 * @return String res  A string with the selected options for esch SN
 * 			   in the form : &SN[Facebook][N]['mach_name'][n]='value'&SN[Twitter][N]['mach_name'][n]='value'...
 * 			   Where 'N' is the numeric index of this option in the given SN options-array(setup.txt)
 * 				and  'n' is the numeric index of the element in the elems array,that is the element that is to be
 * 						replaced with user input,
 * 				and 'value' is the "replace with" value.
 */
naviki.main.SNElementCoordinator.prototype.getSelectedSNOpts= function(){
		
		//the parameters string to add to query string
		var res 		="";
		//temporary string that will be worked with
		var st			="";
		//all DOM input elements
		var elements 	= document.getElementsByTagName("input");
		var lngth 		= elements.length;
		var inputs 		= '';
		//var nativeVars  = new Array();
	
		for(var i = 0 ; i < lngth ; i++){
			if(elements[i].className == "sn_opts" && elements[i].checked){
				// it is an SN option and user has selected it
				st 	+= "&SN"+elements[i].name+"="+elements[i].id;
				// the elems array from the configuration options(setup.txt)
				var elems = YAHOO.lang.JSON.parse(elements[i].value);
				if(elems['args'] == "user_defined"){
					//according to configuration this argument is user-defined,so find the value
					var hid = document.getElementById(elements[i].id+'_usrInput');
					st += this.getParsReady(elements[i],hid.value);
				}
				
				var wayIdEl = document.getElementById(this.caller+'[uid]');
				//wayId not of interest
				var wayID = -1;
				if(wayIdEl != null){
					wayID = wayIdEl.value;
				}
				st  +="&SN"+elements[i].name+"["+elements[i].id+"][wayID]="+wayID;
		
				for(var key in elems['elems']){
					if(elems['elems'][key]['who'] == 'client'){
							switch(elems['elems'][key]['type']){
								case'tbody':{
									//the value source is a table,collect the info from all rows
									var div_parent = document.getElementById(elems['elems'][key]['id']);
									if(div_parent){
										var trs = div_parent.children;
										var tmp_inp="";
										for(var k = 0 ,lngk = trs.length; k < lngk ; k++){
											var td = trs[k].children;
											var input = td[0];
										    tmp_inp += input.value;
										    tmp_inp += (k == lngk-1)?'':',';
										}
									}
									break;
								}
								case'input':{
									//the value source is an input element
									var div_parent = document.getElementById(elems['elems'][key]['id']);
									var tmp_inp = div_parent.value;
									break;
								}
//								case'location':{
//									if(elems['elems'][key]['id'] == "lat"){
//										var pos = window.location.href.indexOf('lat=');
//										if(pos >= 0){
//											var lat = window.location.href.substr(pos+4,8);
//											var tmp_inp = lat;
//										}
//									}
//									if(elems['elems'][key]['id'] == "lon"){
//										var pos = window.location.href.indexOf('lon=');
//										if(pos >= 0){
//											var lon = window.location.href.substr(pos+4,8);
//											var tmp_inp = lon;
//										}
//									}
//									//var tmp_inp = window.location.href;
//									break;
//								}
								case'adPars':
									//value source are additional parameters from the JS class that
									//uses the global el_coord object,usually for asynchron requests
									var tmp_inp = elems['elems'][key]['id'];
									break;
							}
							st += "&SN"+elements[i].name+"["+elements[i].id+"]["+key+"]="+tmp_inp;
						}
					
				}
			}
		}
		res+= st;
		
	return res;
	
};


/*
 * Checks Twitter login status using cookies
 * @return boolean true if user is logged in and  false otherwise
 */
naviki.main.SNElementCoordinator.prototype.checkTwitterLoginStatus = function(){
	if(document.cookie.indexOf('oauth_token') < 0 || document.cookie.indexOf('oauth_token_secret') < 0){
		return false;
	}else{
		return true;
	}
};

/*
 * Checks Facebook login status,using cookies
 * @return boolean true if user is logged in and  false otherwise
 */
naviki.main.SNElementCoordinator.prototype.checkFacebookLoginStatus = function(){

		if(document.cookie.indexOf('fbs_') < 0){
			 return false;
		}else{
			 return true;
		}
};

/*
 * Event Handler: Gets the Twitter login dialog on certain events.
 */
naviki.main.SNElementCoordinator.prototype.getLoginTwitter = function(type,e,me){
	
// with the @anywhere js library of twitter
//	twttr.anywhere(function (T){
//		if (T.isConnected()){
//			eventMgr.checkTwitterStatus.unsubscribe(me.checkTwitterStatus);
//		}else {
//		    //eventMgr.checkTwitterStatus.unsubscribe(me.checkTwitterStatus);
//		    T.signIn();
//		  
//		}
//	});
	
	if(!me.checkTwitterLoginStatus()){
		//OAuth 1.0,asynchron request for authorization
		var addr ='http://'+window.location.host+'/index.php?eID=tx_naviki_pi_socialnetworks&auth=Twitter&caller='+me.caller;
	    var  fenster = window.open(addr,"TwitterAuth","top=200,left=300,width=750,height=400,status=yes");
	    //user logged in,unsubscribe
	    eventMgr.checkTwitterStatus.unsubscribe(me.checkTwitterStatus);
	}
};


/*
 * Event Handler: Gets the Facebook login dialog on certain events.
 * 				  Uses the Facebook JS SDK.
 */
naviki.main.SNElementCoordinator.prototype.getLoginFacebook = function(type,e,me){
//	/**
//	 * Bug found with Facebook Connect as with 18.08.2010, many reposrt on http://forum.developers.facebook.net
//	 *  Use this workaround till Bugfix.
//	 */
//	if(!me.checkFacebookLoginStatus())
//	FB.login(function(response) {
//        if (response.status == 'connected') {
//            FB.getLoginStatus(function(response) {
//                if (response.session) {
//                	eventMgr.getLoginFacebook.unsubscribe(me.getLoginFacebook);
//                    if (response.perms) {
//                        // user is logged in and granted some permissions.
//                        // perms is a comma separated list of granted permissions
//                    } else {
//                        // user is logged in, but did not grant any permissions
//                    }
//                } else {
//                    // user is not logged in
//                }
//            }, true);
//        } else {
//            // user is not logged in
//        }
//    }, {perms:me.commonCont['Facebook']['app_cred']['scope']});


	FB.getLoginStatus(function(response){
						if (response.session) {
							 eventMgr.getLoginFacebook.unsubscribe(me.getLoginFacebook);
						}else{
					 
					//if(!me.checkFacebookLoginStatus()){
							//here with cookie 
							FB.login(function(response){
								  if (response.session) {
								    // user successfully logged in
									  eventMgr.getLoginFacebook.unsubscribe(me.getLoginFacebook);
								  } else {
								    // user cancelled login
									  eventMgr.getLoginFacebook.subscribe(me.getLoginFacebook);
								  }
								},{perms:me.commonCont['Facebook']['app_cred']['scope']});
					//	}
		}
	});
					
	FB.Event.subscribe('auth.login', function() {
		  eventMgr.getLoginFacebook.unsubscribe(me.getLoginFacebook);
    });
	FB.Event.subscribe('auth.logout', function() {
		  eventMgr.getLoginFacebook.subscribe(me.getLoginFacebook);
      });

};

/*
 * If values are user-defined as specified in the setup.txt,then the user input should be collected.
 * This function does this in a modal dialog where the user input is "collected".
 * It is an event handler and the event is fired on clicking the SN option.
 * 
 */
naviki.main.SNElementCoordinator.prototype.collectInput = function(type,e,me){
	var dialog_container = document.getElementById('naviki-dialogs');
	var dialog_div 	= document.createElement('div');
	dialog_div.id		= 'sn-dialog';
	dialog_container.appendChild(dialog_div);
	
	
			var ok = function(o,p,q){
				//user clicked OK button
				var div = document.getElementById(p['id']+'_usrInput');
				var params 	= YAHOO.lang.JSON.parse(div.value);
				
				//fill the content with user input and then remove the dialog from DOM
				for(var parName in params){
					var el = document.getElementById(p['id']+'_'+parName);
					params[parName]['cont'] = el.value;
				}
				//save it in the div element
				div.value = YAHOO.lang.JSON.stringify(params);
				this.destroy();
			};
	
	var par_div = document.getElementById(e[0].id+'_usrInput');
	var pars 	= YAHOO.lang.JSON.parse(par_div.value);
	
	for(var parName in pars){
		// build the query form in the modal dialog
		var el_input = document.createElement('input');
			el_input.id = e[0].id+'_'+parName;
			el_input.type=pars[parName]['type'];
			el_input.value=pars[parName]['cont'];
			el_input.setAttribute('style','width:90%; margin-left:5%;');
		var el_label= document.createElement('label');
			el_label['for'] = e[0].id+'_'+parName;
			el_label.setAttribute('style','margin-left:5%');
		var label_txt = document.createTextNode(pars[parName]['transl']);
			el_label.appendChild(label_txt);
			dialog_div.appendChild(el_label);
			dialog_div.appendChild(el_input);
		
	}
	
	var sn_modal_dlg = new naviki.main.ModalDialog(
			dialog_div.id,   
			{ 	width: "510px",
				fixedcenter: true,  
				visible: true,
				modal: true,
				draggable: true,
				fixedcenter:true,
				zindex: 4,
				close: false,  
				constraintoviewport: true,
				buttons: [ 
                			{ text:naviki.Lang.getLL('save'),handler:{fn:ok,obj:{id:e[0].id},scope:sn_modal_dlg} } 
//                			{ text:"Nein", handler: handleDeleteWayDialogCancel }  
     					 ]
			});

	sn_modal_dlg.setHeader(par_div.name);
	//sn_modal_dlg.setBody();
	sn_modal_dlg.render();
	sn_modal_dlg.show();	
};



/*
 * Handles the asynchron communication to the naviki server(eID classes).
 * @param string url_pars The parameter part of the query string as returned from this.getSelectedSNOpts()
 * @param array adPars  Additional Parameters from the class that uses the el_coord object ,if any.
 */
naviki.main.SNElementCoordinator.prototype.sendAsynch = function(url_pars,adPars){
	
	var replaced ='';
	for(var i=0,lng=adPars.length; i < lng ;i++){
		//first replace the elems values with the additional Parameters,if any.
		var obj = adPars[i];
		var search  = new RegExp(obj.name,"g");
		url_pars 	= url_pars.replace(search,obj.replace);
	}
	if(url_pars.length > 0){
		//build the query string
		var lang 		= naviki.Util.LOCAL_LANG;
		var address 	= "index.php?eID=tx_naviki_pi_socialnetworks&snaction=1&lang="+lang+"&caller="+this.caller;
			address 	+= url_pars;
		//make request	
		var getXML = YAHOO.util.Connect.asyncRequest("GET",address, {
			success : function(o) {
							// on success
							var output = '';
							var res_obj = YAHOO.lang.JSON.parse(o.responseText);
							for(var par in res_obj['sn_feedback']){
								//collect the feedback from server
								output += res_obj['sn_feedback'][par];
							}
						if(output.length > 0){
							//display the feedback in a modal dialog
							var dlg_cont = document.getElementById("naviki-dialogs");
							var dlg = document.createElement("div");
								dlg.id = 'sn_results';
								dlg_cont.appendChild(dlg);
							var resultsDlg = new naviki.main.ModalDialog(
									dlg.id,   
									{ 	width: "410px",  
										fixedcenter: true,  
										visible: true,
										modal: true,
										draggable: true,
										fixedcenter:true,
										zindex: 4,
										close: true,  
										constraintoviewport: true,
										buttons: [ 
					                    			{ text:"OK", handler: function(){ this.destroy();} } 
					                    		]
									});
	
							dlg.innerHTML = "<div style=text-align:center;><br />"+output+"<br /></div>";				
							resultsDlg.setHeader('Feedback');
							resultsDlg.render();
							resultsDlg.show();
						}
	
					},
			failure : function(o) {
							alert("Sorry, social network request failed!\n Here is the response: " + o.responseText);
					},
			argument: null,
			scope   : this
		});
	}
};

