///////////////////////////////////////////////////////////// SINGLETONES

//////////////////////////////////////////////
// Dialog Window Manager it responsible for opening and closing the 
// dialogs. 
// Its a singleton. It means that you can't instantiate any more instances.
// You can only redefine its properties
var dlgWindow = new function(){
	// In your page application you should define the mapping of the
	// contentElement ID and DialogManager instance
	// dlgWindow.registry["LoginDialog"] = new LoginDialogManager("Login")
	this.registry = new Array()
	// remembers/queues 'do not show next time' dialogs to open
	this.doNotShowAgainRegistry = new Array()
	// you can redefine the next fields before first dialog will be opened
	this.dialogContainerId = "DialogContainer"
	this.dialogCaptionId = "DialogCaption"
	this.applyButtonId = "DialogApplyButton"
	this.okButtonId = "DialogOKButton"
	this.cancelButtonId = "DialogCancelButton"
	this.closeDialogButtonId = "closeDialogButton"
	// styles
	this.openedDialogStyle = "openedDialogWindow"
	this.reallyOpenedDialogStyle = "reallyOpenedDialogWindow"
	this.closedDialogStyle = "closedDialogWindow"
	this.visibleContentStyle = "visibleDialogContent"
	this.reallyVisibleContentStyle = "reallyVisibleDialogContent"
	this.hiddenContentStyle = "hiddenDialogContent"
}

// called once before first show to assign windows components
dlgWindow.initComponents = function(){
	this.dialogContainer = document.getElementById(this.dialogContainerId)
	this.dialogCaption = document.getElementById(this.dialogCaptionId)
	this.applyButton = document.getElementById(this.applyButtonId)
	this.okButton = document.getElementById(this.okButtonId)
	this.cancelButton = document.getElementById(this.cancelButtonId)
	this.closeDialogButton = document.getElementById(this.closeDialogButtonId)
}

// Opens Dialog with the specified contentid
// be sure that the DialogManager instance is assigned to the dlgWindow.registry[contentElement.id]
dlgWindow.open = function(contentElementId){
	if (!this.dialogContainer) this.initComponents()

	var currentManager = this.registry[contentElementId]
	if (!currentManager){
		return
		//window.alert("DEBUG: There no Dialog Manager is assigned to the dlgWindow.registry['"+contentElementId+"']")
	}

	if (this.currentContent){
		if (currentManager instanceof DoNotShowNextTimeDialogManager){
			for(var j=0; j < this.doNotShowAgainRegistry.length; j++){
				if (contentElementId == this.doNotShowAgainRegistry[j]){
					return;
				}
			}
			this.addDialogToShow(contentElementId)
			return;
		}
		this.clearDialogsToShow()
		try{
			this.currentManager.closeDialog(this);
		}catch(e){
			this.close();
		}
	}
	this.openinig = currentManager;
	this.currentManager = currentManager;
	this.currentContent = document.getElementById(contentElementId)
	//this.dialogCaption.appendChild(document.createTextNode(this.currentManager.caption))
	this.dialogCaption.innerHTML = this.currentManager.caption;
	this.currentManager.setDialogButtons(this);
	this.applyButton.style.display = (this.currentManager.showApplyButton)?"inline":"none";
	if (this.currentManager.showCancelButton){
		this.cancelButton.style.display = "inline";
		try{
			this.closeDialogButton.style.display = "table-cell";
		}catch(e){
			this.closeDialogButton.style.display = "block";
		}
	}else{
		this.cancelButton.style.display = "none";
		this.closeDialogButton.style.display = "none";
	}
	
	this.dialogContainer.className = this.openedDialogStyle
	this.currentContent.className = this.visibleContentStyle
	
	if (!this.currentManager.activated){
		// additiaonal code related to the tabbed content see TabManager in tabs.js
		var tabManager = this.currentManager.tabManager
		if (tabManager && tabManager.alignConentContainer) tabManager.alignConentContainer()
		this.currentManager.activate();
	}
	this.currentManager.initContent(this.currentContent)
	
	setDialogCoordinates(this.dialogContainer);
	this.dialogContainer.className = this.reallyOpenedDialogStyle
	this.currentContent.className = this.reallyVisibleContentStyle	
	this.openinig = null;
}

