/******************* object size from http://stackoverflow.com/questions/5223/length-of-javascript-associative-array ************/
associativeSize = function(obj) {  var size = 0, key;    for (key in obj) {     if (obj.hasOwnProperty(key)) size++;    }    return size;};

document.formList = new Array ();
var transliterableInputs = new Array();
var googleTransliterationControll;

/** 
* Creates an input element with wrapper and description. Types available are.
*	submit, file, password, hidden, input, select and textarea
* @param type string (input, submit, file, password, hidden, select or textarea)
* @param name string the name attribute of the input.
* @param options contain an array with the following possible options
* * description string a descriptive string of the object if visible
* * value string an optional pre-defined value container to the input
* * select_options contains a list of possible select-list options
* * ajax_reference an optional parameter used by the ajax validation. this should YCÄF=FÄDO argh
* * ajax_name an optional parameter used as replacement for the name for ajaxvalidation
*
* @return a new div containing all nessecary layout etc.
*/
function Input (type, name, options)
{
	if (!options)
		options = {};
// description, value, select_options, tableType
	var npt = document.createElement("input");

	switch (type)
	{
		case "hidden":
		case "submit":
		case "checkbox":
		case "file":
		case "password":
			$(npt).attr("type",type);
		break;
		case "date":
			$(npt).attr("type","text");
		break;
		default:
			npt = document.createElement(type);
		break;
	}
	
	Input.prototype.counter++;

	if (options["value"] == undefined || options["value"] == null)
		npt.defaultValue = "";
	else
		npt.defaultValue = options["value"];

	if (type != "file")
		npt.value = npt.defaultValue;


	npt.success = 1;

	npt.name = name;				//the name of this input


	var wrapper = document.createElement("div");
	var descriptorWrapper = document.createElement("div");		//contains textual description
	var inputWrapper = document.createElement("div");			//contains the input-item
	var inputAjaxIMG = document.createElement("img");		//space for ajax validaton result
	inputAjaxIMG.className = "inputAjaxIMG";
	npt.ajaxIMG = inputAjaxIMG;	

	wrapper.descriptorWrapper = descriptorWrapper;
	wrapper.inputWrapper = inputWrapper;
	wrapper.npt = npt;

	wrapper.className = "inputWrapper";
	descriptorWrapper.className = "inputDescriptorWrapper";
	inputWrapper.className = "inputInputWrapper";


	if (type != "hidden")
	{
		if (options["description"] != undefined)
			$(descriptorWrapper).append(document.createTextNode(Translator(options["description"])));
	}

	$(inputWrapper).append(npt);
	$(wrapper).append([descriptorWrapper,inputWrapper]);
	
	if (options["transliterable"] == true)
	{
		npt.transliterable = true;
		npt.id = name + this.counter; //unique...
	}	
	else
		npt.transliterable = false;

	switch (type)
	{
		case "select":
			npt = getList_(npt,options["select_options"]);
		break;
		case "date":
		case "password":
		case "input":
			
			if (options["ajax_reference"] == undefined)
				throw ("ajax_reference needed for 'input', due to ajax validation");

			if (options["ajax_reference"] != false)
			{
				npt.ajax_name = options["ajax_name"] == undefined ? name : options["ajax_name"];	//ajax-translated name of this input
				npt.ajax_id = this.counter;		//the id of this item, used to identify it during ajax validation
				npt.ajax_type = options["ajax_reference"];		//the table to which this property belongs... argh...

				$(wrapper).append(inputAjaxIMG);

				if (type == "date")
					$(npt).simpleDatepicker();
			}
		break;
		case "checkbox":
			if (options["value"] == "1")
				npt.checked = true;
			else
				npt.checked = false;
		break;
		case "hidden":
			wrapper.style.display = "none";
		break;
		case "submit":
		case "textarea":
			var nptClone = $(npt).clone()[0];//jQuery.extend(false, {}, npt);//$(npt).clone()[0];//document.createElement("textarea"); //jQuery.extend(true, {}, npt);
			nptClone.value = npt.value;
			nptClone.transliterable = npt.transliterable;
			nptClone.id = npt.id;
			nptClone.name = npt.name;
			nptClone.success = npt.success;
			nptClone.ajaxIMG = npt.ajaxIMG;
			nptClone.defaultValue = npt.defaultValue;
			wrapper.innerHTML = "";
			wrapper.npt = nptClone;
			$(wrapper).append(nptClone);
		break;
	}
	
	npt.refresh = function ()
	{
		if (npt.ajax_id > 0 ) 
			AjaxValidator(npt);
 
		if (this.frm)
			this.frm.changed = true;

	}
	$(npt).change ( function() 
	{
		this.refresh();
	}); 


	npt.setSuccess = function (success)
	{
		var src;
		if (success)
			src = _IMAGE_PATH + "/em-edit-icon-small-ok.gif";
		else
			src = _IMAGE_PATH + "/em-edit-icon-small-failure.gif";
		this.success = success;
		this.ajaxIMG.src = src;
	}


	return wrapper;

}


