/**
 *	Note:
 * 
 *		Since FCKeditorAPI is defined only after initializing fck editor,
 *		if the field is put into a tab, fck editor is not initialized
 *		until the corresponding tab section is displayed. For that reason 
 *		and because of a bug of the liferay-ui:tabs taglib that does not
 *		allows to handle properly an 'onChangeTab' event, it is not possible
 *		to insert a translated field implemented as an editor into a
 *		liferay-ui:tabs, excepted for the first tab section (that must 
 *		always be displayed at first when reloading the page).
 */

(function($) {
	
$.widget("ui.vv_transfield", {

	init: function() {
		var self = this;
 		var o = this.options;
		var input = self.element;
		if (o.editor && input.attr('tagName').toLowerCase() == 'iframe') {
			$.extend(o.editor, {
				initMethod	: self._getEditorInitMethod(input),
				loadOnStart	: false
			});
			input.vv_editor(o.editor);
			o.editor = false;
		}
		else
			o.editor = null;
		self._initXml();
	},
	
	destroy: function() {
		this.element.vv_editor('destroy');
	},
	/**
	 * @method displayLanguage
	 * Displays the specific translation into the input control
	 * If the translation does not exist, the method creates it
	 * @param {string} langId
	 * The language code of the translation to display
	 */
	display: function(langId) {
		var self = this;
		var doc = $(self.getData('doc'));
		var content = self._getContentNode(doc, langId);
		if (content) {
			self.setData('curLang', langId);
			var o = self.options;
			var input = self.element;
			if(o.editor == null)
				input.val(content.data);
			else  if(!self._initEditor()) 
				input.vv_editor('setHTML', content.data);
			this._setAvailLocale(doc);
		}
	},

	getCurrentLang: function() {
		return this.getData('curLang');
	},

	/**
	 * @method getDefaultLang
	 * Get the default language id
	 * @return String
	 * a comma separated list of the defined languages id
	 */
	getDefaultLang: function() {
		return $(this.getData('doc'))
			.find('root').attr('default-locale'); 		
	},
	
	/**
	 * @method getLanguages
	 * Get all the language ids
	 * @return string
	 * a comma separated list of the defined languages id
	 */
	getLanguages: function() {
		return $(this.getData('doc')).find('root')
					.attr('available-locales');
	},
	
	getContent: function(langId) {
		var doc = $(this.getData('doc'));
		var content = this._getContentNode(doc, langId);
		if(content)
			return content.data;
	},
	
	remove: function(langId) {
		var doc = $(this.getData('doc'));
		var node = doc.find('static-content[language-id=' + langId + ']')[0];
		if(node && node.parentNode)
			node.parentNode.removeChild(node);
		this._setAvailLocale(doc);
	},
	
	setDefaultLang: function(langId) {
		$(this.getData('doc'))
			.find('root').attr('default-locale', langId);
	},
	
	setXml: function() {
		var xml = $.XML.docToXml(this.getData('doc'));
		$('[name=' + this.options.name +']').val(xml);
	},

	/**
	 * Copy all the edited content into the xml
	 * @param {String} langId
	 *  The language code of the translation to display
	 */
	store: function(langId) {
		var self = this;
		var doc = $(self.getData('doc'));
		var content = self._getContentNode(doc, langId);
		if(content) {
			var input = self.element;
			var text = self.options.editor == null ?  
				input.val() : input.vv_editor('getHTML');
			content.replaceData(0, content.length, text || '');	
		}		
	},
	
	/**
	 * @method syncLanguages
	 * Add the missing languages to the content
	 * @param {string[]}
	 * the language ids requested to be contained
	 */
	sync: function(languages) {
		var doc = $(this.getData('doc'));
		for (var i = 0, ln = languages.length; i < ln; i++) {
			this._getContentNode(doc, languages[i].id)
		}
		this._setAvailLocale(doc);
	},
	
	_addLanguage: function(doc, langId){		
		var node = doc.createElement("static-content");	
		node.setAttribute("language-id", langId);
		node.appendChild(doc.createCDATASection(''));
		return node;							
	}, 
	
	_getContentNode: function(doc, langId) {
		var content = null; 
		while(! (content = doc.find('static-content[language-id=' + langId + ']')[0]))
			doc.find('root').append(this._addLanguage(doc[0], langId));
		if(! content.firstChild) {
			content.appendChild(doc[0].createCDATASection(''));
		} 
		if( content.firstChild.nodeType != 4)  {
			content.insertBefore(doc[0].createCDATASection(''), content.firstChild)
		}
		return content.firstChild;
	},
	
	_getEditorInitMethod: function(input) {
		return function(){
			var curLang = input.vv_transfield('getCurrentLang');
			return input.vv_transfield('getContent', curLang);

		}
	},
	
	_initEditor: function() {
		var o = this.options;
		if (o.editor === false) {
			$('[name=' + o.input + ']').vv_editor('load');
			o.editor = true;
			return true;
		}
		return false;
	}, 
	
	_initXml: function() {
		var o = this.options;
		var doc = null;
		if(o.xml) 
			doc = $.XML.xmlToDoc(o.xml);
		else if(o.xmlUrl)
			doc = $.XML.load(o.xmlUrl);
		if(doc == null || !doc.documentElement) {
			doc = $.XML.xmlToDoc(
			'<?xml version="1.0" encoding="UTF-8"?><root></root>');
		}
		this.setData('doc', doc);
	},
	
	_setAvailLocale: function(doc) {
		var langIds = [];
		doc.find('static-content[language-id]').each(function() {
			var langId = this.getAttribute('language-id');
			if(langId)
				langIds.push(langId);
		});
		doc.find('root').attr('available-locales', langIds.join());
	}
});

$.extend($.ui.vv_transfield, {
	getter: ["getLanguages", "getDefaultLang", "getContent", "getCurrentLang"],
	defaults: {		
	}
});

Vivieb._TransFieldManager = {

	/**
	 * @param {object} options
	 * 
	 * object with the manager options:
	 * 	
	 * 	id: {string}
	 * 		the unique identifier of translation manager.used to select the 
	 * 		input field that must be translated
	 * 		It is used as:
	 * 		- the id of the select box that allows to choose the default
	 * 		language and contains the defined translations. 
	 * 		- the prefix for the select box containing the available languages 
	 * 		(<id>_avail)
	 * 		- the prefix for the remove	language button (<id>_remove)
	 * 		- the CSS class name of the fields that must be translated
	 * 
	 * 	availLangs: {array}
	 * 		available language definitions. Each array item must be an object
	 * 		with the following properties:
	 * 		id: {string}
	 * 			the language code
	 * 		name: {string}  
	 * 			the language description
	 * 
	 * 	defaultLang: {array}
	 * 		the code of the language to set as the default language if the 
	 * 		default language has not been selected yet.
	 * 
	 * 	fields: {array of object}
	 * 		an array of objects that indicates the data for each field that 
	 * 		have to be put under the control of the translation manager.
	 * 		Each object into the array has the following properties:
	 * 		
	 * 			paramName {string}:
	 * 				the name of the hidden input field to post to the server 
	 * 				with the data to save
	 * 
	 * 			inputName {string}:
	 * 				the name of the input field displayed in the user interface
	 * 
	 * 			editor {object}:
	 * 				if set, this field must be implemented as an editor. 
	 * 				The object properties are the options needed to initialize 
	 * 				a vv_editor widget.
	 * 
	 *  		xmlData {string}:
	 *  			the xml content of the field. If not specified, the xmlUrl
	 *  			property must be indicated. If both indicated, xmlData
	 *  			takes the precedence over xmlUrl
	 *  
	 *  	 	xmlUrl {string}:
	 *  			the url which to get the xml content from. 
	 *  			If not specified, the xmlData property must be indicated. 
	 *  			If both indicated, xmlData takes the precedence over xmlUrl
	 *  
	 *  		In both cases, the xml must be like:
	 *  
	 *  			<?xml version='1.0' encoding='UTF-8'?>
	 *  			<root available-locales="en_US" default-locale="en_US">
	 *  				<static-content language-id="en_US">
	 *  					<![CDATA[translated content field]]>
	 *  				</static-content>
	 *  			</root>
	 *  
	 */	
	
	
	initialize: function(options) {
		
		var instance = this;
		instance._setOptions(options);
		var o = instance.options;
		
		for(var i=0, ln=o.fields.length; i<ln; i++ ) {
			var field = o.fields[i];
			$('[name=' + field.inputName+ ']').vv_transfield({
						name	: field.paramName,
						input	: field.inputName,
						xml		: field.xmlData,
						xmlUrl	: field.xmlUrl,
						editor	: field.editor || null
					}).removeClass(o.id).addClass(o.id);
		}
		
		var fields = $("." + instance.options.id);
		instance._defLang = fields.vv_transfield('getDefaultLang') || o.defaultLang;
		var langIds = instance._defLang;
	
		fields.each(function() {
				langIds = instance._mergeLanguages(langIds, $(this).vv_transfield('getLanguages'));
			});
		
		instance.langs = instance._getLanguages(langIds);
		fields.each(function(){
				$(this).vv_transfield('sync', instance.langs);
			}).vv_transfield('setDefaultLang', instance._defLang);
			
		instance._buildSelect(o.id + '_avail', o.availLangs, 
			instance._defLang, instance._onChangeAvailLanguage);
		instance._buildSelect(o.id, instance.langs, 
			instance._defLang, instance._onChangeDefLanguage);
			
		$('#' + o.id + '_remove').hide()
			.bind('click', instance, instance._onClickRemoveLang);
		
		fields.vv_transfield('display', instance._defLang);
		
		instance._curLang = instance._defLang;
		// delay onChange event to resolve IE6 wrong behavior with fck
		instance._delayChangeLang = jQuery.vv_bind(instance._changeLangDelayed, instance);
		instance._delayChangeDefLang = jQuery.vv_bind(instance._changeDefLangDelayed, instance); 
	},
	
	add: function(field) {
		var instance = this;
		var o = instance.options;
		$('[name=' + field.inputName+ ']')
			.vv_transfield({
				name	: field.paramName,
				input	: field.inputName,
				xml		: field.xmlData,
				xmlUrl	: field.xmlUrl,
				editor	: field.editor || null
			}).removeClass(o.id).addClass(o.id)
			.vv_transfield('sync', instance.langs)
			.vv_transfield('setDefaultLang', instance._defLang)
			.vv_transfield('display', instance._defLang);
	},
	
	setHttpParams: function() {
		$("." + this.options.id)
			.vv_transfield('store', this._curLang)
			.vv_transfield('setXml');
	},
	
	_buildSelect: function(id, langs, selected, onChange) {
		var instance = this;
		var o = instance.options;
		var options = '';
		for(var i=0, ln=langs.length; i<ln; i++) {
			var option = langs[i];
			options += '<option value="' + option.id +'"';
			if(option.id == selected)
				options += ' selected="selected"';
			options += '>' + option.name + '</option>'; 
		}
		var select = $('#' + id);
		if(onChange)
			select.unbind('change');
		select.hide().html(options).show(); //hide and show for IE 6
		if(onChange)
			select.bind('change', instance, onChange);
		return select;
	} ,
	
	_getLanguage: function(langId) {
		var langs = this.options.availLangs
		for(var i=0, ln=langs.length; i<ln; i++) {
			if(langs[i].id == langId)
				return langs[i];
		}
		return false;
	},
	
	_getLanguages: function(langIds) {
		var langs = langIds.split(',');
		var rslt = [];
		for (var i = 0, ln = langs.length; i < ln; i++) {
			var lang = this._getLanguage(langs[i]);
			if (lang) 
				rslt.push(lang);
		}
		return rslt;
	},
	
	_mergeLanguages: function(langIds, IdsToMerge) {
		if (IdsToMerge) {
			var langs = IdsToMerge.split(',');
			for (var i = 0, ln = langs.length; i < ln; i++) {
				var lang = langs[i];
				if (langIds.indexOf(lang) == -1) 
					langIds += ',' + lang;
			}
		}
		return langIds;
	},
	
	_onClickRemoveLang: function(ev) {
		var instance = ev.data;
		var id = instance.options.id;
		var fields = $("." + id);
		fields.vv_transfield('remove', instance._curLang)
		fields.vv_transfield('display', instance._defLang);
		instance._curLang = instance._defLang;
		$('#' + id + '_avail').val(instance._defLang);
		instance._buildSelect(
				id, 
				instance._getLanguages(fields.vv_transfield('getLanguages')),
				instance._defLang,
				instance._onChangeDefLanguage);
		instance._setRemoveDisplay();
	},
	
	_onChangeAvailLanguage: function(ev) {
		var instance = ev.data;
		var id = instance.options.id;
		var fields = $("." + id);
		fields.vv_transfield('store', instance._curLang);
		setTimeout(instance._delayChangeLang, 250); // delay for IE6 problem with fck!
	},
	
	_changeLangDelayed: function() {
		
		var instance = this;
		var id = instance.options.id;
		var fields = $("." + id);
		var curLang = $('#' + id + '_avail')[0].value;
		instance._curLang = curLang;
		fields.vv_transfield('display', instance._curLang);
		instance._setRemoveDisplay();
		instance._buildSelect(
				id, 
				instance._getLanguages(fields.vv_transfield('getLanguages')), 
				instance._defLang,
				instance._onChangeDefLanguage);		
	},
	
	_onChangeDefLanguage: function(ev) {
		var instance = ev.data;
		setTimeout(instance._delayChangeDefLang, 250); // delay for IE6 problem with fck!
	},
	
	_changeDefLangDelayed: function() {
		
		var instance = this;
		var id = instance.options.id;
		var defLang = $('#' + id)[0].value;
		$("." + id).vv_transfield('setDefaultLang', defLang);
		instance._defLang = defLang;
		instance._setRemoveDisplay();
	},

	_setOptions: function(options) {
		var instance = this;
		instance.options = $.extend(true, {
			id			: 'tfmng',
			availLangs	: []
		}, options || {});
	},
	
	_setRemoveDisplay: function() {
		var btn = $('#' + this.options.id + '_remove');
		if(this._curLang == this._defLang)
			btn.hide();
		else
			btn.show();		
	}	

}

Vivieb.TransFieldManager = new Class(Vivieb._TransFieldManager);
	
})(jQuery);
