
import { ModbusRequestContainer } from '/sd:modbus-request-container.js'; 
import { BasicContainer } from '/sd:basic-container.js'; 
import { StandardLabel } from '/sd:standard-label.js'; 
import { ActionButton } from '/sd:action-button.js'; 
import { ActionButtonWithValue } from '/sd:action-button-with-value.js'; 
import { NumericSetPoint } from '/sd:numeric-set-point.js';
import { BooleanPoint } from '/sd:boolean-point.js';
import { BooleanSetPoint } from '/sd:boolean-set-point.js';
import { EventField } from '/sd:event-field.js';
import { BasicInput } from '/sd:basic-input.js';
import { EnumDefinition } from '/sd:enum-definition.js';
import { Point } from '/sd:point.js';
import { Debug } from '/sd:debug.js';

/**
 * class to create instance of dialog window to setting new boolean or numeric values. It sends new value into choosen Regiser immediately over Modbus TCP
 */
export class DialogWindow extends BasicContainer {
	/**
	 * Constructor
	 * @param    {jQuery} xmlObject    			Data loaded from XML
	 * @param    {String} parentId    			HTML ID of the object, which has to be a parent of constructing object
	 * @param    {Collection} valueAttributes 	Collection of event value attributes {"unit": "", "scale": 1.0, "floatSeparator": "dot", "enum": "", "falseText": "", "trueText": ""}
	 * @param 	 {jQuery} enumsDefXmlObject  	Data loaded from XML - accept enums definition part only
	 */
	constructor(xmlObject, parentId = "site", valueAttributes, enumsDefXmlObject) {
		super(xmlObject, parentId, "BasicContainer", null, "dialogWindow", true); 
		this.count = parseInt(xmlObject[0].attributes.count.value);
		var basicInputsXmlObject = $(xmlObject).find('basicinput');
		this.setValueAttributes(valueAttributes, enumsDefXmlObject);

		//top bar label
		this.childLabel = new StandardLabel(null, "dialogWindow", "BasicContainer", null, "dialogWindowLabel", true);
		this.childLabel.setTextValue(window.choosenLexicon.getLexiconMarkupText("dialogWindowSetValueTitle") + ": ");
		this.type = null;

		//numeric value
		this.childNumeric = new BasicInput($(basicInputsXmlObject[0]), "dialogWindow", "dialogWindowInputContainer", null, "dialogWindowNumericContainer", "text", "dialogWindowNumeric", "dialogWindowInput", null, null, "dialogWindowNumericLabel", window.choosenLexicon.getLexiconMarkupText("dialogWindowValue"), "dialogWindowSpan", this.floatSeparator, this.clockMode);
		this.childUnit = document.createElement("div");
		this.childUnit.setAttribute("id", "dialogWindowUnit");
		this.childNumeric.mainObj.appendChild(this.childUnit);
		window.theme.setTheme("dialogWindowUnit", "dialogWindow");
		this.childUnitText = document.createElement("div");
		this.childUnitText.setAttribute("id", "dialogWindowUnitText");
		this.childUnit.appendChild(this.childUnitText);
		//Enum value
		var values = new Array();
		var labels = new Array();
		var element = null;
		for(var i = 0; i < this.enum.getItemsLength(); i++) {
			element = this.enum.getElByIndex(i);
			values.push(element.value); 
			labels.push(element.label);
		}

		this.childEnum = new BasicInput($(basicInputsXmlObject[0]), "dialogWindow", "dialogWindowInputContainer", null, "dialogWindowEnumContainer", "select", "dialogWindowEnum", "dialogWindowInput", values, labels, "dialogWindowEnumLabel", window.choosenLexicon.getLexiconMarkupText("dialogWindowValue"), "dialogWindowSpan", this.floatSeparator, this.clockMode);
		//Boolean value
		values = new Array();//TODO - veryfi it looks like duplication
		labels = new Array();
		values.push("false"); 
		labels.push(this.falseText);
		values.push("true"); 
		labels.push(this.trueText);
		this.childBoolean = new BasicInput($(basicInputsXmlObject[0]), "dialogWindow", "dialogWindowInputContainer", null, "dialogWindowBooleanContainer", "select", "dialogWindowBoolean", "dialogWindowInput", values, labels,"dialogWindowBooleanLabel", window.choosenLexicon.getLexiconMarkupText("dialogWindowValue"), "dialogWindowSpan", this.floatSeparator, this.clockMode);
		//day of week field
		values = new Array();
		labels = new Array();
		for(var i = 1; i <= 7; i++) {
			values.push("day" + String(i)); 
			labels.push(window.choosenLexicon.getLexiconMarkupText(values[i-1]));
		}
		if(basicInputsXmlObject.length > 1) { //if scheduler
			this.childDayOfWeek = new BasicInput($(basicInputsXmlObject[1]), "dialogWindow", "dialogWindowInputContainer", null, "dialogWindowDayOfWeekContainer", null, "dialogWindowDayOfWeek", "dialogWindowInput", values, labels, "dialogWindowDayOfWeekLabel", window.choosenLexicon.getLexiconMarkupText("dialogWindowDayOfWeek"), "dialogWindowSpan", this.floatSeparator, this.clockMode);
			//startTime field
			this.childStartTime = new BasicInput($(basicInputsXmlObject[2]), "dialogWindow", "dialogWindowInputContainer", null, "dialogWindowStartTimeContainer", null, "dialogWindowStartTime", "dialogWindowInput", null, null, "dialogWindowStartTimeLabel", window.choosenLexicon.getLexiconMarkupText("dialogWindowStartTime"), "dialogWindowSpan", this.floatSeparator, this.clockMode);
			//endTime field
			this.childEndTime = new BasicInput($(basicInputsXmlObject[3]), "dialogWindow", "dialogWindowInputContainer", null, "dialogWindowEndTimeContainer", null, "dialogWindowEndTime", "dialogWindowInput", null, null, "dialogWindowEndTimeLabel", window.choosenLexicon.getLexiconMarkupText("dialogWindowEndTime"), "dialogWindowSpan", this.floatSeparator, this.clockMode);
		}

		//warning text
		this.childWarningText = document.createElement("span");
		this.childWarningText.setAttribute("id", "dialogWindowWarningText");
		this.mainObj.appendChild(this.childWarningText);
		//buttons
		this.childOkButton = new ActionButton(null, "dialogWindow", "dialogWindow.confirm();", null, "dialogWindowButton", "dialogWindowButtonOK", true);
		this.childOkButton.setLabelText(window.choosenLexicon.getLexiconMarkupText("dialogWindowButtonOK"));
		this.childCancelButton = new ActionButton(null, "dialogWindow", "dialogWindow.setVisibility(false);", null, "dialogWindowButton", "dialogWindowButtonCancel", true);
		this.childCancelButton.setLabelText(window.choosenLexicon.getLexiconMarkupText("dialogWindowButtonCancel"));
		
		//value ranges
		this.highLimit = 32767.0;
		this.lowLimit = -32768.0;
		this.decimalPlaces = 0;
		
		//other definitions
		this.visibility = false;
		this.object = null;
		this.AllDaysEvents = null;
		this.allDayEvents = null;
		this.allDayEventsTemporary = null;
		this.thisEventIndex = null;
		this.thisDayIndex = null;
		this.eventsPerDay = null;
	}

	/**
	 * Adds all enum options of the numeric set point (working as an enum) to the HTML select object
	 * @param {NumericSetPoint} object		Instance of NumericSetPoint class
	 */
	addAllEnumOptions(object) {
		var value = object.getValue();
		var enumObject = (object instanceof ActionButtonWithValue || object instanceof EventField) ? object.point.enum : object.enum;
		for(var i = 0; i < enumObject.getItemsLength(); i++) {
			var element = enumObject.getElByIndex(i);
			this.addEnumOption(element.value, element.label, (element.value == value) ? true : false);
		}
	}