// executes action of curent DialogManager instance 
dlgWindow.action = function(notCloseDlgWindow){
	var settings = this.currentManager.evaluateContentSettings(this.currentContent);
	if (this.currentManager.validateSettings(settings)){
		this.actionOldSettings = this.currentManager.settings
		this.currentManager.settings = settings
		if (notCloseDlgWindow) this.doAction()
		else if (!this.openinig) this.close()
	}
}

// internal method which is realy executes action
dlgWindow.doAction = function(clearManager){
		var oldSettings = this.actionOldSettings;
		this.actionOldSettings = null;
		if (this.currentManager.storeSettings) this.currentManager.storeSettings()
		var manager = this.currentManager;
		if (clearManager)this.currentContent = this.currentManager = null;
		manager.action(oldSettings, true)
}

// Closes dialog without dialog executing
dlgWindow.close = function(){
	// removing of the title
	//for (var c = this.dialogCaption.childNodes[0]; c ; this.dialogCaption.removeChild(c),c = this.dialogCaption.childNodes[0])
	this.dialogCaption.innerHTML = "";
	// hiding content
	this.currentManager.destroyContent(this.currentContent)
	this.currentContent.className = this.hiddenContentStyle
	this.dialogContainer.className = this.closedDialogStyle
	// performing action if neccessary
	if (this.actionOldSettings) this.doAction(true);
	else this.currentContent = this.currentManager = null;
	if (this.doNotShowAgainRegistry.length > 0){
		this.open(this.doNotShowAgainRegistry.shift())
	}
}

dlgWindow.addDialogToShow = function(contentElementId){
	this.doNotShowAgainRegistry.push(contentElementId)
}

dlgWindow.clearDialogsToShow = function(){
	this.doNotShowAgainRegistry = new Array();
}

dlgWindow.getDialogContainer = function(){
	if (this.currentContent) return this.dialogContainer;
	return null;
}

function setDialogCoordinates(dialogContainer){
	dialogContainer.style.top = (dialogContainer.parentNode.offsetHeight - dialogContainer.offsetHeight)/2
	dialogContainer.style.left = (dialogContainer.parentNode.offsetWidth - dialogContainer.offsetWidth)/2
}


///////////////////////////////////////////////////////////// CLASSES

////////////////////////////////////////////////
// Base setting value wrapper object
// Wraps the value and provides initialization string
// which contains a statements for assigning value (works boolean and numbers value types)
function Setting(value){
	this.value = value
}

// generates the value script which return initialization string (works for  boolean and numbers)
Setting.prototype.assignmentStatement = function(valiableName){return valiableName+"= new Setting("+this.value+");"}

///////////////////////////////////////
// String setting value wrapper oblect
// Wraps string values
function StringSetting(value){
	this.base = Setting;
	this.base(value);
}

StringSetting.prototype = new Setting();
StringSetting.prototype.assignmentStatement = function(valiableName){return valiableName+"= new StringSetting(\""+this.value+"\");"};

///////////////////////////////////////
// Array setting value wrapper oblect
// Wraps Array values
function ArraySetting(value){
	this.base = Setting;
	this.base(value);
}

ArraySetting.prototype = new Setting();
ArraySetting.prototype.assignmentStatement = function(valiableName){
	var result = valiableName+"="+"new ArraySetting(new Array());"
	for(i in value){
		result+=this.value[i].assignmentStatement(valiableName+".value["+i+"]");
	}
	return result;
};


/////////////////////////////////////////////////////////////////////
// Each Dialog Manager implementation should be registered in the 
// dlgWindow.registry array opposite the identity of the dialog content
// see implementation of the openDialog() for details

function DialogManager(caption,useApplyButton,useCancelButton) {
	// contains caption of the dialog window
	this.caption = caption
	// defines if the apply button should be present in the dialog
	this.showApplyButton = useApplyButton
	// defines if the cancel button should be present in the dialog
	this.showCancelButton = useCancelButton
	// contains dialog Settings between dialog sessions
	this.settings = new Array();
	// tabManager see tabs.js you should init tab manager for tabbed content
	this.tabManager = null;
	this.activated = false;
	//buttons inscriptions
	this.ok = "OK";
	this.cancel = "Cancel";
}

