
import { BasicContainer } from '/sd:basic-container.js'; 
import { StandardLabel } from '/sd:standard-label.js'; 
import { EnumDefinition } from '/sd:enum-definition.js';
import { ModbusRequestContainer } from '/sd:modbus-request-container.js'; 
import { Point } from '/sd:point.js';
//import { modbusReader } from '/sd:common-includes.js';

/**
 * class to create instance of float value displayer. It allows for define label text and scaled value with unit inside div container. Class keeps the pointRefreshFrequency name, and assigns value to Register of ModbusTCP Network according to the name of pointRefreshFrequency
 */
export class NumericPoint extends BasicContainer {	
	/**
	 * Constructor
	 * @param {jQuery} xmlObject    		Data loaded from XML - accept numeric points part only
	 * @param {String} parentId				HTML ID of the object, which has to be a parent of constructing numeric point
	 * @param {Integer} itemNumber			Number of object constructing numeric point
	 * @param {jQuery} enumsDefXmlObject    Data loaded from XML - accept enums definition part only
	 * @param {String} floatSeparator		Name of chosen float separator
	 * @param {String} pointMainClass		Name of the CSS style's class of numeric point
	 * @param {Integer} holdingRegister		Holding register address in decimal
	 * @param {Float} scale					Scale for read from Modbus value
	 * @param {String} unit					Unit added after value
	 * @param {String} enumName				Enum name if value isn't numeric type
	 */
	constructor(xmlObject, parentId, itemNumber = 0, enumsDefXmlObject, floatSeparator, pointMainClass = "NumericPoint", holdingRegister=null, scale=null, unit=null, enumName=null, pointRefreshFrequency=null) {
		super(xmlObject, parentId, pointMainClass, itemNumber);
		if(itemNumber == null)
			var num = 0;
		else 
			var num = itemNumber;
		var labelXmlObject = $(xmlObject[num]).find("label");
		var topLabelXmlObject = $(xmlObject[num]).find("topLabel");
		var valueXmlObject = $(xmlObject[num]).find("value");
		if(unit == null && valueXmlObject[0].attributes['unit'] != undefined)
			this.unit = valueXmlObject[0].attributes['unit'].value; 
		else if(unit != null)
			this.unit = unit;
		else
			this.unit = "";
		//scale
		var strTemp = this.getRightProperty(scale, valueXmlObject[0].attributes['scale'], "1.0");
		strTemp = strTemp.replace(",", ".");
		this.scale = parseFloat(strTemp);

		//floatSeparator
		this.floatSeparator = floatSeparator;
		//decimalPlaces
		this.decimalPlaces = Point.calculateDecimalPlaces(this.scale);
		//enum
		strTemp = this.getRightProperty(enumName, valueXmlObject[0].attributes['enum'], "");
		this.enum = (strTemp != "") ? new EnumDefinition(enumsDefXmlObject, strTemp) : null;

		//type
		this.type = ((scale != null && unit != null) || (valueXmlObject[0].attributes['scale'] != undefined && valueXmlObject[0].attributes['unit'] != undefined)) ? "numeric" : "enum";

		//default value
		this.value = (this.type == "numeric") ? parseFloat(0.0) : Math.round(0);
		
		//print label or topLabel, and value
		var val = null;
		if(labelXmlObject.length > 0) {
			this.childLabel = new StandardLabel(labelXmlObject, this.id, pointMainClass + "Label", null, this.id + "label");
			val = labelXmlObject[0].attributes['text'].value
		}
		else if(topLabelXmlObject.length > 0) {
			this.childLabel = new StandardLabel(topLabelXmlObject, this.id, pointMainClass + "TopLabel", null, this.id + "topLabel");
			val = topLabelXmlObject[0].attributes['text'].value
		}
		this.childValue = new StandardLabel(valueXmlObject, this.id, pointMainClass + "Value", null, this.id + "value");
		this.childLabel.setTextValue(val);
		this.setTextValue();

		//holdingRegister
		this.holdingRegister = Math.round(this.getRightProperty(holdingRegister, xmlObject[num].attributes['holdingRegister'], 1000));
		//pointRefreshFrequency
		this.pointRefreshFrequency = this.getRightProperty(pointRefreshFrequency, xmlObject[num].attributes['pointRefreshFrequency'], "normal");

		this.bitNumber = "all";
		window.modbusReader[ModbusRequestContainer.findModbusNetworkIndex(this.pointRefreshFrequency, window.modbusReader)].initRegister(this.holdingRegister, this, "int", this.bitNumber);
	}

	/**
	 * Gets label text of the numeric point
	 * @returns {String}	Label text of the numeric point
	 */
	getLabelText() {
		return this.childLabel.getTextValue("string");
	}
	
	/**
	 * Gets starting Modbus register address of point
	 * @returns {Integer}		Register address
	 */
	getModbusRegisterAddress() {
		return this.holdingRegister;
	}

	/**
	 * Gets name of pointRefreshFrequency
	 * @returns {String}	Name of point refresh frequency tunning
	 */
	getPointRefreshFrequency() {
		return this.pointRefreshFrequency;
	}
	
	/**
	 * Gets type of the point
	 * @returns {String}		Type of the point ("numeric", "enum", "boolean" or "unknown")
	 */
	getPointType() {
		return this.type;
	}

	/**
	 * check status of first and second property and return proper
	 * @param {String} firstProperty		Nullable property
	 * @param {String} secondProperty		Undefinable property
	 * @param {String} otherOptionResult	Result value if first and second property aren't value
	 * @returns {String}					Right property
	 */
	getRightProperty(firstProperty, secondProperty, otherOptionResult) {
		if(firstProperty == null && secondProperty != undefined) 
			return secondProperty.value;
		else if(firstProperty != null)
			return firstProperty;
		else
			return otherOptionResult;
	}
	
	/**
	 * Gets scale of the numeric point
	 * @returns {Float}		Scale value
	 */
	getScale() {
		return this.scale;
	}
	
	/**
	 * Gets unit of the numeric point
	 * @returns {String}	Unit of the numeric point
	 */
	getUnit() {
		return this.unit;
	}
	
	/**
	 * Gets current value of the numeric point
	 * @returns {Float} 	Value of the numeric point
	 */
	getValue() {
		return this.value;
	}
	
	/**
	 * Gets rescaled value of the numeric point for Modbus TCP
	 * @returns {Integer}	Rescaled value 
	 */
	getValueToSendOverModbusTcp() {
		return Math.round(this.value / this.scale);
	}	
	
	/**
	 * Sets label of the numeric point
	 * @param {String} value 	Text to set
	 */
	setLabelText(value) {
		this.childLabel.setTextValue(value);
	}
	
	/**
	 * Sets current value as a text to HTML object 
	 */
	setTextValue() {
		this.childValue.setTextValue((this.type == "numeric") ? Point.useChosenSeparator(this.value.toFixed(this.decimalPlaces), this.floatSeparator) + "&nbsp;&nbsp;" + String(this.unit) : this.enum.getLabelByVal(Math.round(this.value)));
	}
	
	/**
	 * Sets unit to the numeric point
	 * @param {String} value 	Unit
	 */
	setUnit(value) {
		this.unit = value;
	}
	
	/**
	 * Sets value - it is saved in current value
	 * @param {Object} value 	Value to set
	 */
	setValue(value) {
		this.value = (this.type == "numeric") ? parseFloat(value) : Math.round(value);
	}
}