	/**
	 * Adds all enum options of the numeric set point (working as an enum) to the HTML select object
	 * @param {Integer} value		Value of the enum item
	 * @param {String} label		Label text of the enum item
	 * @param {Boolean} selected	If true, this option will be selected, if false then not
	 */
	addEnumOption(value, label, selected=false) {
		var newEnumOption = document.createElement("option");
		newEnumOption.setAttribute("id", "dialogWindowEnumOption" + String(value));
		newEnumOption.setAttribute("value", String(value));
		newEnumOption.setAttribute("style", "font-size:200%;");
		this.childEnum.childSelect.appendChild(newEnumOption);
		//choose proper value
		if(selected == true) {
			this.setEnum(value);
		}
		document.getElementById("dialogWindowEnumOption" + String(value)).innerHTML = String(label);
	}
	
	/**
	 * Sets highLimit, lowLimit and decimalPlaces of NumericSetPoint editing value 
	 * @param {Float} scale		Scale of the NumericSetPoint instance
	 */
	adjustValueRanges(scale) {
		this.decimalPlaces = Point.calculateDecimalPlaces(scale);
		this.highLimit = parseFloat(32767.0 * scale).toFixed(this.decimalPlaces);
		this.lowLimit = parseFloat(-32768.0 * scale).toFixed(this.decimalPlaces);
	}

	/**
	 * Changes the day of week - deletes created in old selected day, and try to add it in new selected day
	 * @returns {Boolean}		False if event moving was done; True if any warning occured
	 */
	changeDayIndex() {
		var result = false;
		var dayOfWeek = this.getDayOfWeek();
		var newStartTime = this.getStartTime();
		var newEndTime = this.getEndTime();
		if(DialogWindow.checkTime(newStartTime, newEndTime)) {
			//try to add event in new day
			var freeEventIndex = EventField.findFirstFreeDefaultEvent(this.allDayEvents, 0, newStartTime, newEndTime);
			if(freeEventIndex == -1) {	//no free events
				this.showErrorAndSelectField("dialogWindowWarning", "dialogWindowDayOfWeek");
				result = true;
			}
			else {
				//add event in new day
				EventField.setEvent(this.AllDaysEvents[dayOfWeek], freeEventIndex, this.eventsPerDay, newStartTime, newEndTime, true, null, this.type);
				//remove event in old day:
				EventField.setEvent(this.allDayEvents, this.thisEventIndex, this.eventsPerDay, 1500, 1500, true, 0, this.type);
				//change references
				this.allDayEvents = this.AllDaysEvents[dayOfWeek];
				this.thisEventIndex = freeEventIndex;
				this.thisDayIndex = dayOfWeek;
				//copy new Array to temporary array: 
				this.createTemporaryDayEventsArray();
			}
		}
		return result;
	}
	
	/**
	 * Checks if input value is in limits range, and verifes decimalPlaces of input value
	 * @param {Float} value		Input value
	 * @returns {Integer}		Status of value verification: 0 - proper value; 1 - out of range; 2 - to many decimal places
	 */
	checkValue(value) {
		if(value > this.highLimit || value < this.lowLimit)
			return 1;
		else if(this.decimalPlaces < DialogWindow.verifyDecimalPlacesOfValue(value))
			return 2;
		else {
			return 0;
		}
	}

	/**
	 * Checks the startTime and endTime of event
	 * @param {Integer} startTime 	Start time
	 * @param {Integer} endTime 	End time
	 * @returns {Boolean}			True if relation is proper, and false if not
	 */
	static checkTime(startTime, endTime) {
		return (startTime < endTime) && (startTime >= 0 && startTime < 1440 && endTime <= 1500);
	}
	