Input.prototype.counter = 0;

/**
* Creates the three text input boxes for the form
* @param string language The language of these text boxes
* @param string title The title data in the title input box
* @param string description Description data
* @param string long_text Long text data (currently not used)
* @param boolean rich_display will the rich text be displayed (or null)
*/

function TextInputs (language, values, frm, rich_display)
{

	var wrapper = document.createElement("div"); //wrapper for the whole TextInputs area
	wrapper.className = "TextDivWrapper";	

	var textInputWrapper = document.createElement("div");	//wrapper for the text inputs only
	$(textInputWrapper).css({"margin-left" : "40px", "display" : "block"});

	var titleBar = document.createElement("div");	//wrapper for the <img><title><language> thing on top
	titleBar.className = "title";
	var showHideTextFieldsImage = OpenCloseImage (textInputWrapper);
	
	var shortDescriptionText = document.createElement("span");	$(shortDescriptionText).css({"float" : "left"});	
		if (!rich_display)
			$(shortDescriptionText).append(document.createTextNode(Translator("short_description")));
		else
			$(shortDescriptionText).append(document.createTextNode(Translator("rich_description")));

	var languageDisplayArea = document.createElement("div");	languageDisplayArea.className = "LanguageDisplayArea";	$(languageDisplayArea).append (document.createTextNode(Translator(language)));
	$(titleBar).append ([showHideTextFieldsImage,shortDescriptionText,languageDisplayArea]);

	$(wrapper).append (titleBar,true);
	
	var title = new Input ("input",  "title/" + language, {"description" : "title", "value" : values["title"] != null ? values["title"] : "", "ajax_reference" : "text_data" , transliterable : (language != "english" ? true : false)});
	frm.append(title);


	if (language == "english") 
	{
		title.npt.ajax_name = "english_title" //special case...;
	}	
	else
		title.npt.ajax_name = "title";
	
	$(textInputWrapper).append (title);

	//use the non-customizable text area
	if (!rich_display)
	{
		var description = new Input ("textarea",  "description/" + language, {"description" : "description", "value" : values["description"] != null ? values["description"] : "", transliterable : (language != "english" ? true : false)});
		
		frm.append(description,true);

		$(textInputWrapper).append (description);
	}
	else //or use the rich text (long_text) field
	{
		
		//, transliterable : (language != "english" ? true : false)
		var long_text = new Input ("textarea", "long_text/" + language, { "description" : "long_text", "value" : values["long_text"] != null ? values["long_text"] : ""});
		
		$(long_text.npt).css({"height" : "500px"});
		long_text.npt.id = "long_text/" + language;
		frm.append (long_text, true);
		$(textInputWrapper).append (long_text);
		
	}
	
	$(wrapper).append (textInputWrapper);

	return wrapper;
}
/*
var control;

function shiot()
{
	//alert ("TTA");

      
      //google.setOnLoadCallback(onLoad);
}

  function onLoad() {

  	control = new google.elements.transliteration.TransliterationControl(googleTransliterateOptions["hi"]);
  	control.makeTransliteratable(['transliterateDiv']);	
  }
*/