// Called just before to hide dialog
DialogManager.prototype.destroyContent = function(contentElement){return false};


// Validates content of the dialog returned false when there invalid values
DialogManager.prototype.validateSettings = function(contentSettings){return true};

// Executes dialog action on pressing "OK" or "ApplyButton"
// The settings property already contains new settings
// previous settings are passed via argument. 
// Be careful during the implementation of this method
// because oldSettings could be not specified (case when user initialization is performed at login)
DialogManager.prototype.action = function(oldSettings, explicitAction){}

// Called once per manager at first display time
DialogManager.prototype.activate = function(contentElement){this.activated = true;}

// Called just before to show dialog
// It's the place where you can init dialogContent with the specified this.settings
// by default it calls the setContentElements(this.settings,contentElement) method
DialogManager.prototype.initContent = function(contentElement){
	setContentElements(this.settings,contentElement)
}

// Sets the values (inscriptions) and actions of OK and Cancel buttons
DialogManager.prototype.setDialogButtons = function(dlgWin){
	dlgWin.okButton.innerHTML = this.ok;
	dlgWin.okButton.onclick = function(){dlgWin.action()}
	dlgWin.cancelButton.innerHTML = this.cancel;
	dlgWin.cancelButton.dialog = this;
	dlgWin.cancelButton.onclick = function(){this.dialog.closeDialog(dlgWin)}
}

DialogManager.prototype.closeDialog = function(dlgWin){
	dlgWin.close()
}

DialogManager.prototype.setCaption = function(caption){
	this.caption = caption
}

// evalutes the settings for current content
DialogManager.prototype.evaluateContentSettings = function(contentElement){ 
	return getContentElementsSettings(contentElement);
};

// init the settings for current content
// this method is designed to be invoked no more than once during the main page loading
DialogManager.prototype.initContentSettings = function(contentElement,settings){ 
	return getContentElementsSettings(contentElement,settings,true);
};


// Sets the values from the settings to the inputs and selests 
// which are children of the elemnent. Returns filled settings
// It is important that event handlers calls (onclick, onchange) are in lower case
// otherwise they don't work
function setContentElements(settings,element){
    if (element.nodeType != 1) return
	var tagName = element.tagName.toLowerCase()
	var setting = settings[element.id]
	if ("input" == tagName){
		var inputType = element.type.toLowerCase()
		if ("password" == inputType || "text" == inputType){
			element.value = (setting==null)? "" : setting.value
			if (element.onchange) element.onchange()
		}else if ("file" == inputType){
			element.setAttribute("value",(setting==null)? "" : setting.value)
		}else if  ("checkbox" == inputType || "radio" == inputType){
			element.checked = (setting==null)? element.checked : setting.value
			if (element.onclick && (element.checked || "checkbox" == inputType)){
				element.onclick()
			}
		}
		return
	} 
	if ("textarea" == tagName){
		element.value = (setting==null)? "" : setting.value
		if (element.onchange) element.onchange()
		return
	}
	if ("select" == tagName && !element.multiple){
		element.value= (setting==null)? element.options[0].value : setting.value
		if (element.onchange) element.onchange() 
		return
	}	
	
	for (var i = 0; i < element.childNodes.length; i++){
		setContentElements(settings,element.childNodes[i])
	}
}

// Sets the values to the settings from the inputs and selests 
// which are children of the element
function getContentElementsSettings(element,settings,init){
	if (!settings) settings = new Array()
    if (!element || element.nodeType != 1) return settings
	var tagName = element.tagName.toLowerCase()
	var name = element.id
	if (name){
		if ("input" == tagName){
			var inputType = element.type.toLowerCase()
			if ("password" == inputType || "text" == inputType || "file" == inputType){
				if (!init || !settings[name]) settings[name] = new StringSetting(element.value?element.value:"")
			}else if  ("checkbox" == inputType || "radio" == inputType){
				if (!init || !settings[name]) settings[name] = new Setting(element.checked)
			}
			return settings
		}
		if ("textarea" == tagName){
			if (!init || !settings[name]) settings[name] = new StringSetting(element.value)
			return settings
		}
		if ("select" == tagName && name && !element.multiple && element.value){
			if (!init || !settings[name]) settings[name] = new StringSetting(element.value)
			return settings			
		} 
	}
		
	for (var i = 0; i < element.childNodes.length; i++){
		getContentElementsSettings(element.childNodes[i],settings,init)
	}
	return settings
}