	/**
	 * The method depends on "OK" button clicking - it gets edited new value, and sends it over Modbus TCP to AAC20. It hides the DialogWindow, and unlocks last window
	 */
	confirm() {
		if(this.object != null) {
			if(this.object instanceof BooleanSetPoint || (this.object instanceof ActionButtonWithValue && this.object.getPointType() == "boolean")) {
				var newBitValue = this.getBoolean();
				var val = window.modbusReader[ModbusRequestContainer.findModbusNetworkIndex(this.object.getPointRefreshFrequency(), window.modbusReader)].getRegisterValue(this.object.getModbusRegisterAddress());
				if(val != null && newBitValue != null) {
					this.object.setState(newBitValue);
					val = Math.round(val);
					if(newBitValue)
						val |= (1 << this.object.getBitNumber());
					else
						val &= (~(1 << this.object.getBitNumber()));
					ModbusRequestContainer.sendValueOverModbusTcp(this.object.getModbusRegisterAddress(), val);
				}
				else
					console.log("Setting new value error!");
				
				this.setVisibility(false);
			}
			else if(this.object instanceof NumericSetPoint || this.object instanceof ActionButtonWithValue) {
				if(this.object.getPointType() == "numeric") {
					var val = String(this.getNumeric());
					if(val.indexOf(this.object.getUnit()) > 0)
						val = val.split(this.object.getUnit()).slice(0, -1).join(this.object.getUnit());
					val = val.trim();
					val = parseFloat(String(val).replace(",","."));
				}
				else if(this.object.getPointType() == "enum") {
					var val = this.getEnum();
					val = parseFloat(val);
				}
				else
					console.log("Not supported type of point: " + this.object.getPointType());
				if(val != NaN) {
					var check = this.checkValue(val);
					if(check == 0) {
						this.object.setValue(val);
						this.object.setTextValue();
						ModbusRequestContainer.sendValueOverModbusTcp(this.object.getModbusRegisterAddress(), this.object.getValueToSendOverModbusTcp());
						this.setVisibility(false);
					}
					else if(check == 1) {
						this.showErrorAndSelectField("dialogWindowOutOfRangeValue", "dialogWindowNumeric");
					}
					else if(check == 2) {
						this.showErrorAndSelectField("dialogWindowToManyDecimals", "dialogWindowNumeric");
					}
				}
				else
					console.log("Value is NaN!");
			}
			else if(this.object instanceof EventField) {
				var dayOfWeek = this.getDayOfWeek();
				console.log("dayOfWeek: " + String(dayOfWeek) + ", thisDayIndex: " + String(this.thisDayIndex));
				if(dayOfWeek != this.thisDayIndex && this.AllDaysEvents != null && this.thisDayIndex != null)
					if(this.changeDayIndex())
						return;
				//
				var freeEvent = EventField.findFirstFreeDefaultEvent(this.allDayEvents, 0, newStartTime, newEndTime);
				var sendNewTime = false;
				var newDefaultEventAdded = false;
				var index = -1;
				var val = this.getValue();
				var check = this.checkValue(val);
				//var keysArr = new Array();
				//var valuesArr = new Array();
				var verificationNeeded = false;
				var editEvent = false

				if(check == 0) {//if value ok
					var newStartTime = this.getStartTime();
					var newEndTime = this.getEndTime();
					//console.log("newStartTime: " + String(newStartTime) + ", newEndTime: " + String(newEndTime) + ", this.thisEventIndex: " + String(this.thisEventIndex) + ", val: " + String(val));
			
					if(DialogWindow.checkTime(newStartTime, newEndTime) && EventField.checkTimeOverlapsOnNotDefaultEvent(this.allDayEvents, this.thisEventIndex, this.eventsPerDay, newStartTime, newEndTime) == -1) {
						if(this.allDayEvents[this.thisEventIndex].getDefault() == false) { //edit event
							//verify provided startTime
							if(this.allDayEvents[this.thisEventIndex].getStartTime() != newStartTime) {
								for(var i=this.thisEventIndex; i > 0; i--) {
									if((this.allDayEvents[i - 1].getDefault() == false)) { //find until not default event
										if(this.allDayEvents[i - 1].getStopTime() > newStartTime) { //start time error
											this.showErrorAndSelectField("dialogWindowExistedEventStartTime", "dialogWindowStartTime");
											return;
										}
										break;
									}
								}
								EventField.setEvent(this.allDayEvents, this.thisEventIndex, this.eventsPerDay, newStartTime, null, null, null, this.type);
								sendNewTime = true;
							}
							//verify provided endTime
							if(this.allDayEvents[this.thisEventIndex].getStopTime() != newEndTime) {
								for(var i=this.thisEventIndex; i < (this.eventsPerDay - 1); i++) {
									if((this.allDayEvents[i + 1].getDefault() == false)) { //find until not default event
										if(this.allDayEvents[i + 1].getStartTime() < newEndTime) { //start time error
											this.showErrorAndSelectField("dialogWindowExistedEventEndTime", "dialogWindowEndTime");
											return;
										}
										break;
									}
								}
								EventField.setEvent(this.allDayEvents, this.thisEventIndex, this.eventsPerDay, null, newEndTime, null, null, this.type);
								sendNewTime = true;
							}
							editEvent = true;
						}
						else {//add new event
							if(this.allDayEvents[this.thisEventIndex].getStartTime() == newStartTime && this.allDayEvents[this.thisEventIndex].getStopTime() == newEndTime) { //modify default event to not default
								if(this.thisEventIndex == 7 && this.allDayEvents[this.thisEventIndex - 1].getDefault() && this.allDayEvents[this.thisEventIndex - 1].getStartTime() < newStartTime) {
									//no more free events
									this.showErrorAndSelectField("dialogWindowWarning", "dialogWindowStartTime");
									return;
								}
								else {
									EventField.setEvent(this.allDayEvents, this.thisEventIndex, this.eventsPerDay, null, null, false, val, this.type);
									sendNewTime = true;
								}
							}
							else if(this.thisEventIndex > 0 && this.allDayEvents[this.thisEventIndex - 1].getDefault() && (this.allDayEvents[this.thisEventIndex - 1].getStartTime() == newStartTime || this.allDayEvents[this.thisEventIndex - 1].getStopTime() == newEndTime)) {
								//if there are 2 lasts default events only
								EventField.setEvent(this.allDayEvents, this.thisEventIndex, this.eventsPerDay, newStartTime, newEndTime, false, val, this.type);
								sendNewTime = true;
							}
							else if(this.allDayEvents[this.thisEventIndex].getDefault() && (this.allDayEvents[this.thisEventIndex].getStartTime() != newStartTime || this.allDayEvents[this.thisEventIndex].getStopTime() != newEndTime)) {
								EventField.setEvent(this.allDayEvents, this.thisEventIndex, this.eventsPerDay, newStartTime, newEndTime, false, val, this.type);
								sendNewTime = true;
							}
							else {
								//console.log("thisDefault: " + String(this.allDayEvents[this.thisEventIndex].getDefault()) + ", thisStartTime: " + String(this.allDayEvents[this.thisEventIndex].getStartTime()) + ", thisStopTime: " + String(this.allDayEvents[this.thisEventIndex].getStopTime()));
								console.log("No use case");
							}
						}

						//console.log("sendNewTime: " + String(sendNewTime));
						//console.log("ThisStartTime: " + String(this.allDayEvents[this.thisEventIndex].getStartTime()) + ", ThisStopTime: " + String(this.allDayEvents[this.thisEventIndex].getStopTime()) + ", this.thisEventIndex: " + String(this.thisEventIndex));

						if(EventField.verifyIndexShouldBeByStartTime(this.allDayEvents, this.eventsPerDay, this.allDayEvents[this.thisEventIndex].getStartTime()) == 0) {
							console.log(this.thisEventIndex);
	
							var searchingStartTime = this.allDayEvents[this.thisEventIndex].getStartTime();
							var searchingStopTime = this.allDayEvents[this.thisEventIndex].getStopTime();
							var searchingDefault = this.allDayEvents[this.thisEventIndex].getDefault();
							EventField.bubbleSortEvents(this.allDayEvents, this.eventsPerDay);
							this.thisEventIndex = EventField.getEventIndexByValues(this.allDayEvents, this.eventsPerDay, searchingStartTime, searchingStopTime, searchingDefault);
							//console.log(this.thisEventIndex);
						}

						if(sendNewTime) {//verify if adjacent default Events needed and add/modify it
							if(this.thisEventIndex - 1 >= 0) {
								if(this.allDayEvents[this.thisEventIndex].getStartTime() > this.allDayEvents[this.thisEventIndex - 1].getStopTime())
									verificationNeeded = true;
							}
							if(this.thisEventIndex + 1 < this.eventsPerDay) {
								if(this.allDayEvents[this.thisEventIndex].getStopTime() < this.allDayEvents[this.thisEventIndex + 1].getStartTime())
									verificationNeeded = true;
							}

							if(verificationNeeded && (this.thisEventIndex > 0)) { //verify if previous event needed
								if(this.allDayEvents[this.thisEventIndex - 1].getDefault() && (this.allDayEvents[this.thisEventIndex - 1].getStartTime() < newStartTime)) { //stay previous event and change StopTime only
									EventField.setEvent(this.allDayEvents, (this.thisEventIndex - 1), this.eventsPerDay, null, newStartTime, null, null, this.type);
								}
								else if(this.allDayEvents[this.thisEventIndex - 1].getDefault()) { // delete previous event
									if(this.allDayEvents[this.thisEventIndex - 1].getStopTime() != 1500) {
										EventField.setEvent(this.allDayEvents, (this.thisEventIndex - 1), this.eventsPerDay, 1500, 1500, true, null, this.type);
									}
									else {
										console.log("No use case");
									}
								}
								else { //if(this.allDayEvents[this.thisEventIndex - 1].getDefault() == false)
									index = EventField.findFirstFreeDefaultEvent(this.allDayEvents, this.thisEventIndex, newStartTime, newEndTime);
									if(index < 0) { //no more free events
										if(editEvent && this.allDayEvents[this.thisEventIndex + 1].getDefault() && newEndTime == 1500 && this.allDayEvents[this.thisEventIndex - 1].getDefault() == false && this.allDayEvents[this.thisEventIndex - 1].getStopTime() < newStartTime) {
											//edit last default event
											EventField.setEvent(this.allDayEvents, (this.thisEventIndex + 1), this.eventsPerDay, this.allDayEvents[this.thisEventIndex - 1].getStopTime(), newStartTime, null, null, this.type);
										}
										else { //no more free events
											this.showErrorAndSelectField("dialogWindowWarning", "dialogWindowStartTime");
											return;
										}
										EventField.setEvent(this.allDayEvents, this.thisEventIndex, this.eventsPerDay, newStartTime, newEndTime, false, val, this.type);
									}
									else { 
										if(index <= (this.eventsPerDay - 1)) {///////////////////było (index < (this.eventsPerDay - 1))
											if(this.allDayEvents[0].getStartTime() != newEndTime) {
												if((this.thisEventIndex + 1) < this.eventsPerDay && this.allDayEvents[this.thisEventIndex + 1].getDefault() && this.allDayEvents[this.thisEventIndex + 1].getStartTime() == newEndTime) {
													//edit existed Default event
													EventField.setEvent(this.allDayEvents, index, this.eventsPerDay, this.allDayEvents[this.thisEventIndex - 1].getStopTime(), newStartTime, true, 0, this.type);
													newDefaultEventAdded = true;
												}
												else if(editEvent && this.allDayEvents[this.thisEventIndex + 1].getDefault() && this.allDayEvents[this.thisEventIndex + 1].getStopTime() == newEndTime && this.allDayEvents[this.thisEventIndex - 1].getDefault() == false && this.allDayEvents[this.thisEventIndex - 1].getStopTime() < newStartTime) {
													//edit default event
													EventField.setEvent(this.allDayEvents, (this.thisEventIndex + 1), this.eventsPerDay, this.allDayEvents[this.thisEventIndex - 1].getStopTime(), newStartTime, null, null, this.type);
												}
												else if(EventField.freeEventsQuantity(this.allDayEvents, this.eventsPerDay, this.allDayEvents[this.thisEventIndex - 1].getStopTime(), newStartTime) > 0) {
													//add new default event on the end of events list
													EventField.setEvent(this.allDayEvents, index, this.eventsPerDay, this.allDayEvents[this.thisEventIndex - 1].getStopTime(), newStartTime, true, 0, this.type);
													newDefaultEventAdded = true;
												}
												else if(editEvent && this.allDayEvents[this.thisEventIndex + 1].getDefault() && newEndTime == 1500 && this.allDayEvents[this.thisEventIndex - 1].getDefault() == false && this.allDayEvents[this.thisEventIndex - 1].getStopTime() < newStartTime) {
													//edit last default event
													EventField.setEvent(this.allDayEvents, (this.thisEventIndex + 1), this.eventsPerDay, this.allDayEvents[this.thisEventIndex - 1].getStopTime(), newStartTime, null, null, this.type);
												}
												else { //no more free events
													this.showErrorAndSelectField("dialogWindowWarning", "dialogWindowStartTime");
													return;
												}
												EventField.setEvent(this.allDayEvents, this.thisEventIndex, this.eventsPerDay, newStartTime, newEndTime, false, val, this.type);
												if((this.thisEventIndex + 1) < this.eventsPerDay && this.allDayEvents[this.thisEventIndex + 1].getDefault() && this.allDayEvents[this.thisEventIndex + 1].getStopTime() == 1500 && this.allDayEvents[this.thisEventIndex + 1].getStartTime() != this.allDayEvents[this.thisEventIndex].getStopTime()) {
													EventField.setEvent(this.allDayEvents, this.thisEventIndex + 1, this.eventsPerDay, newEndTime, null, null, null, this.type);
												}
											}
											else {//add new default event on the end of events list
												EventField.setEvent(this.allDayEvents, index, this.eventsPerDay, this.allDayEvents[this.thisEventIndex - 1].getStopTime(), newStartTime, true, 0, this.type);
											}
										}
										else { //no more free events
											this.showErrorAndSelectField("dialogWindowWarning", "dialogWindowStartTime");
											return;
										}
									}
								}
							}
							else {
								EventField.setEvent(this.allDayEvents, this.thisEventIndex, this.eventsPerDay, newStartTime, newEndTime, false, val, this.type);
								if(this.thisEventIndex > 0) {
									if(this.thisEventIndex == 7) {
										if(this.allDayEvents[this.thisEventIndex - 1].getDefault() && this.allDayEvents[this.thisEventIndex - 1].getStopTime() == 1500) { //Update startTime of prevous last and default event
											if(newEndTime == 1500)
												EventField.setEvent(this.allDayEvents, (this.thisEventIndex - 1), this.eventsPerDay, null, newStartTime, null, null, this.type);
											else if(EventField.freeEventsQuantity(this.allDayEvents, this.eventsPerDay, newEndTime, 1500) > 0) {
												EventField.setEvent(this.allDayEvents, (this.thisEventIndex - 1), this.eventsPerDay, newEndTime, 1500, null, null, this.type);
											}
											else if(this.allDayEvents[this.thisEventIndex - 1].getDefault() && this.allDayEvents[this.thisEventIndex - 1].getStartTime() == this.allDayEvents[this.thisEventIndex].getStartTime()) {
												EventField.setEvent(this.allDayEvents, (this.thisEventIndex - 1), this.eventsPerDay, newEndTime, 1500, null, null, this.type);
											}
											else { //no more free events
												this.showErrorAndSelectField("dialogWindowWarning", "dialogWindowStartTime");
												return;
											}
										}
										else if(this.allDayEvents[this.thisEventIndex - 1].getDefault() && this.allDayEvents[this.thisEventIndex - 1].getStopTime() < 1500) {
											EventField.setEvent(this.allDayEvents, (this.thisEventIndex - 1), this.eventsPerDay, newEndTime, 1500, null, null, this.type);
										}
										else
											console.log("No use case");
									}
									else {
										if(this.allDayEvents[this.thisEventIndex - 1].getDefault() && this.allDayEvents[this.thisEventIndex - 1].getStopTime() == 1500) {
											//if previous event is default, then that previous event can't be the first in the array, so there is possible request about event (this.thisEventIndex - 2)
											if(this.allDayEvents[this.thisEventIndex - 2].getDefault()) {
												EventField.setEvent(this.allDayEvents, (this.thisEventIndex - 1), this.eventsPerDay, newEndTime, null, null, null, this.type);
											}
											else {
												EventField.setEvent(this.allDayEvents, (this.thisEventIndex - 1), this.eventsPerDay, null, newStartTime, null, null, this.type);
											}
										}
										else {
											EventField.setEvent(this.allDayEvents, (this.thisEventIndex + 1), this.eventsPerDay, newEndTime, null, null, null, this.type);
										}
									}
								}
								else {//if(this.thisEventIndex == 0)
									if(this.allDayEvents[this.thisEventIndex + 1].getDefault() && this.allDayEvents[this.thisEventIndex + 2].getStartTime() == newEndTime) {
										//delete default event if it is needed
										EventField.setEvent(this.allDayEvents, (this.thisEventIndex + 1), this.eventsPerDay, 1500, 1500, null, null, this.type);
									}
									else if(this.allDayEvents[this.thisEventIndex + 1].getDefault() && this.allDayEvents[this.thisEventIndex + 1].getStartTime() != newEndTime) {
										//fix startTime of next default event
										EventField.setEvent(this.allDayEvents, (this.thisEventIndex + 1), this.eventsPerDay, newEndTime, null, true, null, this.type);
									}
									else
										console.log("No use case");
								}
							}
							/*keysArr = new Array();
							valuesArr = new Array();
							for(var p=0; p < this.eventsPerDay; p++) {
								keysArr.push("StartTime" + String(p));
								keysArr.push("StopTime" + String(p));
								keysArr.push("Default" + String(p));
								valuesArr.push(this.allDayEvents[p].getStartTime());
								valuesArr.push(this.allDayEvents[p].getStopTime());
								valuesArr.push(this.allDayEvents[p].getDefault());
							}
							Debug.traceTable(keysArr, valuesArr, "DialogWindow-confirm{" + String(this.eventsPerDay) +"}");
							console.log(this.thisEventIndex);*/

							searchingStartTime = this.allDayEvents[this.thisEventIndex].getStartTime();
							searchingStopTime = this.allDayEvents[this.thisEventIndex].getStopTime();
							searchingDefault = this.allDayEvents[this.thisEventIndex].getDefault();
							EventField.bubbleSortEvents(this.allDayEvents, this.eventsPerDay);
							this.thisEventIndex = EventField.getEventIndexByValues(this.allDayEvents, this.eventsPerDay, searchingStartTime, searchingStopTime, searchingDefault);

							/*console.log(this.thisEventIndex);
							keysArr = new Array();
							valuesArr = new Array();
							for(var p=0; p < this.eventsPerDay; p++) {
								keysArr.push("StartTime" + String(p));
								keysArr.push("StopTime" + String(p));
								keysArr.push("Default" + String(p));
								valuesArr.push(this.allDayEvents[p].getStartTime());
								valuesArr.push(this.allDayEvents[p].getStopTime());
								valuesArr.push(this.allDayEvents[p].getDefault());
							}
							Debug.traceTable(keysArr, valuesArr, "DialogWindow-confirm{" + String(this.eventsPerDay) +"}");*/

							//clear duplicates
							EventField.deleteDuplicateEvents(this.allDayEvents, this.eventsPerDay, this.type);
							/*console.log(this.thisEventIndex);
							keysArr = new Array();
							valuesArr = new Array();
							for(var p=0; p < this.eventsPerDay; p++) {
								keysArr.push("StartTime" + String(p));
								keysArr.push("StopTime" + String(p));
								keysArr.push("Default" + String(p));
								valuesArr.push(this.allDayEvents[p].getStartTime());
								valuesArr.push(this.allDayEvents[p].getStopTime());
								valuesArr.push(this.allDayEvents[p].getDefault());
							}
							Debug.traceTable(keysArr, valuesArr, "DialogWindow-confirm{" + String(this.eventsPerDay) +"}");*/

							if(verificationNeeded && this.thisEventIndex < (this.eventsPerDay - 1)) { //verify if next event needed
								if(this.allDayEvents[this.thisEventIndex + 1].getDefault() && (this.allDayEvents[this.thisEventIndex + 1].getStopTime() > newEndTime)) { //stay next event and change StartTime only
									EventField.setEvent(this.allDayEvents, (this.thisEventIndex + 1), this.eventsPerDay, newEndTime, null, null, null, this.type);
								}
								else if(this.allDayEvents[this.thisEventIndex + 1].getDefault() && this.allDayEvents[this.thisEventIndex + 1].getStartTime() < 1500 && newDefaultEventAdded == false) { // delete next event
									EventField.setEvent(this.allDayEvents, (this.thisEventIndex + 1), this.eventsPerDay, 1500, 1500, true, null, this.type);
								}
								else if(this.allDayEvents[this.thisEventIndex + 1].getDefault() == false) {
									index = EventField.findFirstFreeDefaultEvent(this.allDayEvents, this.thisEventIndex, newStartTime, newEndTime);
									if(index < 0) { //no more free events
										this.showErrorAndSelectField("dialogWindowWarning", "dialogWindowStartTime");
										return;
									}
									else { //add new default event on the end of events list
										if(newEndTime < 1500) {
											if(EventField.freeEventsQuantity(this.allDayEvents, this.eventsPerDay, newStartTime, newEndTime) > 0) {
												EventField.setEvent(this.allDayEvents, index, this.eventsPerDay, newEndTime, this.allDayEvents[this.thisEventIndex + 1].getStartTime(), true, 0, this.type);
											}
											else { //no more free events
												this.showErrorAndSelectField("dialogWindowWarning", "dialogWindowStartTime");
												return;
											}
											//EventField.setEvent(this.allDayEvents, this.thisEventIndex, this.eventsPerDay, newStartTime, newEndTime, false, val, this.type);
										}
										else
											console.log("Not defined case");
									}
								}
								else if(newDefaultEventAdded) {
									index = EventField.findFirstFreeDefaultEvent(this.allDayEvents, this.thisEventIndex, newStartTime, newEndTime);
									if(index < 0) { //no more free events
										this.showErrorAndSelectField("dialogWindowWarning", "dialogWindowStartTime");
										return;
									}
									else { //add new default event on the end of events list
										if(newEndTime < 1500) {
											EventField.setEvent(this.allDayEvents, index, this.eventsPerDay, newEndTime, 1500, true, 0, this.type);
										}
										else
											console.log("Not defined case");
									}
								}
								else
									console.log("No use case");
							}
							else if(verificationNeeded && (this.thisEventIndex == (this.eventsPerDay - 1)) && (newEndTime < 1500)) {
								if(this.allDayEvents[this.thisEventIndex].getDefault() == true && this.allDayEvents[this.thisEventIndex].getStartTime() == 1500) {// only last free default event
									//verify if new event will be neighbour with  other existed event
									var neighbour = false;
									for(var i=0; i < (this.eventsPerDay - 1); i++) {
										if(this.allDayEvents[i].getStartTime() == newEndTime || this.allDayEvents[i].getStopTime() == newStartTime) {
											neighbour = true;
											break;
										}
									}
									if(neighbour) { //ad event
										EventField.setEvent(this.allDayEvents, this.thisEventIndex, this.eventsPerDay, newStartTime, newEndTime, false, val, this.type);
									}
									else {//no more free events
										console.log("No more events");
										this.showErrorAndSelectField("dialogWindowWarning", "dialogWindowStartTime");
										return;
									}
								}
								else {//no more free events
									console.log("No more events");
									this.showErrorAndSelectField("dialogWindowWarning", "dialogWindowStartTime");
									return;
								}
							}
							else if(verificationNeeded)
								console.log("Not defined case");
							else
								console.log("No use case");
							/*keysArr = new Array();
							valuesArr = new Array();
							for(var p=0; p < this.eventsPerDay; p++) {
								keysArr.push("StartTime" + String(p));
								keysArr.push("StopTime" + String(p));
								keysArr.push("Default" + String(p));
								valuesArr.push(this.allDayEvents[p].getStartTime());
								valuesArr.push(this.allDayEvents[p].getStopTime());
								valuesArr.push(this.allDayEvents[p].getDefault());
							}
							Debug.traceTable(keysArr, valuesArr, "DialogWindow-confirm{" + String(this.eventsPerDay) +"}");*/
							EventField.bubbleSortEvents(this.allDayEvents, this.eventsPerDay);
						}
						else if(sendNewTime && (freeEvent == (this.eventsPerDay - 1))) { //only one event free
							EventField.setEvent(this.allDayEvents, freeEvent, this.eventsPerDay, newStartTime, newEndTime, false, val, this.type);
						}
						else if((!sendNewTime) && this.allDayEvents[this.thisEventIndex].getDefault() == false && this.allDayEvents[this.thisEventIndex].getStartTime() == newStartTime && this.allDayEvents[this.thisEventIndex].getStopTime() == newEndTime) {
							EventField.setEvent(this.allDayEvents, this.thisEventIndex, this.eventsPerDay, null, null, null, val, this.type);
						}
						else if((!sendNewTime) && (freeEvent != -1)) { //only one event free
							EventField.setEvent(this.allDayEvents, freeEvent, this.eventsPerDay, newStartTime, newEndTime, false, val, this.type);
						}
						else {
							this.showErrorAndSelectField("dialogWindowWarning", "dialogWindowStartTime");
							return;
						}
					}
					else { //Time not proper
						var overlapsed = EventField.checkTimeOverlapsOnNotDefaultEvent(this.allDayEvents, this.thisEventIndex, this.eventsPerDay, newStartTime, newEndTime);
						if(overlapsed >= 0)
						{
							if(this.allDayEvents[overlapsed].getStartTime() <= newStartTime && this.allDayEvents[overlapsed].getStopTime() > newStartTime)
								this.showErrorAndSelectField("dialogWindowExistedEventStartTime", "dialogWindowStartTime");
							else if(this.allDayEvents[overlapsed].getStartTime() < newEndTime && this.allDayEvents[overlapsed].getStopTime() >= newEndTime)
								this.showErrorAndSelectField("dialogWindowExistedEventEndTime", "dialogWindowEndTime");
							else
								this.showErrorAndSelectField("dialogWindowStartAndEndTimeWrong", "dialogWindowStartTime");
						}
						else //newStartTime and/or newEndTime wrong
							this.showErrorAndSelectField("dialogWindowStartAndEndTimeWrong", "dialogWindowStartTime");
						return;
					}

					/*keysArr = new Array();
					valuesArr = new Array();
					for(var p=0; p < this.eventsPerDay; p++) {
						keysArr.push("StartTime" + String(p));
						keysArr.push("StopTime" + String(p));
						keysArr.push("Default" + String(p));
						valuesArr.push(this.allDayEvents[p].getStartTime());
						valuesArr.push(this.allDayEvents[p].getStopTime());
						valuesArr.push(this.allDayEvents[p].getDefault());
					}
					Debug.traceTable(keysArr, valuesArr, "DialogWindow-confirm{" + String(this.eventsPerDay) +"}");*/
					//clear duplicates
					EventField.deleteDuplicateEvents(this.allDayEvents, this.eventsPerDay, this.type);

					/*keysArr = new Array();
					valuesArr = new Array();
					for(var p=0; p < this.eventsPerDay; p++) {
						keysArr.push("StartTime" + String(p));
						keysArr.push("StopTime" + String(p));
						keysArr.push("Default" + String(p));
						valuesArr.push(this.allDayEvents[p].getStartTime());
						valuesArr.push(this.allDayEvents[p].getStopTime());
						valuesArr.push(this.allDayEvents[p].getDefault());
					}
					Debug.traceTable(keysArr, valuesArr, "DialogWindow-confirm{" + String(this.eventsPerDay) +"}");

					//print temporary Data
					console.log(this.allDayEventsTemporary);
					keysArr = new Array();
					valuesArr = new Array();
					for(var p=0; p < this.eventsPerDay; p++) {
						keysArr.push("StartTime" + String(p));
						keysArr.push("StopTime" + String(p));
						keysArr.push("Default" + String(p));
						valuesArr.push(this.allDayEventsTemporary[p].startTime);
						valuesArr.push(this.allDayEventsTemporary[p].stopTime);
						valuesArr.push(this.allDayEventsTemporary[p].default);
					}
					Debug.traceTable(keysArr, valuesArr, "DialogWindow-confirm-allDayEventsTemporary");*/

					//last sorting and sending values
					EventField.bubbleSortEvents(this.allDayEvents, this.eventsPerDay)
					if(this.allDayEvents[7].getStopTime() != 1500) {
						//if last event isn't finished at 1500 second, then restore data and print warning
						this.showErrorAndSelectField("dialogWindowWarning", "dialogWindowStartTime");
						return;
					}
					else {
						EventField.sendMultipleEventsByModbus([this.allDayEvents], 0, 0, 0, (this.eventsPerDay - 1), this.eventsPerDay);
					}
					this.setVisibility(false);

					/*keysArr = new Array();
					valuesArr = new Array();
					for(var p=0; p < this.eventsPerDay; p++) {
						keysArr.push("StartTime" + String(p));
						keysArr.push("StopTime" + String(p));
						keysArr.push("Default" + String(p));
						valuesArr.push(this.allDayEvents[p].getStartTime());
						valuesArr.push(this.allDayEvents[p].getStopTime());
						valuesArr.push(this.allDayEvents[p].getDefault());
					}
					Debug.traceTable(keysArr, valuesArr, "DialogWindow-confirm{" + String(this.eventsPerDay) +"}");*/
				}
				else if(check == 1) {
					this.showErrorAndSelectField("dialogWindowOutOfRangeValue", "dialogWindowNumeric");
				}
				else if(check == 2) {
					this.showErrorAndSelectField("dialogWindowToManyDecimals", "dialogWindowNumeric");
				}
				else
					console.log("No use case");
			}
			else 
				console.log("Dialog window invoked by unexpected class instance object!");	
		}
		else 
			console.log("Dialog window invoked by null pointer reference!");
	}