/**
* The button used to create new text fields from the remaining languages.
* @param DOMObject frm the form to which the new-text-button/functionality is attached.
* @param boolean rich_display If the TextInput will be of type rich (TinyMCE)
*/
function NewText (frm, rich_display)
{
	newTextWrapper = document.createElement("div");
	newTextWrapper.frm = frm;
	newTextWrapper.rich_display = rich_display ? true : false;

	newTextWrapper.TextInputCount = 0; //only used to switch colour between TextInputFields from different language

	$(newTextWrapper).css( {"padding-left" : "10px", "width" : "676px", "background-color" : "#ffaaff", "float" : "left", "padding-top" : "10px"});

	newTextWrapper.refresh = function ()
	{
		//no more languages: make invisible
		if (associativeSize(this.frm.availableLanguages) == 0)
		{
			$(this).css( {"padding-top" : "0px"});
			return;
		}

		this.container = new Input("select","new_text",{select_options : this.frm.availableLanguages});
		$(this.container.npt).css({"padding": "0px", "margin-left" : "100px", "width" : "200px"});
		this.container.descriptorWrapper.innerHTML = "";
		this.container.descriptorWrapper.className = "editLink";
		this.container.descriptorWrapper.wrapper = this;
		var showHideTextFieldsImage = document.createElement("img");	showHideTextFieldsImage.src = _IMAGE_PATH + "/em-arrow-transp-black-close.gif";	$(showHideTextFieldsImage).css ({ "margin-right": "10px", "float" : "left"});
		var shortDescriptionText = document.createElement("span");	$(shortDescriptionText).css({"float" : "left", "font-weight" : "bold"});	$(shortDescriptionText).append(document.createTextNode(Translator("add_new_language")));		
		$(this.container.descriptorWrapper).append(showHideTextFieldsImage);
		$(this.container.descriptorWrapper).append(shortDescriptionText);
		
		$(this).append(this.container);
		
		

		//add new language, update the form's availabel languages and refresh:
		$(this.container.descriptorWrapper).click(function() 
			{	
				language = this.wrapper.container.npt.value;
				this.wrapper.frm.activeLanguages[language] = {};
				delete this.wrapper.frm.availableLanguages [language];
				var textInputsWrapper = new TextInputs (language, new Array(), this.wrapper.frm, this.wrapper.rich_display);
				
				//fixing the colour shift...
				this.wrapper.TextInputCount++;
				if (this.wrapper.TextInputCount % 2)
					$(textInputsWrapper).css("background-color" , "#77bbcc");

				$(this.wrapper.frm.language_container.textInputs).append(textInputsWrapper);
				this.wrapper.container.style.display = "none";
				this.wrapper.refresh();

				tinyMCE.execCommand('mceAddControl', false, "long_text/" + language);
				//alert (document.getElementById("long_text/" + language));
				//alert (document.getElementById("long_text/" + language).innerHTML);
				this.wrapper.frm.refresh();
			
			});

	}
	
	newTextWrapper.refresh();

	return newTextWrapper;

}