/////////////////////////////////////////////// Storable DialogManager 
// Extends Dialog Manager provides with ability to store
// it's properties on the server
function StorableDialogManager(name,showApply,showCancel){
	this.base = DialogManager;
	this.base(name,showApply,showCancel);
}

StorableDialogManager.prototype = new DialogManager();

// Stores it's settings to the database
StorableDialogManager.prototype.storeSettings = function(){
	if (!top.user) return; // do not post settings
	if (!this.dlgContentId){
		for (n in dlgWindow.registry){
			if (dlgWindow.registry[n] == this){
				this.dlgContentId = n;
				break
			}
		}
	}
	// only for debug (remove in release)
	if (this.dlgContentId == null){
		window.alert("DEBUG: There no Dialog Manager is assigned to the dlgWindow.registry['"+contentElement.id+"']")
		return
	} 
	
	exchangeGate.post("postSettigns.do",this.getStoreParameters())
}

StorableDialogManager.prototype.getStoreParameters = function(){
	return evaluateStoreParameters(this.settings,this.dlgContentId)
}

function evaluateStoreParameters(settings,dlgContentId){
	var parameters = new Array();
	var varPrefix="dlgWindow.registry['"+dlgContentId+"'].settings['"
	for (n in settings){
		var varName = varPrefix+n+"']";
		parameters["gnt."+dlgContentId+"."+n]=settings[n].assignmentStatement(varName);
	}
	return parameters
}

////////////////////////////////////// FilteringDialogManager
function FilteringDialogManager(name,showApply,showCancel){
    this.base = StorableDialogManager;
    this.base(name,showApply,showCancel);
}

FilteringDialogManager.prototype = new StorableDialogManager();

FilteringDialogManager.prototype.acceptMorphemeHighlighting = function(word){return true}


////////////////////////////////////// DoNotShowNextTimeDialogManager
function DoNotShowNextTimeDialogManager(name,showApply,showCancel){
	this.base = DialogManager;
	this.base(name,showApply,showCancel);
}

DoNotShowNextTimeDialogManager.prototype = new DialogManager();
//////////////////////////////////////////////////////////////////D&D FUNCTIONS
// Initiates dragging of the dialog
function initDragDialog(dialogTitleElement,e){
	var evt =  (e)? e : window.event
	dialogTitleElement.dragStartX = evt.clientX
	dialogTitleElement.dragStartY = evt.clientY		
	dialogTitleElement.style.cursor = 'move'
	dialogTitleElement.processDragAndDrop = true
}

// Drags the dialog
function dragDialog(dialogTitleElement,dialogElement,e)
{
	if (dialogTitleElement.processDragAndDrop){
		var evt =  (e)? e : window.event
		dialogElement = dialogElement?dialogElement:getDialogElement(dialogTitleElement)
		dialogElement.style.left = dialogElement.offsetLeft + evt.clientX - dialogTitleElement.dragStartX
		dialogElement.style.top = dialogElement.offsetTop + evt.clientY - dialogTitleElement.dragStartY
		dialogTitleElement.style.cursor = 'move'
		dialogTitleElement.dragStartX = evt.clientX
		dialogTitleElement.dragStartY = evt.clientY
	} else dropDialog(dialogTitleElement)
}

// Returns the whole dialog element by the title element
function getDialogElement(element){
	return (element.parentNode == document.body)? element : getDialogElement(element.parentNode);
}		

// Drops dialog element
function dropDialog(dialogTitleElement){
	dialogTitleElement.processDragAndDrop = false
	dialogTitleElement.dragStartX = 0
	dialogTitleElement.dragStartY = 0
	dialogTitleElement.style.cursor='default'
}