	/**
	 * Creates temporary and independent data of this.allDayEvents array
	 */
	createTemporaryDayEventsArray() {
		this.allDayEventsTemporary = new Array();
		for(var i = 0; i < this.eventsPerDay; i++) {
			this.allDayEventsTemporary.push({"startTime": this.allDayEvents[i].getStartTime(), "stopTime": this.allDayEvents[i].getStopTime(), "default": this.allDayEvents[i].getDefault(), "value": this.allDayEvents[i].getValue()})
		}
	}
	
	/**
	 * Flushes all enum options in select HTML object for enum editing in DialogWindow
	 */
	flushEnumOptions() {
		var selectInput = document.getElementById("dialogWindowEnum");
		while (selectInput.hasChildNodes()) {
			selectInput.removeChild(selectInput.firstChild);
		}
	}
	
	/**
	 * Gets selected boolean value from selector located on DialogWindow
	 * @returns {Boolean}	Selected boolean value
	 */
	getBoolean() {
		return BooleanPoint.parseBoolean(document.getElementById("dialogWindowBoolean").value);
	}

	/**
	 * Gets entered day of week value from select box located on DialogWindow
	 * @returns {String}	Entered day of week value
	 */
	getDayOfWeek() {
		return this.childDayOfWeek.getValue();
	}