/**
* Creates a form with form container
* @param string action The action to be used (eg post/add)
* @param array {} values Parameter inputs to the form:
*	- string type The content type of this item (eg event, media etc)
*	- int parent_id The parent of the item (or 0 if no parent item selected)
*	- array["text"][<languageu>][<title> or <description> or long_text] Text parameters for this form
* 	Special values:
*	*	boolean hide_bottom_send : if true - the send-buttons will not be visible
* @param boolean rich_display if set, the description will not be shown, but the long_text
* @param boolean hide_bottom_send special case for the fckn image uploads: hide the save-form-button in the bottom section
*/
function Form (action, values, rich_display)
{
	frm = document.createElement("form");
	frm.action = "";
	frm.method = "POST";
	frm.availableLanguages = jQuery.extend(true, {}, _AVAILABLE_LANGUAGES); //deep copy of the available languages.
	frm.activeLanguages = {}; //languages currently being used
	frm.npts = new Array(); // contains a list of the active inputs and their status
	frm.changed = false;

	document.formList.push (frm);

	frm.topDisplay = GrayBox (); $(frm).append(frm.topDisplay); //contains the Main Information and all inputs but the text-fields
	frm.topDisplay.content.mainInputWrapper = document.createElement("div"); //the element that contains all the inputs, but NOT the title bar
	$(frm.topDisplay.content.mainInputWrapper).css ("padding-left", "40px");

	//creates title of the main information where all inputs, but text-fields are stored
	var titleBar = document.createElement("div"); titleBar.className = "title"; $(titleBar).css({"width" : "600px"});
	var showHideTextFieldsImage = OpenCloseImage (frm.topDisplay.content.mainInputWrapper);
	var shortDescriptionText = document.createElement("span");	$(shortDescriptionText).css({"float" : "left"}); $(shortDescriptionText).append(document.createTextNode(Translator("main_information")));
	var ajaxDisplayEditedImage = document.createElement("img");	$(ajaxDisplayEditedImage).css({"float" : "right"});	frm.ajaxDisplayEditedImage = ajaxDisplayEditedImage;

	$(titleBar).append ([showHideTextFieldsImage,shortDescriptionText,ajaxDisplayEditedImage]);

	$(frm.topDisplay.content).append(titleBar);
	$(frm.topDisplay.content).append(frm.topDisplay.content.mainInputWrapper);

	//the div containing all language forms	
	var languageDisplayWrapper = GrayBox ();
	languageDisplayWrapper.content.textInputs = document.createElement("div"); $(languageDisplayWrapper.content).append (languageDisplayWrapper.content.textInputs); //contains the TextInputs fields 
	languageDisplayWrapper.content.bottomSection = document.createElement("div");  $(languageDisplayWrapper.content).append (languageDisplayWrapper.content.bottomSection); //contains the bottom section
	frm.language_container = languageDisplayWrapper.content; //a pointer to the area in which new languages could be added
	frm.language_wrapper = languageDisplayWrapper;	//the pointer to the wrapper of the language displays


	//contains an additional SubmitImage at the bottom of the form
	if (values["hide_bottom_send"] != true)
	{
		var submitImageAtTheBottom = new SubmitImage (frm, Translator("send"));	 $(submitImageAtTheBottom).css({"margin-left": "35%"});
		$(languageDisplayWrapper.content.bottomSection).append (submitImageAtTheBottom);
	}

	/**
	* Updates the edit-button according to success
	* @param boolean success If the action was successfull or not (result appends to input form status)
	*/
	frm.refresh = function (success)
	{
		if (this.refreshing)
		{
			return false;
		}

		this.refreshing = true; //used to avoid unnessecary recursion

		if (!success && (success != 0)) 
			success = 1;


		for (var i = 0; i < this.npts.length; i++)
		{
			success &= this.npts[i].npt.success;
		
			if (!this.npts[i].npt.is_checked && this.npts[i].npt.ajax_id > 0)
			{
				this.npts[i].npt.is_checked = true;
				AjaxValidator(this.npts[i].npt);
				this.npts[i].npt.is_checked = true;
			}
		}
		


		this.ajaxDisplayEditedImage.src =  _IMAGE_PATH + (success == 1 ? "/em-edit-change-icon-ok.jpg" : "/em-edit-change-icon-failure.jpg");

		if (googleTransliterationControll)
			googleTransliterationControll.makeTransliteratable(transliterableInputs);

		this.refreshing = false;
	}
	
	/**
	* Checks if all values in the form are correct
	* @return boolean true if all input forms have correct values.
	*/
	frm.checkValues = function ()
	{	
		var success = true;

		for (var i = 0; i < this.npts.length; i++)
			success &=  this.npts[i].npt.success;

		return success;
	}
	
	/**
	* Appends an input-wrapper to the form
	* @param Input npt The Input (wrapper) object to be attached
	* @param boolean ignore_append If set, the Input will not be added to the regular Form Wrapper, but rather appended to the form-area
	*/
	frm.append = function (npt, ignore_append)
	{
		if (ignore_append != true)
			$(this.topDisplay.content.mainInputWrapper).append(npt);

		if (npt.npt)
		{ 
			if (npt.npt.transliterable)
				transliterableInputs.push(npt.npt.id);

			npt.npt.frm = this;
			npt.npt.is_checked = false;
			this.npts.push(npt);
			return true;
		}


		return false;
		
	}
	/**
	*	Is used to retrieve the input with the name <name>
	*/
	frm.getInput = function (name)
	{
		for (var i = 0; i < this.npts.length; i++)
		{
			if (this.npts[i].npt.name == name)
				return this.npts[i];
		}

		return false;
	}
	
	//appendding the common fields
	$(frm).append(new Input("hidden", "form_descriptor",{value : action}));		//set form action (add/update)
	$(frm).append(new Input("hidden","target_id",{value : values["target_id"]}));  //set target content (add: parent to the object being created, update: id of the object being updated)

	//update the languageDisplayWrapper with the language information in values
	for (language in values["text"])
	{
		frm.activeLanguages[language] = {};
		delete frm.availableLanguages [language];

		$(languageDisplayWrapper.content.textInputs).append(new TextInputs (
			language, {
			"title" : values["text"][language]["title"], 
			"description" : values["text"][language]["description"], 
			"long_text" : values["text"][language]["long_text"]},
			frm,
			rich_display)
		);
	}

	$(languageDisplayWrapper.content.bottomSection).append (NewText(frm, rich_display)); //add the new text button to the bottom section of the form


	return frm;
}

/**
* Checks if forms has unsaved changes
* @return boolean true if there have been any changes
*/
function documentFormsHasUnsavedChanges ()
{
	for (var i = 0; i < document.formList.length; i++)
	{
		if (document.formList[i].changed)
		{
			return true;
		}
	}
	return false;
}


function SubmitImage (frm, text,classPostFix)
{

	var npt = BlueButton (text,classPostFix);

	npt.frm = frm;

	$(npt).click (function () {
		if (frm.checkValues())
			frm.submit ();
		else
			alert (Translator("form_errors"));
	});
	

	return npt;
}


/**
*	Helper method for list generation.
*	Generates a list of <options> parameters
*	@param <list> npt the list to be extended with <options>
*	@param array a list of available options
*	@param int level used for the determination of indentation
*	@return <list> containing the added options
*
*	(the selected value is allways the last in the options list to equal tmpValue)
*/
getList_ = function (npt, options, level)
{
	
	if (level == null) 
		level = 0;

	for (var option in options)
	{
		
		//don't use the post-last non-existing value...
		if (option != null)
		{

			var optionElement = document.createElement("option");
			optionElement.value = option;
			$(optionElement).append (document.createTextNode(option.indent(level)));

			

			if (option == npt.defaultValue)
			{
				optionElement.selected = 1;
			}
			$(npt).append (optionElement);

			//associative array - continue recursion
			if ( associativeSize(options[option]) > 0)
				npt = getList_ (npt, options[option],level+1);

		}

	}

	return npt;
}