	/**
	 * Gets entered end time value from input time box located on DialogWindow
	 * @returns {Integer}	Entered end time value
	 */
	getEndTime() {
		var val = this.childEndTime.getValue();
		return (val == 0) ? 1500 : val;
	}
	
	/**
	 * Gets selected enum option value from selector located on DialogWindow
	 * @returns {Integer}	Selected enum option value
	 */
	getEnum() {
		return parseInt(document.getElementById("dialogWindowEnum").value);
	}

	/**
	 * Gets entered numeric value from input text box located on DialogWindow
	 * @returns {Float}	Entered numeric value
	 */
	getNumeric() {
		return parseFloat(document.getElementById("dialogWindowNumeric").value.replace(",", "."));
	}

	/**
	 * Gets entered start time value from input time box located on DialogWindow
	 * @returns {Integer}	Entered start time value
	 */
	getStartTime() {
		return this.childStartTime.getValue();
	}

	/**
	 * Gets entered value from input box located on DialogWindow
	 * @returns {Object}	Current value
	 */
	getValue() {
		if(this.type == "numeric") {
			return this.getNumeric();
		}
		else if(this.type == "enum") {
			return this.getEnum();
		}
		else if(this.type == "boolean") {
			return this.getBoolean();
		}
		else 
			return null;
	}
	
	/**
	 * Gets visibility status of the DialogWindow 
	 * @returns {Boolean}	True if DialogWindow is shown, false if it is hidden
	 */
	getVisibility() {
		return this.visibility;
	}

	/**
	 * Restores temporary values from this.allDayEventsTemporary in this.allDayEvents
	 */
	restoreTemporaryDayEventsValues() {
		for(var i = 0; i < this.eventsPerDay; i++) {
			this.allDayEvents[i].setDefault(this.allDayEventsTemporary[i].default);
			this.allDayEvents[i].setStartTime(this.allDayEventsTemporary[i].startTime);
			this.allDayEvents[i].setStopTime(this.allDayEventsTemporary[i].stopTime);
			this.allDayEvents[i].setValue(this.allDayEventsTemporary[i].value);
		}
	}

	/**
	 * Changes the background opacity and pointer-events of the chosen HTML object
	 * @param {String} backgroundId 	ID of the HTML object
	 * @param {Float} opacityLevel 		Opacity style value level (between 0.0 and 1.0)
	 * @param {String} pointer 			Pointer-events style value
	 */
	static setBackground(backgroundId, opacityLevel, pointer) {
		var obj = document.getElementById(backgroundId);
		if(obj == null) 
			obj.setAttribute("style", "pointer-events: " + pointer + "; opacity: " + String(opacityLevel) + ";");
		else {
			obj.style.setProperty("pointer-events", pointer);
			obj.style.setProperty("opacity", opacityLevel);
		}
	}
	
	/**
	 * Changes boolean value selector (texts represerntation) and selects chosen option item
	 * @param {Boolean} value 		Input value
	 * @param {String} trueText 	True text
	 * @param {String} falseText 	False text
	 */
	setBoolean(value, trueText = null, falseText = null) {
		var elem = document.getElementById('dialogWindowBoolean');
		elem.options.selectedIndex = (value == true) ? 1 : 0;
		if(trueText == null || trueText == "" || falseText == null || falseText == "") {
			trueText = window.choosenLexicon.getLexiconMarkupText("defaultTrueText");
			falseText = window.choosenLexicon.getLexiconMarkupText("defaultFalseText");
		}
		document.getElementById("dialogWindowBooleanTrue").innerHTML = trueText;
		document.getElementById("dialogWindowBooleanFalse").innerHTML = falseText;
	}

	/**
	 * Sets day of week value to select box located on DialogWindow
	 * @param {String} value 	Day of week value
	 */
	setDayOfWeek(value) {
		this.childDayOfWeek.setValue(value);
	}

	/**
	 * Sets end time value to input time box located on DialogWindow
	 * @param {Integer} value 	Start end value
	 */
	setEndTime(value) {
		this.childEndTime.setValue(value);
	}
	
	/**
	 * Selects chosen option item of the enum
	 * @param {Integer} value	Input value
	 */
	setEnum(value) {
		var elem = document.getElementById('dialogWindowEnum');
		elem.options.selectedIndex = value;
	}

	/**
	 * Sets label text of the edited point in top bar in DialogWindow
	 * @param {String} text		Label text
	 */
	setLabelText(text) {
		document.getElementById('dialogWindowLabel').innerHTML = text;
	}
	
	/**
	 * Puts value to numeric input text box, and unit to the unit label
	 * @param {Float} value 	input value
	 * @param {String} unit 	unit
	 */
	setNumeric(value, unit) {
		var elem = document.getElementById('dialogWindowNumeric');
		if(elem.hasAttribute("value"))
			elem.value = Point.useChosenSeparator(String((parseFloat(value)).toFixed(this.decimalPlaces)), this.floatSeparator);
		else 
			elem.setAttribute("value", Point.useChosenSeparator(String((parseFloat(value)).toFixed(this.decimalPlaces)), this.floatSeparator));
		document.getElementById('dialogWindowUnitText').innerHTML = String(unit);
	}

	/**
	 * Sets start time value to input time box located on DialogWindow
	 * @param {Integer} value 	Start time value
	 */
	setStartTime(value) {
		this.childStartTime.setValue(value);
	}

	/**
	 * Sets new type information for dialogWindow
	 * @param {String} type 		New type of value - it mus be equal to "numeric", "boolean", "enum" or "unknown"
	 * @returns {Boolean} 			True if type was "numeric", "boolean", "enum" or "unknown"; False in other cases; 
	 */
	setType(type) {
		if(type == "numeric" || type == "enum" || type == "boolean" || type == "unknown") {
			this.type = type;
			return true;
		}
		else	
			return false;
	}

	/**
	 * Sets value to the proper value BasicInput type ("numeric", "enum" or "boolean")
	 * @param {Object} value 		New value
	 * @param {*} scale 
	 * @param {String} unit 		Unit of numeric value (if not set for numeric value then must be "", if value isn't numeric then must be null)
	 * @param {String} falseText 	FalseText of boolean value (if not set for boolean value then must be "", if value isn't boolean then must be null)
	 * @param {String} trueText 	TrueText of boolean value (if not set for boolean value then must be "", if value isn't boolean then must be null)
	 */
	setValue(value, scale=null, unit=null, falseText=null, trueText=null) {//TODO - delete scale from
		if(this.type == "numeric") {
			this.setNumeric(value, ((unit == null) ? this.unit : unit));
		}
		else if(this.type == "enum") {
			this.setEnum(value);
		}
		else if(this.type == "boolean") {
			this.setBoolean(value, ((trueText == null) ? this.trueText : trueText), ((falseText == null) ? this.falseText : falseText));
		}
	}

	/**
	 * Sets value attributions
	 * @param    {Collection} valueAttributes 	Collection of event value attributes {"unit": "", "scale": 1.0, "floatSeparator": "dot", "enum": "", "falseText": "", "trueText": ""}
	 * @param	 {jQuery} enumsDefXmlObject		Data loaded from XML - all enums definitions
	 */
	setValueAttributes(valueAttributes, enumsDefXmlObject) {
		this.floatSeparator = valueAttributes.floatSeparator;
		this.clockMode = valueAttributes.clockMode;
		this.unit = valueAttributes.unit;
		this.scale = valueAttributes.scale;
		this.enum = new EnumDefinition(enumsDefXmlObject, valueAttributes.enum);
		this.falseText = valueAttributes.falseText;
		this.trueText = valueAttributes.trueText;
	}
	
	/**
	 * Sets visibility of DialogWindow, and locks/unlocks previous wiondow
	 * @param {Boolean} value		If true then DialogWindow is shown, if false it is hidden 
	 */
	setVisibility(value) {
		this.visibility = value;
		if(value) {
			DialogWindow.setBackground("mainContainer", 0.4, "none");
			document.getElementById("dialogWindow").style.setProperty("display", "block");
			DialogWindow.setBackground("dialogWindow", 1.0, "auto");
		}
		else {
			DialogWindow.setBackground("mainContainer", 1.0, "auto");
			document.getElementById("dialogWindow").style.setProperty("display", "none");
			document.getElementById("dialogWindowBoolean").value = '';
			document.getElementById("dialogWindowNumeric").value = '';
			document.getElementById("dialogWindowUnitText").value = '';
		}
		window.setPollingInModbusDrivers(!value);
		this.setWarningVisibility(false, "");
	}
	
	/**
	 * Shows warning text under "OK" and "Cancel" buttons
	 * @param {Boolean} value		If true then warning text is shown, if false it is hidden 
	 * @param {String} warningName	Name of the warning, which has to be shown - "dialogWindowOutOfRangeValue" or "dialogWindowToManyDecimals"
	 */
	setWarningVisibility(value, warningName) {
		if(warningName == "dialogWindowOutOfRangeValue")
			this.childWarningText.innerHTML = window.choosenLexicon.getLexiconMarkupText("dialogWindowOutOfRangeValue", String(32767), String(this.highLimit), String(-32768), String(this.lowLimit));
		else if(warningName == "dialogWindowToManyDecimals")
			this.childWarningText.innerHTML = window.choosenLexicon.getLexiconMarkupText("dialogWindowToManyDecimals", "0", String(this.decimalPlaces));
		else
			this.childWarningText.innerHTML = window.choosenLexicon.getLexiconMarkupText(warningName);
		document.getElementById("dialogWindowWarningText").style.setProperty("display", (value) ? "block" : "none");
	}
	
	/**
	 * Shows the DialogWindow as a popup window, and loads chosen instance of SetPoint value
	 * @param {Object} object 	Instance of BooleanSetPoint, NumericSetPoint, EventField or ActionButtonWithValue class
	 * @param {Object} object2	Used if object is EventField only - it reperesents Array of all EventFields in single day
	 * @param {Object} object3	Used if object is EventField only - it reperesents events per day count
	 * @param {Object} object4	(Optional) Used if object is EventField only - it reperesents Array of Arrays of all EventFields in each day of week
	 * @param {Integer} object5	(Optional) Used if object is EventField only - it reperesents selectedDayIndex
	 */
	show(object = null, object2 = null, object3 = null, object4 = null, object5 = null) {
		if(object != null) {
			this.object = object;
			if(object instanceof BooleanSetPoint || (((object instanceof EventField) || (object instanceof ActionButtonWithValue)) && object.getPointType() == "boolean")) {
				if(object instanceof BooleanSetPoint || object instanceof ActionButtonWithValue)
					this.showHideSpecifiedFields("block", "none", "none", "none", "none", "none");
				else
					this.showHideSpecifiedFields("block", "none", "none", "block", "block", "block");
				this.setBoolean(object.getState(), object.getTrueText(), object.getFalseText());
			}
			else if(object instanceof NumericSetPoint || object instanceof EventField || object instanceof ActionButtonWithValue) {
				if(object.getPointType() == "numeric") {
					if((object instanceof NumericSetPoint) || (object instanceof ActionButtonWithValue && (!(object instanceof EventField)))) {
						this.showHideSpecifiedFields("none", "none", "block", "none", "none", "none");
						console.log("NumericSetPoint or ActionButtonWithValue");
					}
					else {
						this.showHideSpecifiedFields("none", "none", "block", "block", "block", "block");
						console.log("others");
					}
					this.adjustValueRanges(object.getScale());
					this.setNumeric(object.getValue(), object.getUnit(), object.getScale());
					document.getElementById("dialogWindowNumeric").select();
				}
				else if(object.getPointType() == "enum") {
					if((object instanceof NumericSetPoint) || (object instanceof ActionButtonWithValue && (!(object instanceof EventField))))
						this.showHideSpecifiedFields("none", "block", "none", "none", "none", "none");
					else
						this.showHideSpecifiedFields("none", "block", "none", "block", "block", "block");
					this.flushEnumOptions();
					this.addAllEnumOptions(object);
					this.adjustValueRanges(object.getScale());
					this.setEnum(object.getValue());
				}
				this.setWarningVisibility(false, "");
			}
			else 
				console.log("Dialog window invoked by unexpected class instance object!");
			this.setLabelText(window.choosenLexicon.getLexiconMarkupText("dialogWindowSetValueTitle") + ": " + object.getLabelText());
			//set day of week, start time and end time
			if(object instanceof EventField) {
				this.allDayEvents = object2;
				this.thisEventIndex = BasicContainer.decodeFieldNumber(object.id);
				this.eventsPerDay = object3;
				this.AllDaysEvents = object4;// it can be null, because object4 is optional
				this.thisDayIndex = object5;// it can be null, because object5 is optional
				this.createTemporaryDayEventsArray();
				this.setDayOfWeek(object.getDayOfWeek()-1);
				this.setStartTime(object.getStartTime());
				this.setEndTime(object.getStopTime());
				this.childDayOfWeek.setEnabling(object4 != null && object5 != null);


				/*var keysArr = new Array();
				var valuesArr = new Array();
				for(var p=0; p < this.eventsPerDay; p++) {
					keysArr.push("StartTime" + String(p));
					keysArr.push("StopTime" + String(p));
					keysArr.push("Default" + String(p));
					valuesArr.push(this.allDayEvents[p].getStartTime());
					valuesArr.push(this.allDayEvents[p].getStopTime());
					valuesArr.push(this.allDayEvents[p].getDefault());
				}
				Debug.traceTable(keysArr, valuesArr, "DialogWindow-show[" + String(this.thisEventIndex) +"]");*/
			}
			this.setVisibility(true);
		}
		else 
			console.log("Dialog window invoked by null pointer reference!");
	}
	/**
	 * Shows dialog window for schedulers only
	 * @param {String} id 					ID of selected event or hour field
	 * @param {DialogWindow} dialogWindow 	Instance of DialogWindow
	 * @param {Array} events 				Array of all eventsof all days
	 * @param {Integer} eventsPerDay 		Amount events per day
	 * @param {Boolean} restArgs			If ti is true, then show method will get also all days events and dayIndex as an arguments
	 */
	static ShowDialogWindow(id, dialogWindow, events, eventsPerDay, restArgs = false) {
		//example id: schedulerDay1Event0
		var dayIndex = BasicContainer.decodeDayNumber(id) - 1;
		var eventIndex = BasicContainer.decodeFieldNumber(id);
		dialogWindow.show(events[dayIndex][eventIndex],events[dayIndex],eventsPerDay, (restArgs==true)? events : null, (restArgs==true)? dayIndex : null);
	}

	/**
	 * Shows dialog window with choosed error (warning)
	 * @param {String} errorType 			Id of choosed error (warning)
	 * @param {String} fieldToSelect 		Id of field in Dialog Window, which has to be selected
	 * @param {Array} arrayOfFields 		Array of expected state ("block" or "none")
	 * @param {String} idSelectedElement 	Id of selected event or hour field
	 */
	showDialogWithError(errorType, fieldToSelect, arrayOfFields, idSelectedElement) {
		var hour = BasicContainer.decodeFieldNumber(idSelectedElement);
		var day = BasicContainer.decodeDayNumber(idSelectedElement) - 1;
		this.showHideSpecifiedFields(arrayOfFields[0], arrayOfFields[1], arrayOfFields[2], arrayOfFields[3], arrayOfFields[4], arrayOfFields[5]);
		this.setValue(0.0);
		this.setDayOfWeek(day);
		this.setStartTime(hour * 60);
		this.setEndTime((hour + 1) * 60);
		this.setVisibility(true);
		this.showErrorAndSelectField(errorType, fieldToSelect);
	}

	/**
	 * Sets to true visibility of Warning (error) field and selects choosed field of Dialog Window
	 * @param {String} errorType 		Id of choosed error (warning)
	 * @param {String} fieldToSelect 	Id of field in Dialog Window, which has to be selected
	 */
	showErrorAndSelectField(errorType, fieldToSelect) {
		this.setWarningVisibility(true, errorType);
		document.getElementById(fieldToSelect).select();
		Debug.traceLog("Warning in DialogWindow occured!", errorType)
		this.restoreTemporaryDayEventsValues;
	}

	/**
	 * Shows/Hides specified BasicInputs in DialogWindow
	 * @param {String} boolean 		Accepts "block" (show) or "none" (hide) values only
	 * @param {String} enumeric 	Accepts "block" (show) or "none" (hide) values only
	 * @param {String} numeric  	Accepts "block" (show) or "none" (hide) values only
	 * @param {String} dayOfWeek  	Accepts "block" (show) or "none" (hide) values only
	 * @param {String} startTime  	Accepts "block" (show) or "none" (hide) values only
	 * @param {String} endTime  	Accepts "block" (show) or "none" (hide) values only
	 */
	showHideSpecifiedFields(boolean, enumeric, numeric, dayOfWeek, startTime, endTime) {
		document.getElementById("dialogWindowBooleanContainer").style.setProperty("display", boolean);
		document.getElementById("dialogWindowEnumContainer").style.setProperty("display", enumeric);
		document.getElementById("dialogWindowNumericContainer").style.setProperty("display", numeric);
		if(this.childDayOfWeek != undefined)
			document.getElementById("dialogWindowDayOfWeekContainer").style.setProperty("display", dayOfWeek);
		if(this.childStartTime != undefined)
			document.getElementById("dialogWindowStartTimeContainer").style.setProperty("display", startTime);
		if(this.childEndTime != undefined)
			document.getElementById("dialogWindowEndTimeContainer").style.setProperty("display", endTime);
		//check number of active inputs
		var array = [boolean, enumeric, numeric, dayOfWeek, startTime, endTime];
		var count = 0;
		for(var i = 0; i < array.length; i++)
			count += (array[i] == "block") ? 1 : 0;
		//update height
		document.getElementById("dialogWindow").style.setProperty("height", String(170 + count * 75) + "px");
	}
	
	/**
	 * Verifies the input value, how many decimal places does it contain
	 * @param {Float} value 	Input value
	 * @returns {Integer}		Amount of deciaml places in input value
	 */
	static verifyDecimalPlacesOfValue(value) {
		var strValue = String(value);
		var index = strValue.indexOf(".");
		if(index == -1) {
			index = strValue.indexOf(",");
		}
		return (index == -1) ? 0 : (strValue.length - index - 1);
	}
}

window.DialogWindow = DialogWindow;