import { LasalRuntimeSigElement, SigPolymer } from '../../sigmatek/sig-element/sig-element.js';
import { DA_DataManager } from '../sig-control-da-datamanager/sig-control-da-datamanager.js';

export class LasalRuntimeSigControlDAChannelSettings extends LasalRuntimeSigElement {

    /***************************************************************************************************************************
     * Defines the custom tag name. Must match the dom module id
     ***************************************************************************************************************************/
    static get is() {
        return 'sig-control-da-channelsettings';
    }

    /***************************************************************************************************************************
     * When the element is loaded, importMeta() assigns reference to the path from 
     * which an element was imported to its importPath property. 
     * Relative URLs in styles are automatically re-written to be relative to the importPath property. 
     * You can use [[importPath]] in your component to load url resources
     ***************************************************************************************************************************/
    static get importMeta() { return import.meta; }

    /***************************************************************************************************************************
     * Return the component style and template as a template literal
     ***************************************************************************************************************************/    
    static get template() {
        return SigPolymer.html`

        <style include='sig-element-css'>
            :host {
                /* Basic styling of the component */
                color: var(--theme-sig-control-da-channelsettings-color, inherit);
                background-color: var(--theme-sig-control-da-channelsettings-background-color, transparent);

                border-width: var(--theme-sig-control-da-channelsettings-border-width, inherit);
                border-color: var(--theme-sig-control-da-channelsettings-border-color, inherit);
                border-style: var(--theme-sig-control-da-channelsettings-border-style, none);
                border-radius: var(--theme-sig-control-da-channelsettings-border-radius, 0);

                /* Basic box model settings */
                display: block;
                position: absolute;
            }

            :host * {
                /* Reset margin and padding for child elements and turn off text selection */
                @apply --notextselect;
                margin: 0;
                padding: 0;
            }         
        </style>
        <slot name='settingscc'></slot>
        `;
    }

    static get properties() {
        return {                                                                
        };
    }

    /***************************************************************************************************************************
     * Called when the element has been created,
     * but before property values are set and local DOM is initialized.
     ***************************************************************************************************************************/
    constructor() {
        super();

        //only do if not in designmode
        if (!this.isdesignmode) {
            //  Create shortcuts to the common apis makes the code more readable
            if (window.sigApi) {
                this.datapointApi = window.sigApi.datapointManager;
                this.vmApi = window.sigApi.vm;
                this.menuApi = window.sigApi.menuManager;
                this.propApi = window.sigApi.properties;
                this.constApi = window.sigApi.SIG_CONST;
                this.evtApi = window.sigApi.events;
                this.evtMediaApi = window.sigApi.eventMediator;
                this.unitApi = window.sigApi.unitManager;
            } else {
                this._log('constructor(): API not ready!', 'ERROR');
            }         

            //event ids
            this.majorID = 0x8003;
            Object.freeze(this.majorID); 

            //define datatypes
            this.dataTypes = {
                void: 0,
                bool: 1,
                int8: 2,
                int16: 3,
                int32: 4,
                int64: 5,
                uint8: 6,
                uint16: 7,
                uint32: 8,
                uint64: 9,
                float32: 10,
                float64: 11
            }
            Object.freeze(this.dataTypes);            

            //register for incoming events
            this._registerEvents();

            //add required properties
            this.sigAddRequiredProperty('graphinstanceid');

            //request instance of datamanager
            this.DA_DataManager = DA_DataManager.requestInstance();
        }
    }

    /**
     * register for incoming events
     */
    _registerEvents() {

        //*******************************************************************************************************
        //** new graph view logged in so format zeroline offset knob cause now we know which mode
        //*******************************************************************************************************
        this.sigAddEventListener('_DA_GRAPH_VIEW_LOGGED_IN', (e) => {
            if (e.detail !== undefined) {
                //check if already initialized
                if (this.initialized) {
                    //check if channel is ment for graph instance id
                    if (this.graphinstanceid === e.detail.graphInstID) {
                        if (this.instances !== undefined) {
                            for (let [id, instances] of this.instances) {  
                                //format zerolineoffset knob
                                this._formatZeroLineOffsetKnob(instances.channelSelectionMenu, instances.zeroLineOffsetKnob);                                
                            }                         
                        }             
                    }                      
                }           
            }
        }, 'jsEvent', window);       

        //*******************************************************************************************************
        //** new channel logged in so get channels and draw them
        //*******************************************************************************************************
        this.sigAddEventListener('_DA_NEW_CHANNEL_LOGGED_IN', (e) => {
            if (e.detail !== undefined) {
                //check if already initialized
                if (this.initialized) {
                    //check if channel is ment for graph instance id
                    if (this.graphinstanceid === e.detail.instID) {
                        //build channel menu once for all
                        this._buildChannelMenu(true).then(() => {
                            if (this.instances !== undefined) {
                                for (let [id, instances] of this.instances) {
                                    //build channel selection
                                    this._setChannelMenuList(instances.channelSelectionMenu, instances.scaleTypeMenu, true);
                                    //build server lists
                                    this._buildServerMenuList(instances.channelSelectionMenu, instances.serverConfigMenu, true);            
                                    //set channel name
                                    this._setChannelName(instances.channelSelectionMenu, instances.channelNameInput);
                                    //format min and maxvalue
                                    this._formatLimits(instances.channelSelectionMenu, instances.minValueInput, instances.maxValueInput); 
                                    //format value per division
                                    this._formatValuePerDiv(instances.channelSelectionMenu, instances.valuePerDivInput);  
                                    //format zerolineoffset
                                    this._formatZeroLineOffset(instances.channelSelectionMenu, instances.zeroLineOffsetInput);  
                                    //format zerolineoffset knob
                                    this._formatZeroLineOffsetKnob(instances.channelSelectionMenu, instances.zeroLineOffsetKnob);                                
                                }                         
                            }   
                        }).catch((error) => {
                            this._log('_registerEvents(): build channel list failed (channel log in) -> ' + error, 'ERROR');
                        });
                    }                      
                }           
            }
        }, 'jsEvent', window);       

        //*******************************************************************************************************
        //** channel name changed
        //*******************************************************************************************************
        this.sigAddEventListener('_DA_CHANNEL_NAME_CHANGED', (e) => {
            if (e.detail !== undefined) {
                //check if already initialized
                if (this.initialized) {
                    //check if datamanager was initialized
                    if (this.DA_DataManager !== undefined) {
                        //get visuchannels
                        const visuChls = this.DA_DataManager.getVisuChannels(this.graphinstanceid);
                        if ((visuChls !== undefined) && (visuChls.size > 0)) {
                            for (let [visuChlID, channel] of visuChls) {
                                if (channel.chlReference !== undefined) {
                                    //check if it is about this channel
                                    if ((channel.chlReference.stationNumber === e.detail.stationNumber) && (channel.chlReference.chlID === e.detail.chlID)) {
                                        //build channel menu list only once for all
                                        Promise.all([this._buildChannelMenu(true), this._buildRealChannelMenu(true)]).then(() => {
                                            if (this.instances !== undefined) {
                                                for (let [id, instances] of this.instances) {
                                                    //build channel selection
                                                    this._setChannelMenuList(instances.channelSelectionMenu, instances.scaleTypeMenu, true);
                                                    //build real channelselection new
                                                    this._setRealChannelMenuList(instances.realChannelSelectionMenu); 
                                                }                         
                                            }                   
                                        }).catch((error) => {
                                            this._log('_registerEvents(): build channel list failed (server chg) -> ' + error, 'ERROR');
                                        });                                         
                                    }
                                }
                                else {
                                    this._log('_registerEvents(): invalid channel reference', 'ERROR');
                                }                                
                            }
                        }
                    }                      
                }         
            }
        }, 'jsEvent', window); 

        //*******************************************************************************************************
        //** check for unit change to format limits new
        //*******************************************************************************************************
        this.sigAddEventListener('_DA_UNIT_CHANGED', (e) => {
            if (e.detail !== undefined) {
                //check if init
                if (this.initialized) {
                    //check if datamanager was initialized
                    if (this.DA_DataManager !== undefined) {
                        //get visuchannels
                        const visuChls = this.DA_DataManager.getVisuChannels(this.graphinstanceid);
                        if ((visuChls !== undefined) && (visuChls.size > 0)) {
                            for (let [visuChlID, channel] of visuChls) {
                                if (channel.chlReference !== undefined) {
                                    //check if it is about this channel
                                    if ((channel.chlReference.stationNumber === e.detail.stationNumber) && (channel.chlReference.chlID === e.detail.chlID)) {
                                        if (this.instances !== undefined) {
                                            for (let [id, instances] of this.instances) {
                                                //format min and maxvalue
                                                this._formatLimits(instances.channelSelectionMenu, instances.minValueInput, instances.maxValueInput); 
                                                //format value per division
                                                this._formatValuePerDiv(instances.channelSelectionMenu, instances.valuePerDivInput); 
                                                //format zerolineoffset
                                                this._formatZeroLineOffset(instances.channelSelectionMenu, instances.zeroLineOffsetInput);                                                 
                                            }                         
                                        }                                          
                                    }
                                }
                                else {
                                    this._log('_registerEvents(): invalid channel reference', 'ERROR');
                                }                                
                            }
                        }
                    }  
                }
            }
        }, 'jsEvent', window);         

        //*******************************************************************************************************
        //** check for change of source -> limits have to be formatted new
        //*******************************************************************************************************
        this.sigAddEventListener('_DA_SERVER_CHANGED', (e) => {
            if (e.detail !== undefined) {
                //check if init
                if (this.initialized) {
                    //check if datamanager was initialized
                    if (this.DA_DataManager !== undefined) {
                        //get visuchannels
                        const visuChls = this.DA_DataManager.getVisuChannels(this.graphinstanceid);
                        if ((visuChls !== undefined) && (visuChls.size > 0)) {
                            for (let [visuChlID, channel] of visuChls) {
                                if (channel.chlReference !== undefined) {
                                    //check if it is about this channel
                                    if ((channel.chlReference.stationNumber === e.detail.stationNumber) && (channel.chlReference.chlID === e.detail.chlID)) {
                                        //build channel menu list only once for all
                                        Promise.all([this._buildChannelMenu(true), this._buildRealChannelMenu(true)]).then(() => {
                                            if (this.instances !== undefined) {
                                                for (let [id, instances] of this.instances) {
                                                    //build channel selection
                                                    this._setChannelMenuList(instances.channelSelectionMenu, instances.scaleTypeMenu, true);
                                                    //build real channelselection new
                                                    this._setRealChannelMenuList(instances.realChannelSelectionMenu);                                                 
                                                    //format min and maxvalue
                                                    this._formatLimits(instances.channelSelectionMenu, instances.minValueInput, instances.maxValueInput); 
                                                    //format value per division
                                                    this._formatValuePerDiv(instances.channelSelectionMenu, instances.valuePerDivInput); 
                                                    //format zerolineoffset
                                                    this._formatZeroLineOffset(instances.channelSelectionMenu, instances.zeroLineOffsetInput);                                                 
                                                }                         
                                            }                     
                                        }).catch((error) => {
                                            this._log('_registerEvents(): build channel list failed (server chg) -> ' + error, 'ERROR');
                                        });                                             
                                    }
                                }
                                else {
                                    this._log('_registerEvents(): invalid channel reference', 'ERROR');
                                }                                
                            }
                        }
                    }  
                }
            }
        }, 'jsEvent', window); 

        //*******************************************************************************************************
        //** channel reference changed
        //*******************************************************************************************************
        this.sigAddEventListener('_DA_CHANNEL_REFERENCE_CHANGED', (e) => {
            if (e.detail !== undefined) {
                //check if already initialized
                if (this.initialized) {
                    //check if ment for this channel settings
                    if (this.graphinstanceid === e.detail.graphInstID) {
                        //build channel menu list only once for all
                        this._buildChannelMenu(true).then(() => {
                            if (this.instances !== undefined) {
                                for (let [id, instances] of this.instances) {
                                    //build channel selection
                                    this._setChannelMenuList(instances.channelSelectionMenu, instances.scaleTypeMenu, true);
                                    //build real channelselection new
                                    this._setRealChannelMenuList(instances.realChannelSelectionMenu);           
                                    //set channel name
                                    this._setChannelName(instances.channelSelectionMenu, instances.channelNameInput);
                                    //format min and maxvalue
                                    this._formatLimits(instances.channelSelectionMenu, instances.minValueInput, instances.maxValueInput); 
                                    //format value per division
                                    this._formatValuePerDiv(instances.channelSelectionMenu, instances.valuePerDivInput); 
                                    //format zerolineoffset
                                    this._formatZeroLineOffset(instances.channelSelectionMenu, instances.zeroLineOffsetInput); 
                                }                         
                            }                      
                        }).catch((error) => {
                            this._log('_registerEvents(): build channel list failed (ref chg) -> ' + error, 'ERROR');
                        });                                                               
                    }                    
                }       
            }
        }, 'jsEvent', window);

        //*******************************************************************************************************
        //** min scale value of channel changed (also written at autoset)
        //*******************************************************************************************************
        this.sigAddEventListener('_DA_MIN_SCALE_CHANGED', (e) => {
            if (e.detail !== undefined) {
                //check if already initialized
                if (this.initialized) {
                    //check if ment for us   
                    if (e.detail.instID === this.graphinstanceid) {
                        if (this.instances !== undefined) {
                            for (let [id, instances] of this.instances) {
                                //format min and maxvalue
                                this._formatLimits(instances.channelSelectionMenu, instances.minValueInput, instances.maxValueInput); 
                                //format limits of knob
                                this._formatZeroLineOffsetKnob(instances.channelSelectionMenu, instances.zeroLineOffsetKnob);
                            }
                        }        
                    }                      
                }  
            }
        }, 'jsEvent', window);        

        //*******************************************************************************************************
        //** max scale value of channel changed (also written at autoset)
        //*******************************************************************************************************
        this.sigAddEventListener('_DA_MAX_SCALE_CHANGED', (e) => {
            if (e.detail !== undefined) {
                //check if already initialized
                if (this.initialized) {
                    //check if ment for us   
                    if (e.detail.instID === this.graphinstanceid) {
                        if (this.instances !== undefined) {
                            for (let [id, instances] of this.instances) {
                                //format min and maxvalue
                                this._formatLimits(instances.channelSelectionMenu, instances.minValueInput, instances.maxValueInput); 
                                //format limits of knob
                                this._formatZeroLineOffsetKnob(instances.channelSelectionMenu, instances.zeroLineOffsetKnob);                                
                            }
                        }  
                    } 
                }            
            }
        }, 'jsEvent', window);  
        
        //*******************************************************************************************************
        //** value per division of channel changed (also written at autoset)
        //*******************************************************************************************************
        this.sigAddEventListener('_DA_VALUE_PER_DIVISION_CHANGED', (e) => {
            if (e.detail !== undefined) {
                //check if already initialized
                if (this.initialized) {
                    //check if ment for us   
                    if (e.detail.instID === this.graphinstanceid) {
                        if (this.instances !== undefined) {
                            for (let [id, instances] of this.instances) {
                                //format value per division
                                this._formatValuePerDiv(instances.channelSelectionMenu, instances.valuePerDivInput); 
                                //format limits of knob
                                this._formatZeroLineOffsetKnob(instances.channelSelectionMenu, instances.zeroLineOffsetKnob);
                            }
                        }  
                    }  
                }           
            }
        }, 'jsEvent', window);   

        //*******************************************************************************************************
        //** zerolineoffset of channel changed (also written at autoset)
        //*******************************************************************************************************
        this.sigAddEventListener('_DA_ZERO_LINE_OFFSET_CHANGED', (e) => {
            if (e.detail !== undefined) {
                //check if already initialized
                if (this.initialized) {
                    //check if ment for us   
                    if (e.detail.instID === this.graphinstanceid) {
                        if (this.instances !== undefined) {
                            for (let [id, instances] of this.instances) {
                                //format zeroline offset
                                this._formatZeroLineOffset(instances.channelSelectionMenu, instances.zeroLineOffsetInput);
                                //format limits of knob
                                this._formatZeroLineOffsetKnob(instances.channelSelectionMenu, instances.zeroLineOffsetKnob);                                
                            }
                        }  
                    }  
                }           
            }
        }, 'jsEvent', window);          

        //*******************************************************************************************************
        //** language changed so we have to rebuild the server cause name might change
        //*******************************************************************************************************
        this.sigAddEventListener('LANGUAGE_CHG', (e) => {
            //check if already initialized
            if (this.initialized) {
                //build channel menu list only once for all
                Promise.all([this._buildChannelMenu(true), this._buildRealChannelMenu(true)]).then(() => {
                    if (this.instances !== undefined) {
                        for (let [id, instances] of this.instances) {
                            //build channel list new cause there are might channelnames from var text
                            this._setChannelMenuList(instances.channelSelectionMenu, instances.scaleTypeMenu, true); 
                            this._setRealChannelMenuList(instances.realChannelSelectionMenu, true);
                            //build server lists
                            this._buildServerMenuList(instances.channelSelectionMenu, instances.serverConfigMenu, true); 
                        }
                    }                     
                }).catch((error) => {
                    this._log('_registerEvents(): build channel list failed (lang chg) -> ' + error, 'ERROR');
                });
            }           
        }, 'runtimeEvent');          
    }

    /**
     * gets called if all required properties are ready
     */
    sigOnRequiredPropertiesReady() {
        super.sigOnRequiredPropertiesReady();
        this.requiredPropsReady = true;
        if (this.isReady) {
            //initialize component
            this._init();            
        }
    }
    
    /**
     * local dom was initialized and properties are set
     */
    ready() {
        super.ready();
        if (!this.isdesignmode) {
            this.isReady = true;
            if (this.requiredPropsReady) {
                //initialize component
                this._init();              
            }            
        }
    }


    /****************************************************************************************************
     * method used to initialize the settings
     *
     * @memberof LasalRuntimeSigControlDAChannelSettings
     ****************************************************************************************************/
    _init() {
        //set info that control was init
        this.initialized = true;
        //get instances which should be manipulated or observed
        this._getInstances();
        //get channel and real channel menu once for all instances
        Promise.all([this._buildChannelMenu(), this._buildRealChannelMenu()])
        .then(()=>{
            if (this.instances !== undefined) {
                for (let [id, instances] of this.instances) {
                    //overload cc
                    this._overloadCC(instances.vm).then(() => {
                        //build recording channel lists
                        this._setRealChannelMenuList(instances.realChannelSelectionMenu);           
                        //build channel selection
                        this._setChannelMenuList(instances.channelSelectionMenu, instances.scaleTypeMenu);
                        //build server lists
                        this._buildServerMenuList(instances.channelSelectionMenu, instances.serverConfigMenu);            
                        //set channel name
                        this._setChannelName(instances.channelSelectionMenu, instances.channelNameInput);
                        //format min and maxvalue
                        this._formatLimits(instances.channelSelectionMenu, instances.minValueInput, instances.maxValueInput); 
                        //format value per division
                        this._formatValuePerDiv(instances.channelSelectionMenu, instances.valuePerDivInput); 
                        //format zeroline offset
                        this._formatZeroLineOffset(instances.channelSelectionMenu, instances.zeroLineOffsetInput);  
                        //format limits of knob
                        this._formatZeroLineOffsetKnob(instances.channelSelectionMenu, instances.zeroLineOffsetKnob);                                      
                    });                
                }                         
            } 
        }).catch((error) => {
            this._log('_init(): failed to build channel menu -> ' + error, 'ERROR');
        }) 
    }

    /**
     * method is used to get the instances of controls which need to be manipulated or observed
     */
    _getInstances() {
        //check if vm api ready
        if ((this.vmApi !== undefined) && (this.propApi !== undefined)) {
            //get composite controls
            const ccs = this.querySelectorAll(`[slot="settingscc"]`);
            if (ccs !== null) {
                //check if map already exists
                if (this.instances === undefined) {
                    //new map
                    this.instances = new Map();                    
                }
                let instanceObj = {
                    vm: undefined,
                    channelSelectionMenu: undefined,
                    realChannelSelectionMenu: undefined,
                    channelNameInput: undefined,
                    serverConfigMenu: undefined,
                    scaleTypeMenu: undefined,
                    minValueInput: undefined,
                    maxValueInput: undefined,
                    valuePerDivInput: undefined,
                    zeroLineOffsetInput: undefined,
                    zeroLineOffsetKnob: undefined
                }
                for (let i=0;i<ccs.length;i++) {        
                    //check if instance object already exists
                    if (this.instances.get(ccs[i].id) === undefined) {
                        instanceObj.vm = this.vmApi.getVmById(ccs[i].id);
                        if (instanceObj.vm !== null) {                
                            //build instance object
                            //get menu for channel selection
                            const chlSelMenuVm = instanceObj.vm.getChildByName('@DA_ChannelSelection');
                            if (chlSelMenuVm !== null) {
                                //get domref of menu
                                instanceObj.channelSelectionMenu = chlSelMenuVm.getDomRef();
                                //add observer for channel selection
                                if (instanceObj.channelSelectionMenu !== undefined) {
                                    //save id of parent cc so at selection changed we can refer to instance. Simply getting the parent id is not correct, cause it might
                                    //be placed within another cc
                                    instanceObj.channelSelectionMenu.daCCParent = ccs[i].id;
                                    instanceObj.channelSelectionMenu.sigAddEventListener('sig-control-menu-input-value-changed', (event) => this._selectionChanged(event.srcElement.daCCParent));
                                    //register for menu onrequired properties ready as value prop will get overwritten if not ready yet
                                    instanceObj.channelSelectionMenu.origReadyCB = instanceObj.channelSelectionMenu.sigOnRequiredPropertiesReady.bind(instanceObj.channelSelectionMenu);
                                    instanceObj.channelSelectionMenu.sigOnRequiredPropertiesReady = () => {
                                        //first of all call original
                                        instanceObj.channelSelectionMenu.origReadyCB();
                                        //update value
                                        this._selectionChanged(instanceObj.channelSelectionMenu.daCCParent);
                                    }                                    
                                }
                                else {
                                    this._log('_getInstances(): invalid channel selection', 'ERROR');
                                }                         
                            }
                            else {
                                //reset channelselection
                                instanceObj.channelSelectionMenu = undefined;
                            }
                            //get menu for recording channel selection
                            const realChlSelMenuVm = instanceObj.vm.getChildByName('@DA_RealChannelSelection');
                            if (realChlSelMenuVm !== null) {
                                //get domref of menu
                                instanceObj.realChannelSelectionMenu = realChlSelMenuVm.getDomRef();                        
                            }
                            else {
                                //reset real channel selection in case of reinitialization
                                instanceObj.realChannelSelectionMenu = undefined;
                            }
                            //get menu for recorded server selection
                            const serverConfigMenuVm = instanceObj.vm.getChildByName('@DA_ServerConfiguration');
                            if (serverConfigMenuVm !== null) {
                                //get domref of menu
                                instanceObj.serverConfigMenu = serverConfigMenuVm.getDomRef();
                                //add observer for channel selection
                                if (instanceObj.serverConfigMenu !== undefined) {
                                    //save id of parent cc so at selection changed we can refer to instance. Simply getting the parent id is not correct, cause it might
                                    //be placed within another cc
                                    instanceObj.serverConfigMenu.daCCParent = ccs[i].id;
                                    instanceObj.serverConfigMenu.sigAddEventListener('sig-control-menu-input-value-changed', (event) => {
                                        //check if observer should be ignored
                                        if (this.ignoreSvrSelObs !== true) {
                                            this._serverSelectionChanged(event)
                                        }
                                        this.ignoreSvrSelObs = false;
                                    });   
                                }
                                else {
                                    this._log('_getInstances(): invalid server configuration', 'ERROR');
                                }                         
                            }
                            else {
                                //reset server config in case of reinitialization
                                instanceObj.serverConfigMenu = undefined;
                            }                    
                            //get menu for scale type
                            const scaleTypeMenuVm = instanceObj.vm.getChildByName('@DA_ScaleType');
                            if (scaleTypeMenuVm !== null) {
                                //get domref of menu
                                instanceObj.scaleTypeMenu = scaleTypeMenuVm.getDomRef();
                            }  
                            //get input of channelname
                            const chlNameInputVm = instanceObj.vm.getChildByName('@DA_ChannelName');
                            if (chlNameInputVm !== null) {
                                //get domref of menu
                                instanceObj.channelNameInput = chlNameInputVm.getDomRef();
                                //add observer for channel name
                                if (instanceObj.channelNameInput !== undefined) {
                                    //save id of parent cc so at selection changed we can refer to instance. Simply getting the parent id is not correct, cause it might
                                    //be placed within another cc
                                    instanceObj.channelNameInput.daCCParent = ccs[i].id;
                                    instanceObj.channelNameInput.sigAddEventListener('value-changed', (event) => this._channelInputChanged(event));
                                }
                                else {
                                    this._log('_getInstances(): invalid channel name', 'ERROR');
                                }                          
                            }
                            else {
                                //reset channelname in case of reinitialization
                                instanceObj.channelNameInput = undefined;
                            }       
                            //get input of minvalue
                            const minValueInputVm = instanceObj.vm.getChildByName('@DA_MinValue');
                            if (minValueInputVm !== null) {
                                //get domref of minimum value
                                instanceObj.minValueInput = minValueInputVm.getDomRef();
                                //add observer for changes
                                if (instanceObj.minValueInput !== undefined) {
                                    //save id of parent cc so at selection changed we can refer to instance. Simply getting the parent id is not correct, cause it might
                                    //be placed within another cc
                                    instanceObj.minValueInput.daCCParent = ccs[i].id;
                                    //set numeric
                                    instanceObj.minValueInput.type = 'numeric';
                                    instanceObj.minValueInput.sigAddEventListener('value-changed', (event) => this._minValueChanged(event));
                                }
                                else {
                                    this._log('_getInstances(): invalid channel selection', 'ERROR');
                                }                          
                            } 
                            else {
                                //reset minvalue input in case of reinitialization
                                instanceObj.minValueInput = undefined;
                            }                                          
                            //get input of maxvalue
                            const maxValueInputVm = instanceObj.vm.getChildByName('@DA_MaxValue');
                            if (maxValueInputVm !== null) {
                                //get domref of maximum value
                                instanceObj.maxValueInput = maxValueInputVm.getDomRef();
                                //add observer for changes
                                if (instanceObj.maxValueInput !== undefined) {
                                    //save id of parent cc so at selection changed we can refer to instance. Simply getting the parent id is not correct, cause it might
                                    //be placed within another cc
                                    instanceObj.maxValueInput.daCCParent = ccs[i].id;                                    
                                    //set numeric
                                    instanceObj.maxValueInput.type = 'numeric';                            
                                    instanceObj.maxValueInput.sigAddEventListener('value-changed', (event) => this._maxValueChanged(event));
                                }
                                else {
                                    this._log('_getInstances(): invalid channel selection', 'ERROR');
                                }                          
                            } 
                            else {
                                //reset maxvalue input in case of reinitialization
                                instanceObj.maxValueInput = undefined;
                            }     
                            //get input of value per division
                            const valuePerDivVm = instanceObj.vm.getChildByName('@DA_ValuePerDivision');
                            if (valuePerDivVm !== null) {
                                //get domref of value per division
                                instanceObj.valuePerDivInput = valuePerDivVm.getDomRef();
                                //add observer for changes
                                if (instanceObj.valuePerDivInput !== undefined) {
                                    //save id of parent cc so at selection changed we can refer to instance. Simply getting the parent id is not correct, cause it might
                                    //be placed within another cc
                                    instanceObj.valuePerDivInput.daCCParent = ccs[i].id;                                     
                                    //set numeric
                                    instanceObj.valuePerDivInput.type = 'numeric';                            
                                    instanceObj.valuePerDivInput.sigAddEventListener('value-changed', (event) => this._valuePerDivChanged(event));
                                }
                                else {
                                    this._log('_getInstances(): invalid channel selection', 'ERROR');
                                }                          
                            }  
                            else {
                                //reset value per division in case of reinitialization
                                instanceObj.valuePerDivInput = undefined;
                            }   
                            //get input of zerolineoffset offset
                            const zeroLineOffsetVM = instanceObj.vm.getChildByName('@DA_ZeroLineOffset');
                            if (zeroLineOffsetVM !== null) {
                                //get domref of zerolineoffset
                                instanceObj.zeroLineOffsetInput = zeroLineOffsetVM.getDomRef();
                                //add observer for changes
                                if (instanceObj.zeroLineOffsetInput !== undefined) {
                                    //save id of parent cc so at selection changed we can refer to instance. Simply getting the parent id is not correct, cause it might
                                    //be placed within another cc
                                    instanceObj.zeroLineOffsetInput.daCCParent = ccs[i].id;                                     
                                    //set numeric
                                    instanceObj.zeroLineOffsetInput.type = 'numeric';
                                    instanceObj.zeroLineOffsetInput.sigAddEventListener('value-changed', (event) => this._zeroLineOffsetChanged(event));
                                }
                                else {
                                    this._log('_getInstances(): invalid zeroline offset input', 'ERROR');
                                }                          
                            } 
                            else {
                                //reset zerolineoffset input in case of reinitialization
                                instanceObj.zeroLineOffsetInput = undefined;
                            }                                 
                            //get input of zerolineoffset offset
                            const zeroLineOffsetKnobVM = instanceObj.vm.getChildByName('@DA_ZeroLineOffset_Knob');
                            if (zeroLineOffsetKnobVM !== null) {
                                //get domref of zerolineoffset
                                instanceObj.zeroLineOffsetKnob = zeroLineOffsetKnobVM.getDomRef();
                                //add observer for changes
                                if (instanceObj.zeroLineOffsetKnob !== undefined) {
                                    //save id of parent cc so at selection changed we can refer to instance. Simply getting the parent id is not correct, cause it might
                                    //be placed within another cc
                                    instanceObj.zeroLineOffsetKnob.daCCParent = ccs[i].id;
                                    //create callback for value changed
                                    const vcCallback = (event) => {
                                        if (this.zeroLineOffsetDebouncer === undefined) {
                                            this.zeroLineOffsetDebouncer = this.sigSetTimeout(() => {
                                                this._zeroLineOffsetKnobChanged(event);
                                                this.zeroLineOffsetDebouncer = undefined;
                                            }, 20);                                            
                                        } 
                                    }
                                    //check if unconverted values should be used
                                    //knob was updated to use unconverted values but we want to stay compatible with the old version of knob
                                    if (instanceObj.zeroLineOffsetKnob.valueuc !== undefined) {
                                        instanceObj.zeroLineOffsetKnob. useUnconverted = true;
                                        //listen to unconverted value changed
                                        instanceObj.zeroLineOffsetKnob.sigAddEventListener('valueuc-changed', vcCallback); 
                                    }      
                                    else {
                                        instanceObj.zeroLineOffsetKnob.sigAddEventListener('value-changed', vcCallback); 
                                    }                                
                                       
                                }
                                else {
                                    this._log('_getInstances(): invalid zeroline offset input', 'ERROR');
                                }                          
                            } 
                            else {
                                //reset zerolineoffset input in case of reinitialization
                                instanceObj.zeroLineOffsetKnob = undefined;
                            }  

                            //save instances in array
                            this.instances.set(ccs[i].id, instanceObj);
                        }
                        else {
                            this._log('_getInstances(): get vm of cc failed', 'ERROR');
                        }                         
                    }        
                }                     
            }
            else {
                this._log('_getInstances(): get cc failed', 'ERROR');
            }             
        }
        else {
            this._log('_getInstances(): apis not ready', 'ERROR');
        }        
    }

    /**
     * gets called if channel selection was changed
     * @param {*} parentCC - parent composite control
     */
    _selectionChanged(parentCC) {
        if (parentCC !== undefined) {
            //get instance object
            const instObj = this.instances.get(parentCC);
            if (instObj !== undefined) {
                this._overloadCC(instObj.vm, instObj.channelSelectionMenu).then(() => {
                    //rebuild scaletype list to remove actual selected channel
                    this._buildScaleTypeMenu(instObj.channelSelectionMenu, instObj.scaleTypeMenu, true);
                    //build server list new cause userbit might change
                    this._buildServerMenuList(instObj.channelSelectionMenu, instObj.serverConfigMenu, true);
                    //update channel name
                    this._setChannelName(instObj.channelSelectionMenu, instObj.channelNameInput);
                    //format limits
                    this._formatLimits(instObj.channelSelectionMenu, instObj.minValueInput, instObj.maxValueInput); 
                    //format value per division
                    this._formatValuePerDiv(instObj.channelSelectionMenu, instObj.valuePerDivInput);  
                    //format zeroline offset
                    this._formatZeroLineOffset(instObj.channelSelectionMenu, instObj.zeroLineOffsetInput);  
                    //format zeroline offset knob
                    this._formatZeroLineOffsetKnob(instObj.channelSelectionMenu, instObj.zeroLineOffsetKnob);                                                                           
                });            
            } 
            else {
                this._log('_selectionChanged(): get instances failed', 'ERROR');
            }           
        }
        else {
            this._log('_selectionChanged(): invalid instances', 'ERROR');
        }
    }

    /**
     * gets called if minvalue was changed
     * @param {*} event - event of value changed event
     */
    async _minValueChanged(event) {
        if (this.instances !== undefined) {
            //get instance object
            const instObj = this.instances.get(event.srcElement.daCCParent);
            if (instObj !== undefined) {
                //check if channelselection is valid
                if (instObj.channelSelectionMenu.value !== undefined) {
                    //check if inputs for limits exist
                    if ((instObj.minValueInput !== undefined)) {
                        //check if element has already been formatted -> if not we ignore changed event cause it is the initial value
                        if (instObj.minValueInput.formatted === true) {              
                            //get actual selected channel
                            if (this.DA_DataManager !== undefined) {
                                //get visu channels
                                const visuChls = this.DA_DataManager.getVisuChannels(this.graphinstanceid);
                                if (visuChls !== undefined) {
                                    const channel = visuChls.get(instObj.channelSelectionMenu.value);
                                    if (channel !== undefined) {
                                        let realChl = this.DA_DataManager.getChannelByID(channel.chlReference.stationNumber, channel.chlReference.chlID);
                                        if (realChl !== undefined) {
                                            //get datapoint to get is floating point info
                                            const dp = this.datapointApi.getDatapoint(realChl.srcVarID);
                                            if (dp !== null) {
                                                const isFloatingPoint = dp.isFloatingPoint();
                                                //check if value needs to be converted back
                                                let value = instObj.minValueInput.value;
                                                if (instObj.minValueInput.unitInfo !== undefined) {
                                                    value = await this._convertValueBack(value, instObj.minValueInput.unitInfo, isFloatingPoint);
                                                }
                                                value = this.DA_DataManager.getUncastedValue(realChl, value, channel.minScale.ref);
                                                if (value !== undefined) {
                                                    //check for datapoint given
                                                    if (channel.minScale.ref !== undefined) {
                                                        if (this.datapointApi !== undefined) {
                                                            this.datapointApi.writeDataPoint(channel.minScale.ref.getId(), value);
                                                        }
                                                        else {
                                                            this._log("_minValueChanged(): invalid datapoint api", 'ERROR')
                                                        }
                                                    }
                                                    channel.minScale.value = value;                                
                                                }
                                                else {
                                                    this._log('_minValueChanged(): uncast value failed', 'ERROR');
                                                }                                  
                                            }
                                            else {
                                                this._log('_minValueChanged(): get datapoint failed', 'ERROR');
                                            }    
                                        }
                                        else {
                                            this._log('_minValueChanged(): get real channel failed', 'ERROR');
                                        }                                                         
                                    }
                                    else {
                                        this._log('_minValueChanged(): failed to get channel', 'ERROR');
                                    } 
                                }
                                else {
                                    this._log('_minValueChanged(): get visuchannels failed', 'ERROR');
                                }
                            }    
                            else {
                                this._log('_minValueChanged(): invalid datamanager reference', 'ERROR');
                            } 
                        }                                              
                    }                     
                }
                else {
                    //no error log cause this might happen due to bad timing
                }
            } 
            else {
                this._log('_minValueChanged(): get instances failed', 'ERROR');
            }           
        }
        else {
            this._log('_minValueChanged(): invalid instances', 'ERROR');
        }        
 
    }

    /**
     * gets called if maxvalue was changed
     * @param {*} event - event of value changed event
     */
    async _maxValueChanged(event) {
        if (this.instances !== undefined) {
            //get instance object
            const instObj = this.instances.get(event.srcElement.daCCParent);
            if (instObj !== undefined) {     
                //check if channelselection is valid
                if (instObj.channelSelectionMenu.value !== undefined) {                   
                    //check if inputs for limits exist
                    if ((instObj.maxValueInput !== undefined)) {
                        //check if element has already been formatted -> if not we ignore changed event cause it is the initial value
                        if (instObj.maxValueInput.formatted === true) {               
                            //get actual selected channel
                            if (this.DA_DataManager !== undefined) {
                                //get visu channels
                                const visuChls = this.DA_DataManager.getVisuChannels(this.graphinstanceid);
                                if (visuChls !== undefined) {
                                    const channel = visuChls.get(instObj.channelSelectionMenu.value);
                                    if (channel !== undefined) {
                                        let realChl = this.DA_DataManager.getChannelByID(channel.chlReference.stationNumber, channel.chlReference.chlID);
                                        if (realChl !== undefined) {
                                            //get datapoint to get is floating point info
                                            const dp = this.datapointApi.getDatapoint(realChl.srcVarID);
                                            if (dp !== null) {
                                                const isFloatingPoint = dp.isFloatingPoint();                            
                                                //check if value needs to be converted back
                                                let value = instObj.maxValueInput.value;
                                                if (instObj.maxValueInput.unitInfo !== undefined) {
                                                    value = await this._convertValueBack(value, instObj.maxValueInput.unitInfo, isFloatingPoint);
                                                }
                                                value = this.DA_DataManager.getUncastedValue(realChl, value, channel.maxScale.ref);
                                                if (value !== undefined) {
                                                    if (channel.maxScale.ref !== undefined) {
                                                        if (this.datapointApi !== undefined) {
                                                            this.datapointApi.writeDataPoint(channel.maxScale.ref.getId(), value);
                                                        }
                                                        else {
                                                            this._log("_maxValueChanged(): invalid datapoint api", 'ERROR')
                                                        }                        
                                                    }
                                                    channel.maxScale.value = value;                                 
                                                }
                                                else {
                                                    this._log('_maxValueChanged(): uncast value failed', 'ERROR');
                                                } 
                                            }
                                            else {
                                                this._log('_maxValueChanged(): get datapoint failed', 'ERROR');
                                            }     
                                        }
                                        else {
                                            this._log('_maxValueChanged(): get real channel failed', 'ERROR');
                                        }                                                      
                                    }
                                    else {
                                        this._log('_maxValueChanged(): failed to get channel', 'ERROR');
                                    } 
                                }
                                else {
                                    this._log('_maxValueChanged(): get visuchannels failed', 'ERROR');
                                }
                            }    
                            else {
                                this._log('_maxValueChanged(): invalid datamanager reference', 'ERROR');
                            } 
                        }                                              
                    } 
                }
                else {
                    //no error log cause this might happen due to bad timing
                }    
            } 
            else {
                this._log('_maxValueChanged(): get instances failed', 'ERROR');
            }           
        }
        else {
            this._log('_maxValueChanged(): invalid instances', 'ERROR');
        }                        
    }  

    /**
     * gets called if zerolineoffset was changed
     * @param {*} event - event of value changed event
     */
     async _zeroLineOffsetChanged(event) {
        if (this.instances !== undefined) {
            //get instance object
            const instObj = this.instances.get(event.srcElement.daCCParent);
            if (instObj !== undefined) {  
                //check if channelselection is valid
                if (instObj.channelSelectionMenu.value !== undefined) {      
                    //check if inputs for zerolineoffset exist
                    if ((instObj.zeroLineOffsetInput !== undefined)) {
                        //check if element has already been formatted -> if not we ignore changed event cause it is the initial value
                        if (instObj.zeroLineOffsetInput.formatted === true) {               
                            //get actual selected channel
                            if (this.DA_DataManager !== undefined) {
                                //get visu channels
                                const visuChls = this.DA_DataManager.getVisuChannels(this.graphinstanceid);
                                if (visuChls !== undefined) {
                                    const channel = visuChls.get(instObj.channelSelectionMenu.value);
                                    if (channel !== undefined) {
                                        let realChl = this.DA_DataManager.getChannelByID(channel.chlReference.stationNumber, channel.chlReference.chlID);
                                        if (realChl !== undefined) {
                                            //get datapoint to get is floating point info
                                            const dp = this.datapointApi.getDatapoint(realChl.srcVarID);
                                            if (dp !== null) {
                                                const isFloatingPoint = dp.isFloatingPoint();                            
                                                //check if value needs to be converted back
                                                let value = instObj.zeroLineOffsetInput.value;
                                                if (instObj.zeroLineOffsetInput.unitInfo !== undefined) {
                                                    value = await this._convertValueBack(value, instObj.zeroLineOffsetInput.unitInfo, isFloatingPoint);
                                                }
                                                value = this.DA_DataManager.getUncastedValue(realChl, value, channel.zeroLineOffset.ref);
                                                if (value !== undefined) {
                                                    if (channel.zeroLineOffset.ref !== undefined) {
                                                        if (this.datapointApi !== undefined) {
                                                            this.datapointApi.writeDataPoint(channel.zeroLineOffset.ref.getId(), value);
                                                        }
                                                        else {
                                                            this._log("_zeroLineOffsetChanged(): invalid datapoint api", 'ERROR')
                                                        }                        
                                                    }
                                                    channel.zeroLineOffset.value = value;                                 
                                                }
                                                else {
                                                    this._log('_zeroLineOffsetChanged(): uncast value failed', 'ERROR');
                                                } 
                                            }
                                            else {
                                                this._log('_zeroLineOffsetChanged(): get datapoint failed', 'ERROR');
                                            }     
                                        }
                                        else {
                                            this._log('_zeroLineOffsetChanged(): get real channel failed', 'ERROR');
                                        }                                                      
                                    }
                                    else {
                                        this._log('_zeroLineOffsetChanged(): failed to get channel', 'ERROR');
                                    } 
                                }
                                else {
                                    this._log('_zeroLineOffsetChanged(): get visuchannels failed', 'ERROR');
                                }
                            }    
                            else {
                                this._log('_zeroLineOffsetChanged(): invalid datamanager reference', 'ERROR');
                            } 
                        }                                              
                    }
                }     
                else {
                    //no error log cause this might happen due to bad timing
                } 
            } 
            else {
                this._log('_zeroLineOffsetChanged(): get instances failed', 'ERROR');
            }           
        }
        else {
            this._log('_zeroLineOffsetChanged(): invalid instances', 'ERROR');
        }                        
    }  

    /**
     * gets called if zerolineoffset knob was changed
     * @param {*} event - event of value changed event
     */
     async _zeroLineOffsetKnobChanged(event) {
        if (this.instances !== undefined) {
            //get instance object
            const instObj = this.instances.get(event.srcElement.daCCParent);
            if (instObj !== undefined) {       
                //check if channelselection is valid
                if (instObj.channelSelectionMenu.value !== undefined) {                 
                    //check if inputs for zerolineoffset exist
                    if ((instObj.zeroLineOffsetKnob !== undefined)) {            
                        //get actual selected channel
                        if (this.DA_DataManager !== undefined) {
                            //get visu channels
                            const visuChls = this.DA_DataManager.getVisuChannels(this.graphinstanceid);
                            if (visuChls !== undefined) {
                                const channel = visuChls.get(instObj.channelSelectionMenu.value);
                                if (channel !== undefined) {
                                    let realChl = this.DA_DataManager.getChannelByID(channel.chlReference.stationNumber, channel.chlReference.chlID);
                                    if (realChl !== undefined) {                            
                                        //check if value needs to be converted back
                                        let value = instObj.zeroLineOffsetKnob.useUnconverted ? instObj.zeroLineOffsetKnob.valueuc : instObj.zeroLineOffsetKnob.value;
                                        value = this.DA_DataManager.getUncastedValue(realChl, value, channel.zeroLineOffset.ref);
                                        if (value !== undefined) {
                                            if (channel.zeroLineOffset.ref !== undefined) {
                                                if (this.datapointApi !== undefined) {
                                                    this.datapointApi.writeDataPoint(channel.zeroLineOffset.ref.getId(), value);
                                                }
                                                else {
                                                    this._log("_zeroLineOffsetKnobChanged(): invalid datapoint api", 'ERROR')
                                                }                        
                                            }
                                            channel.zeroLineOffset.value = value;                                 
                                        }
                                        else {
                                            this._log('_zeroLineOffsetKnobChanged(): uncast value failed', 'ERROR');
                                        }    
                                    }
                                    else {
                                        this._log('_zeroLineOffsetKnobChanged(): get real channel failed', 'ERROR');
                                    }                                                      
                                }
                                else {
                                    this._log('_zeroLineOffsetKnobChanged(): failed to get channel', 'ERROR');
                                } 
                            }
                            else {
                                this._log('_zeroLineOffsetKnobChanged(): get visuchannels failed', 'ERROR');
                            }
                        }    
                        else {
                            this._log('_zeroLineOffsetKnobChanged(): invalid datamanager reference', 'ERROR');
                        }                                              
                    } 
                }     
                else {
                    //no error log cause this might happen due to bad timing
                }                     
            } 
            else {
                this._log('_zeroLineOffsetKnobChanged(): get instances failed', 'ERROR');
            }           
        }
        else {
            this._log('_zeroLineOffsetKnobChanged(): invalid instances', 'ERROR');
        }                        
    }  

    /**
     * gets called if server selection was changed
     * @param {*} event - event of value changed event
     */
    async _serverSelectionChanged(event) {
        //check for datamanager
        if (this.DA_DataManager !== undefined) {
            if (this.instances !== undefined) {
                //get instance object
                const instObj = this.instances.get(event.srcElement.daCCParent);
                if (instObj !== undefined) {   
                    //check if channelselection is valid
                    if (instObj.channelSelectionMenu.value !== undefined) {                              
                        //get visu channels
                        const visuChls = this.DA_DataManager.getVisuChannels(this.graphinstanceid);
                        if (visuChls !== undefined) {
                            const channel = visuChls.get(instObj.channelSelectionMenu.value);
                            if (channel !== undefined) {
                                //get real channel
                                if (channel.chlReference !== undefined) {                                       
                                    //check for valid menu instance
                                    if (instObj.serverConfigMenu !== undefined) {
                                        //get actual selection
                                        const varID = parseInt(instObj.serverConfigMenu.value);
                                        //check if datapoint api available
                                        if ((this.datapointApi !== undefined) && (this.constApi !== undefined)) {
                                            //get datapoint for getting datatype
                                            const datapoint = this.datapointApi.getDatapoint(varID);
                                            if (datapoint !== null) {
                                                //get type ref id
                                                const typeRef = datapoint.getTypeRefId();
                                                try {
                                                    //get lasal id
                                                    let result = await this.datapointApi.getLasalIdFromId(varID);
                                                    if ((result !== undefined) && (result[0] !== undefined)) {
                                                        const lasalID = result[0];
                                                        //get crc
                                                        result = await this.datapointApi.getCRCFromId(varID);
                                                        if ((result !== undefined) && (result[0] !== undefined)) {
                                                            const crc = result[0];
                                                            //request setting new server
                                                            this.DA_DataManager.setNewChannelServer(channel.chlReference.stationNumber, channel.chlReference.chlID, 
                                                                                                    lasalID, crc, varID, typeRef);
                                                        }
                                                        else {
                                                            this._log('_serverSelectionChanged(): get crc failed', 'ERROR');
                                                        }                          
                                                    }
                                                    else {
                                                        this._log('_serverSelectionChanged(): get lasal id failed', 'ERROR');
                                                    }                         
                                                }
                                                catch (error) {
                                                    this._log('_serverSelectionChanged(): failed to get dp infos -> ' + error, 'ERROR');
                                                }                                    
                                            }
                                            else {
                                                this._log('_serverSelectionChanged(): failed to get datapoint', 'ERROR');
                                            }
                                        }   
                                        else {
                                            this._log('_serverSelectionChanged(): invalid apis', 'ERROR');
                                        }            
                                    }
                                    else {
                                        this._log('_serverSelectionChanged(): invalid server config reference', 'ERROR');
                                    }                                  
                                }
                                else {
                                    this._log('_serverSelectionChanged(): invalid channel reference', 'ERROR');
                                }   
                            }
                            else {
                                this._log('_serverSelectionChanged(): channel not found', 'ERROR');
                            }  
                        }
                        else {
                            this._log('_serverSelectionChanged(): get visu channels failed', 'ERROR');
                        } 
                    }     
                    else {
                        //no error log cause this might happen due to bad timing
                    }                         
                } 
                else {
                    this._log('_serverSelectionChanged(): get instances failed', 'ERROR');
                }           
            }
            else {
                this._log('_serverSelectionChanged(): invalid instances', 'ERROR');
            }                                               
        }
        else {
            this._log('_serverSelectionChanged(): invalid data manager reference', 'ERROR');
        }     
    }  

    /**
     * gets called if channel name was changed
     * @param {*} event - event of value changed event
     */
    async _channelInputChanged(event) {
        //write channel name to server
        if (this.datapointApi !== undefined) {
            //get actual selected channel
            if (this.DA_DataManager !== undefined) {
                if (this.instances !== undefined) {
                    //get instance object
                    const instObj = this.instances.get(event.srcElement.daCCParent);
                    if (instObj !== undefined) {   
                        //check if channelselection is valid
                        if (instObj.channelSelectionMenu.value !== undefined) {                                       
                            //get visu channels
                            const visuChls = this.DA_DataManager.getVisuChannels(this.graphinstanceid);
                            if (visuChls !== undefined) {
                                const channel = visuChls.get(instObj.channelSelectionMenu.value);
                                if (channel !== undefined) {
                                    //get real channel
                                    if (channel.chlReference !== undefined) {
                                        const realChl = this.DA_DataManager.getChannelByID(channel.chlReference.stationNumber, channel.chlReference.chlID);
                                        if (realChl !== undefined) {
                                            //get channel name
                                            try {
                                                //get id of channel name datapoint
                                                const result = await this.datapointApi.getIdFromLasalId(realChl.chlNameLasalID, channel.chlReference.stationNumber);
                                                if ((result !== undefined) && (result[0] !== undefined)) {
                                                    const varID = result[0];
                                                    //set new channelname
                                                    await this.datapointApi.writeDataPoint(varID, instObj.channelNameInput.value);                                                           
                                                }   
                                                else {
                                                    this._log('_channelInputChanged(): get varid failed', 'ERROR');
                                                }                                                                                                                                                                       
                                            }
                                            catch (error) {
                                                this._log('_channelInputChanged(): get channel name lasal id failed -> ' + error, 'ERROR');
                                            }                                     
                                        }
                                        else {
                                            this._log('_channelInputChanged(): get real channel failed', 'ERROR');
                                        }                                   
                                    }
                                    else {
                                        this._log('_channelInputChanged(): invalid channel reference', 'ERROR');
                                    }   
                                }
                                else {
                                    this._log('_channelInputChanged(): channel not found', 'ERROR');
                                }  
                            }
                            else {
                                this._log('_channelInputChanged(): get visu channels failed', 'ERROR');
                            }
                        }
                        else {
                            //no error log cause this might happen due to bad timing
                        }    
                    } 
                    else {
                        this._log('_channelInputChanged(): get instances failed', 'ERROR');
                    }           
                }
                else {
                    this._log('_channelInputChanged(): invalid instances', 'ERROR');
                }                           
            }
            else {
                this._log('_channelInputChanged(): invalid datamanager reference', 'ERROR');
            }              
        }
        else {
            this._log('_channelInputChanged(): invalid datapoint api', 'ERROR');
        }
    }

    /****************************************************************************************************
     * method is used to build channel menu -> special handling with promises cause there might be 
     * multiple calls due to update events which should be called back if the menu was built
     *
     * @param {boolean} [renew=false] - if true menu will be rebuild anyway
     * @return {Promise} - resolved if channel menu available 
     * @memberof LasalRuntimeSigControlDAChannelSettings
     ****************************************************************************************************/
    _buildChannelMenu(renew=false) {
        //check if promise active
        if ((this.channelMenuPromise) && (this.channelMenuPromise.pending)) {
            //check if channel menue should be renewed
            if (renew) this.renewChannelMenue = true;
            //return active promise
            return this.channelMenuPromise;
        }
        else {
            //create new promise
            //define promise for return
            this.channelMenuPromise = new Promise((resolve, reject) => {
                //build menu list
                this._buildChannelMenuList(renew).then(() => {
                    this.channelMenuPromise.pending = false;
                    resolve();
                }).catch((error) => {
                    this.channelMenuPromise.pending = false;
                    reject(error);
                })
            });
            //append pending info
            this.channelMenuPromise.pending = true;
            return this.channelMenuPromise; 
        }               
    }

    /****************************************************************************************************
     * method is used to create the channel menu
     *
     * @param {*} renew - info if new menu should be build anyway
     * @return {Promise} - promise pending until menu was created 
     * @memberof LasalRuntimeSigControlDAChannelSettings
     ****************************************************************************************************/
    _buildChannelMenuList(renew) {
        return new Promise(async (resolve, reject) => {
            //check for valid apis
            if ((this.menuApi !== undefined) && (this.constApi !== undefined)) {            
                //----------------------------------------------------------------------------------------
                //-- create menue with visu channels
                //---------------------------------------------------------------------------------------- 
                //check if menu should be created new
                if (renew) {
                    if (this.visuChlsMenu !== undefined) {
                        this.menuApi.removeMenu(this.visuChlsMenu.getIndex());
                        this.visuChlsMenu = undefined;                        
                    }
                }
                //check if channel selection menu has already been created
                if (this.visuChlsMenu === undefined) {                         
                    //get visu channels
                    if (this.DA_DataManager !== undefined) {
                        //create blueprint
                        let menuBluePrint = {
                            name: this.graphinstanceid + '_channelSelection',
                            menuItems: []
                        }
                        //get visu channels
                        const visuChls = this.DA_DataManager.getVisuChannels(this.graphinstanceid);
                        if (visuChls !== undefined) {        
                            let menuProps = {
                                name: undefined,
                                props: {
                                    value: {
                                        name: 'value',
                                        value: undefined,
                                        src: this.constApi.PROP_SRC_CONSTANT,
                                        dest: this.constApi.PROP_DEST_VARIABLE
                                    },
                                    text: {
                                        name: 'text',
                                        value: undefined,
                                        src: this.constApi.PROP_SRC_CONSTANT,
                                        dest: this.constApi.PROP_DEST_VARIABLE
                                    }
                                } 
                            }                          
                            for (let [visuChlID, channel] of visuChls) {
                                //set name of entry
                                menuProps.name = 'channel' + visuChlID;
                                //set visuchannel id as value
                                menuProps.props.value.value = visuChlID;
                                //get channel name
                                if (channel.chlReference !== undefined) {
                                    //get real channel
                                    const realChl = this.DA_DataManager.getChannelByID(channel.chlReference.stationNumber, channel.chlReference.chlID);
                                    if (realChl !== undefined) {
                                        if(this.datapointApi !== undefined) {
                                            //get channel name
                                            try {
                                                //get id of channel name datapoint
                                                const result = await this.datapointApi.getIdFromLasalId(realChl.chlNameLasalID, channel.chlReference.stationNumber);
                                                if ((result !== undefined) && (result[0] !== undefined)) {
                                                    const varID = result[0];
                                                    //get data point
                                                    const datapoint = this.datapointApi.getDatapoint(varID);
                                                    if (datapoint !== null) {
                                                        let channelName = await datapoint.getValue();
                                                        if (channelName === '') {
                                                            //if no channelname configured, we take the var text 1 of the source
                                                            channelName = await this.datapointApi.getDatapointText(realChl.srcVarID, 'text1');
                                                        }
                                                        menuProps.props.text.value = visuChlID + ' : ' + channelName;
                                                        //add item
                                                        menuBluePrint.menuItems.push(JSON.parse(JSON.stringify(menuProps)));
                                                    }
                                                    else {
                                                        reject('_buildChannelMenuList(): get datapoint failed');                                                         
                                                    }                                                             
                                                }   
                                                else {
                                                    reject('_buildChannelMenuList(): get varid failed');                                                     
                                                }                                                                                                                                                                       
                                            }
                                            catch (error) {
                                                reject('_buildChannelMenuList(): get channel name lasal id failed -> ' + error);                                                 
                                            }                                                       
                                        }
                                        else {
                                            reject('_buildChannelMenuList(): invalid datapoint api');                                                 
                                        }            
                                    }
                                    else {
                                        reject('_buildChannelMenuList(): get real channel failed');                                             
                                    }                                                 
                                }
                                else {
                                    reject('_buildChannelMenuList(): invalid channel reference');                                         
                                }                                            
                            }
                            //add menu
                            this.visuChlsMenu = this.menuApi.addMenu(menuBluePrint);
                        }                          
                    }
                    else {
                        reject('_buildChannelMenuList(): invalid datamanager reference');                             
                    }                  
                } 
                
                //check if a renew was triggered in the meantime
                if (this.renewChannelMenue) {
                    this.renewChannelMenue = false;
                    this._buildChannelMenuList(true).then(() => {
                        resolve();
                    }).catch((error) => {
                        reject(error);
                    });
                }
                else {
                    resolve();                        
                }                
            }         
            else {
                reject('_buildChannelMenuList(): invalid apis');                    
            } 
        })
    }

    /**
     * this method is used to build the entries for the menues
     * @param {*} channelSelectionMenu - menu instance for channel selection
     * @param {*} scaleTypeMenu - menu instance for scale type
     * @param {*} renew - false .. menus are not created new, true .. menus are created new
     */
    _setChannelMenuList(channelSelectionMenu, scaleTypeMenu, renew) {
        //check for valid apis
        if ((this.menuApi !== undefined) && (this.constApi !== undefined)) {
            //check if channel selection menu has already been created
            if (this.visuChlsMenu !== undefined) {                                     
                //---------------------------------------------------------------------------------------------------------------------------------------
                //-- set selection menu
                //---------------------------------------------------------------------------------------------------------------------------------------
                if (channelSelectionMenu !== undefined) {
                    //set channel selection menu reference
                    channelSelectionMenu.menuref = this.visuChlsMenu.getIndex();
                    //update text on menu input
                    channelSelectionMenu._updateValue(channelSelectionMenu.value);         
                }        
                //---------------------------------------------------------------------------------------------------------------------------------------

                //---------------------------------------------------------------------------------------------------------------------------------------
                //-- build scale type menu
                //---------------------------------------------------------------------------------------------------------------------------------------
                this._buildScaleTypeMenu(channelSelectionMenu, scaleTypeMenu, renew);
            }
            else {
                this._log('_setChannelMenuList(): invalid channel menu', 'ERROR');
            }    
        }
        else {
            this._log('_setChannelMenuList(): invalid apis', 'ERROR');
        }
    }    

    /**
     * build scaletype menu
     * @param {*} channelSelectionMenu - menu instance for channel selection
     * @param {*} scaleTypeMenu - menu instance to manipulate 
     * @param {*} renew - false..menu is not renewed. true..menu is renewed
     */
    _buildScaleTypeMenu(channelSelectionMenu, scaleTypeMenu, renew=false) {
        if (scaleTypeMenu !== undefined) {
            //check if scale type menu should be renewed
            if (renew) {
                if (this.scaleTypeMenu !== undefined) {
                    this.menuApi.removeMenu(this.scaleTypeMenu.getIndex());
                    this.scaleTypeMenu = undefined;
                }
            }
            if (this.scaleTypeMenu === undefined) {
                //get blueprint of channel selection
                if (this.visuChlsMenu !== undefined) {
                    let blueprint = this.visuChlsMenu.getBlueprint();
                    if (blueprint !== undefined) {
                        //remove actual channel selection from menu
                        if (channelSelectionMenu !== undefined) {
                            //filter own channel for selection
                            blueprint.menuItems = blueprint.menuItems.filter((item) => item.props.value.value !== channelSelectionMenu.value);
                        }
                        //----------------------------------------------------------------------------------------
                        //-- set entries of menu
                        //----------------------------------------------------------------------------------------
                        //check if menu configured
                        if (scaleTypeMenu.menuref !== undefined) {
                            //check if original menu ref needs to be set -> otherwise reference will be overwritten
                            if (scaleTypeMenu.origMenuRef === undefined) {
                                scaleTypeMenu.origMenuRef = scaleTypeMenu.menuref;
                            }
                            //check if menu api ready
                            if (this.menuApi !== undefined) {
                                //get menu
                                const menu = this.menuApi.getMenu(scaleTypeMenu.origMenuRef);
                                if (menu !== null) {
                                    //get items of menu
                                    const defaultBP = menu.getBlueprint();
                                    if ((defaultBP !== undefined) && (defaultBP.menuItems.length > 0)) {
                                        for (let i=0;i<defaultBP.menuItems.length;i++) {
                                            //add menu items at beginning
                                            blueprint.menuItems.unshift(defaultBP.menuItems[i]);
                                        }
                                    }
                                }
                                else {
                                    this._log('_buildScaleTypeMenu(): failed to get menu', 'ERROR');
                                }                
                            }
                        }  
                        //create menu out of blueprint
                        this.scaleTypeMenu = this.menuApi.addMenu(blueprint);                              
                    }
                    else {
                        this._log('_buildScaleTypeMenu(): get blueprint failed', 'ERROR');
                    }    
                }                               
            }
            //add menu as ref
            if (this.scaleTypeMenu !== undefined) {
                scaleTypeMenu.menuref = this.scaleTypeMenu.getIndex();
                //update text of input
                scaleTypeMenu._updateValue(scaleTypeMenu.value);
            }
        } 
    }

    /****************************************************************************************************
     * method is used to build channel menu -> special handling with promises cause there might be 
     * multiple calls due to update events which should be called back if the menu was built
     *
     * @param {boolean} [renew=false] - if true menu will be rebuild anyway
     * @return {Promise} - resolved if channel menu available 
     * @memberof LasalRuntimeSigControlDAChannelSettings
     ****************************************************************************************************/
    _buildRealChannelMenu(renew=false) {
        //check if promise active
        if ((this.realChannelMenuPromise) && (this.realChannelMenuPromise.pending)) {
            //check if channel menue should be renewed
            if (renew) this.renewRealChannelMenue = true;
            //return active promise
            return this.realChannelMenuPromise;
        }
        else {
            //create new promise
            //define promise for return
            this.realChannelMenuPromise = new Promise((resolve, reject) => {
                //build menu list
                this._buildRealChannelMenuList(renew).then(() => {
                    this.realChannelMenuPromise.pending = false;
                    resolve();
                }).catch((error) => {
                    this.realChannelMenuPromise.pending = false;
                    reject(error);
                })
            });
            //append pending info
            this.realChannelMenuPromise.pending = true;
            return this.realChannelMenuPromise; 
        }  
    }

    /****************************************************************************************************
     * method is used to build the real channel menu list
     *
     * @param {boolean} [renew=false] - if true the old menu will be destroyed and a new one will be created
     * @return {Promise} - Promise resolved if building menu is finished 
     * @memberof LasalRuntimeSigControlDAChannelSettings
     ****************************************************************************************************/
    _buildRealChannelMenuList(renew=false) {
        //define promise for return
        return new Promise(async (resolve, reject) => {            
            //check for valid apis
            if ((this.menuApi !== undefined) && (this.constApi !== undefined)) {            
                //----------------------------------------------------------------------------------------
                //-- create menue with real channels
                //---------------------------------------------------------------------------------------- 
                //check if menu should be created new
                if (renew) {
                    if (this.realChlMenu !== undefined) {
                        this.menuApi.removeMenu(this.realChlMenu.getIndex());
                        this.realChlMenu = undefined;                        
                    }
                }
                //check if channel selection menu has already been created
                if (this.realChlMenu === undefined) { 
                    //get visu channels
                    if (this.DA_DataManager !== undefined) {
                        //get real channels
                        const channels = this.DA_DataManager.getRegisteredChannels();
                        if (channels !== undefined) {                               
                            //create blueprint
                            let menuBluePrint = {
                                name: this.graphinstanceid + '_realChannelSelection',
                                menuItems: []
                            }  
                            let menuProps = {
                                name: undefined,
                                props: {
                                    value: {
                                        name: 'value',
                                        value: undefined,
                                        src: this.constApi.PROP_SRC_CONSTANT,
                                        dest: this.constApi.PROP_DEST_VARIABLE
                                    },
                                    text: {
                                        name: 'text',
                                        value: undefined,
                                        src: this.constApi.PROP_SRC_CONSTANT,
                                        dest: this.constApi.PROP_DEST_VARIABLE
                                    }                                 
                                } 
                            }                         
                            //get through dms stations and managers to get channel
                            for (let [dmsKey, managers] of channels) {
                                if (managers.size > 0) {
                                    for (let [mngKey, manager] of managers) {
                                        if (manager.stations.size > 0) {
                                            for (let [dasStationNumber, station] of manager.stations) {
                                                if (station.channels.size > 0) {
                                                    for (let [chlID, channel] of station.channels) {
                                                        //get channel name
                                                        try {
                                                            //get id of channel server
                                                            let result = await this.datapointApi.getIdFromLasalId(channel.chlLasalID, dasStationNumber);
                                                            if ((result !== undefined) && (result[0] !== undefined)) {
                                                                const varID = result[0];
                                                                //get crc which is used as channel reference
                                                                result = await this.datapointApi.getCRCFromId(varID); 
                                                                if ((result !== undefined) && (result[0] !== undefined)) {
                                                                    menuProps.props.value.value = result[0];
                                                                }   
                                                                else {
                                                                    reject('_buildRealChannelMenuList(): get crc of channel failed');
                                                                }                                                                                                                              
                                                            }   
                                                            else {
                                                                reject('_buildRealChannelMenuList(): get crc of channel failed');
                                                            }                                                         
                                                            //get id of channel name datapoint
                                                            result = await this.datapointApi.getIdFromLasalId(channel.chlNameLasalID, dasStationNumber);
                                                            if ((result !== undefined) && (result[0] !== undefined)) {
                                                                const varID = result[0];
                                                                //get data point
                                                                const datapoint = this.datapointApi.getDatapoint(varID);
                                                                if (datapoint !== null) {
                                                                    let channelName = await datapoint.getValue();
                                                                    if (channelName === '') {
                                                                        //if no channelname configured, we take the var text 1 of the source
                                                                        channelName = await this.datapointApi.getDatapointText(channel.srcVarID, 'text1');
                                                                    }
                                                                    menuProps.props.text.value = channelName;
                                                                    //add item
                                                                    menuBluePrint.menuItems.push(JSON.parse(JSON.stringify(menuProps)));
                                                                }
                                                                else {
                                                                    reject('_buildRealChannelMenuList(): get datapoint failed');                                                                        
                                                                }                                                         
                                                            }   
                                                            else {
                                                                reject('_buildRealChannelMenuList(): get varid failed');                                                                       
                                                            }                                                                                                                                                                       
                                                        }
                                                        catch (error) {
                                                            reject('_buildRealChannelMenuList(): get channel name lasal id failed -> ' + error);                                                                   
                                                        }                                                       
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                            //create menu
                            this.realChlMenu = this.menuApi.addMenu(menuBluePrint);
                        }
                        else {
                            reject('_buildRealChannelMenuList(): get channels failed');                                  
                        }                              
                    }
                    else {
                        reject('_buildRealChannelMenuList(): invalid datamanager reference'); 
                    }                  
                }
                //check if menues should be rebuild
                if (this.renewRealChannelMenue) {
                    this.renewRealChannelMenue = false;
                    this._buildRealChannelMenuList(true).then(() => {
                        resolve();
                    }).catch((error) => {
                        reject(error);
                    });
                }
                else {
                    resolve();                        
                }
            }         
            else {
                reject('_buildRealChannelMenuList(): invalid apis');                    
            }             
        });
    }

    /**
     * method is used to build a selection list of recording channels
     * @param {*} realChannelSelectionMenu - menu instance for real channel selection
     */
    async _setRealChannelMenuList(realChannelSelectionMenu) {
        if (realChannelSelectionMenu !== undefined) {         
            if (this.realChlMenu !== undefined) {
                realChannelSelectionMenu.menuref = this.realChlMenu.getIndex();
                //update text in menu input
                realChannelSelectionMenu._updateValue(realChannelSelectionMenu.value);
            }        
        }
    }

    /**
     * method is used to build a selection list of servers which can be recorded
     * @param {*} channelSelectionMenu - menu instance for channel selection
     * @param {*} serverConfigMenu - menu instance for server configuration
     * @param {*} renew - info if menu should be renewed or not
     */
     async _buildServerMenuList(channelSelectionMenu, serverConfigMenu, renew=false) {
        if (this.serverMenuCreationActive !== true) {
            if ((channelSelectionMenu !== undefined) && (serverConfigMenu !== undefined)) {         
                if (this.DA_DataManager !== undefined) {
                    //check for valid datapoint api cause we need this later on
                    if ((this.datapointApi !== undefined) && (this.menuApi !== undefined) && (this.constApi !== undefined)) {
                        this.serverMenuCreationActive = true;
                        //check if menu should be created new
                        if (renew) {
                            if (this.serverMenuList !== undefined) {
                                this.menuApi.removeMenu(this.serverMenuList.getIndex());
                                this.serverMenuList = undefined;                        
                            }
                        }
                        //check if server menu list already created
                        if (this.serverMenuList === undefined) {                         
                            //create blueprint
                            let menuBluePrint = {
                                name: this.graphinstanceid + '_serverMenuList',
                                menuItems: []
                            }  
                            let menuProps = {
                                name: undefined,
                                props: {
                                    value: {
                                        name: 'value',
                                        value: undefined,
                                        src: this.constApi.PROP_SRC_CONSTANT,
                                        dest: this.constApi.PROP_DEST_VARIABLE
                                    },
                                    text: {
                                        name: 'text',
                                        value: undefined,
                                        src: this.constApi.PROP_SRC_CONSTANT,
                                        dest: this.constApi.PROP_DEST_VARIABLE
                                    }                                  
                                } 
                            }                       
                            //get visu channels
                            const visuChls = this.DA_DataManager.getVisuChannels(this.graphinstanceid);
                            if (visuChls !== undefined) {
                                const channel = visuChls.get(channelSelectionMenu.value);
                                //it is possible that channel is not found cause the login is done later
                                if (channel !== undefined) {
                                    //get real channel
                                    if (channel.chlReference !== undefined) {
                                        const realChl = this.DA_DataManager.getChannelByID(channel.chlReference.stationNumber, channel.chlReference.chlID);
                                        if (realChl !== undefined) {
                                            if ((serverConfigMenu.value !== undefined) && (serverConfigMenu.value !== realChl.srcVarID)) {
                                                this.ignoreSvrSelObs = true;                                  
                                            }
                                            //set value of menu
                                            serverConfigMenu.value = realChl.srcVarID;   
                                            try {
                                                //get list of servers by information of user defined bits
                                                const dpList = await this.datapointApi.getDpList_DS(channel.recordMask.value);
                                                if ((dpList !== undefined) && (dpList.length > 0)) {                                                        
                                                    //go through list and get server text 1
                                                    for (let i=0;i<dpList.length;i++) {
                                                        menuProps.name = 'source_' + dpList[i];
                                                        //id is variable id of server
                                                        menuProps.props.value.value = dpList[i];
                                                        menuProps.props.text.value = await this.datapointApi.getDatapointText(dpList[i], 'text1');
                                                        //add option
                                                        menuBluePrint.menuItems.push(JSON.parse(JSON.stringify(menuProps)));
                                                    }
                                                    //create menu
                                                    this.serverMenuList = this.menuApi.addMenu(menuBluePrint);
                                                }
                                            
                                            }
                                            catch (error) {
                                                this._log('_buildServerMenuList(): build server list failed', 'ERROR');
                                            }
                                        }
                                        else {
                                            this._log('_buildServerMenuList(): get real channel failed', 'ERROR');
                                        }                                   
                                    }
                                    else {
                                        this._log('_buildServerMenuList(): invalid channel reference', 'ERROR');
                                    }   
                                }
                            }
                        } 
                        if (this.serverMenuList !== undefined) {
                            serverConfigMenu.menuref = this.serverMenuList.getIndex();
                            //update text of menu input
                            serverConfigMenu._updateValue(serverConfigMenu.value);
                        }  
                        //reset active info
                        this.serverMenuCreationActive = false;
                        //check if menues should be rebuild
                        if ((this.renewServerMenues !== undefined) && (this.renewServerMenues.length > 0)) {
                            const renewEntry = this.renewServerMenues.splice(0);
                            this._buildServerMenuList(renewEntry[0].channelMenu, renewEntry[0].serverMenu, true);
                        }                         
                    }
                    else {
                        this._log('_buildServerMenuList(): invalid apis', 'ERROR');
                    }                                                     
                }
                else {
                    this._log('_buildServerMenuList(): invalid datamanager reference', 'ERROR');
                }             
            }            
        }      
        else {
            //safe infos for renewing channel menus
            if (this.renewServerMenues === undefined) {
                this.renewServerMenues = [];
            }
            //check if infos should be saved or already there
            if (this.renewServerMenues.length > 0) {
                //go through entries to check if already there
                for (let i=0;i<this.renewServerMenues.length;i++) {
                    if ((this.renewServerMenues[i].channelMenu === channelSelectionMenu) && (this.renewServerMenues[i].serverMenu === serverConfigMenu)) {
                        //no need for new entry
                        return;
                    }
                }
            }
            this.renewServerMenues.push(Object.assign(new Object(), {channelMenu: channelSelectionMenu, serverMenu: serverConfigMenu}));
        }
    }

    /**
     * method is used to set the datapoint of the name input in cc
     * @param {*} channelSelectionMenu - menu instance for channel selection
     * @param {*} channelNameInput - input instance for channelname
     */
    async _setChannelName(channelSelectionMenu, channelNameInput) {
        //set value of channelname
        if ((channelNameInput !== undefined) && (channelSelectionMenu !== undefined)) {
            //check if api ready
            if (this.datapointApi !== undefined) {
                //get actual selected channel
                if (this.DA_DataManager !== undefined) {
                    //get visu channels
                    const visuChls = this.DA_DataManager.getVisuChannels(this.graphinstanceid);
                    if (visuChls !== undefined) {
                        const channel = visuChls.get(channelSelectionMenu.value);
                        //it is possible that channel is not found cause the login is done later
                        if (channel !== undefined) {
                            //get real channel
                            if (channel.chlReference !== undefined) {
                                const realChl = this.DA_DataManager.getChannelByID(channel.chlReference.stationNumber, channel.chlReference.chlID);
                                if (realChl !== undefined) {
                                    //get channel name
                                    try {
                                        //get id of channel name datapoint
                                        const result = await this.datapointApi.getIdFromLasalId(realChl.chlNameLasalID, channel.chlReference.stationNumber);
                                        if ((result !== undefined) && (result[0] !== undefined)) {
                                            const varID = result[0];
                                            //get data point
                                            const datapoint = this.datapointApi.getDatapoint(varID);
                                            if (datapoint !== null) {
                                                //at least get value which is the name
                                                channelNameInput.value = await datapoint.getValue();
                                            }
                                            else {
                                                this._log('_setChannelName(): get datapoint failed', 'ERROR');
                                            }                                                             
                                        }   
                                        else {
                                            this._log('_setChannelName(): get varid failed', 'ERROR');
                                        }                                                                                                                                                                       
                                    }
                                    catch (error) {
                                        this._log('_setChannelName(): get channel name lasal id failed -> ' + error, 'ERROR');
                                    }                                     
                                }
                                else {
                                    this._log('_setChannelName(): get real channel failed', 'ERROR');
                                }                                   
                            }
                            else {
                                this._log('_setChannelName(): invalid channel reference', 'ERROR');
                            }   
                        } 
                    }
                }
                else {
                    this._log('_setChannelName(): invalid datamanager reference', 'ERROR');
                }                                                                    
            }
            else {
                this._log('_setChannelName(): invalid datapoint api', 'ERROR');
            }
        }
    }

    /**
     * method is used to format min and maxvalue
     * @param {*} channelSelectionMenu - menu instance for channel selection
     * @param {*} minValueInput - input instance for minimum scale value
     * @param {*} maxValueInput - input instance for maximum scale value
     */
    async _formatLimits(channelSelectionMenu, minValueInput, maxValueInput) {
        //avoid format
        //check if inputs for limits exist
        if ((channelSelectionMenu !== undefined) && (minValueInput !== undefined) && (maxValueInput !== undefined)) {
            //get actual selected channel
            if (this.DA_DataManager !== undefined) {
                //get visu channels
                const visuChls = this.DA_DataManager.getVisuChannels(this.graphinstanceid);
                if (visuChls !== undefined) {
                    const channel = visuChls.get(channelSelectionMenu.value);
                    //it is possible that channel is not found cause the login is done later
                    if (channel !== undefined) {
                        //check if datapoint api ready cause we need to get the source datapoint of the channel for the unit
                        if (this.datapointApi !== undefined) {
                            let realChl = this.DA_DataManager.getChannelByID(channel.chlReference.stationNumber, channel.chlReference.chlID);
                            if (realChl !== undefined) {
                                //get datapoint for limits and floatingpoint info
                                //get datapoint to get is floating point info
                                const dp = this.datapointApi.getDatapoint(realChl.srcVarID);
                                if (dp !== null) {                                
                                    //get limit values by evaluating datatype
                                    const limitValues = await this._getLimitValues(dp);
                                    if (limitValues !== undefined) {
                                        //get the unitproperty
                                        const unitInfo = dp.getProperties().unit;
                                        //get min and max value casted to correct format -> needs to be done afterwords cause it might change in the meantime
                                        const scaleValues = {
                                            minValue: this.DA_DataManager.getCastedValue(realChl, channel.minScale),
                                            maxValue: this.DA_DataManager.getCastedValue(realChl, channel.maxScale)
                                        }                                         
                                        if (unitInfo !== undefined) {
                                            const isFloatingPoint = dp.isFloatingPoint();                                            
                                            //Set limits - do not indicate overflow to be able to set values
                                            minValueInput.limitLow = await this._formatValue(limitValues.limitLow, unitInfo, isFloatingPoint, false);
                                            minValueInput.limitHigh = await this._formatValue(limitValues.limitHigh, unitInfo, isFloatingPoint, false);                               
                                            minValueInput.unittext = await this._getUnitText(unitInfo);
                                            maxValueInput.limitLow = minValueInput.limitLow;
                                            maxValueInput.limitHigh = minValueInput.limitHigh;                                 
                                            maxValueInput.unittext = minValueInput.unittext;
                                            //set unit info to convert value back to base unit later on
                                            minValueInput.unitInfo = unitInfo;
                                            maxValueInput.unitInfo = unitInfo;
                                            //reset formatted to avoid bigger units setting value 0
                                            minValueInput.formatted = false;  
                                            maxValueInput.formatted = false;                                                
                                            minValueInput.value = await this._formatValue(scaleValues.minValue, unitInfo, isFloatingPoint);
                                            maxValueInput.value = await this._formatValue(scaleValues.maxValue, unitInfo, isFloatingPoint);
                                            //set formatted
                                            minValueInput.formatted = true;  
                                            maxValueInput.formatted = true;                                                                                                                                                               
                                        }
                                        else {
                                            minValueInput.limitLow = limitValues.limitLow;
                                            minValueInput.limitHigh = limitValues.limitHigh;                                  
                                            minValueInput.unittext = '';
                                            maxValueInput.limitLow = minValueInput.limitLow;
                                            maxValueInput.limitHigh = minValueInput.limitHigh;                                 
                                            maxValueInput.unittext = '';   
                                            //set unit info to convert value back to base unit later on
                                            minValueInput.unitInfo = unitInfo;
                                            maxValueInput.unitInfo = unitInfo;  
                                            minValueInput.value = scaleValues.minValue; 
                                            maxValueInput.value = scaleValues.maxValue;
                                            //set formatted
                                            minValueInput.formatted = true;  
                                            maxValueInput.formatted = true;                                                                         
                                        } 
                                    }
                                    else {
                                        this._log('_formatLimits(): get limit values failed', 'ERROR');
                                    }                                                                                          
                                }
                                else {
                                    this._log('_formatLimits(): get datapoint failed', 'ERROR');
                                }                             
                            }
                            else {
                                this._log('_formatLimits(): get real channel failed', 'ERROR');
                            }                           
                        }
                        else {
                            this._log('_formatLimits(): datapoint api not ready', 'ERROR');
                        }                                 
                    }
                }
            }    
            else {
                this._log('_formatLimits(): invalid datamanager reference', 'ERROR');
            }                                           
        }         
    }

    /**
     * method is used to get the limits configured at the source datapoint
     * @param {*} datapoint - source datapoint to fetch the limits from
     * @returns 
     */
    async _getLimitValues(datapoint) {
        if ((datapoint !== undefined) && (datapoint !== null)) {
            //get limits
            let lowLimit = datapoint.getLimitLow();
            let highLimit = datapoint.getLimitHigh();
            if ((lowLimit) && (lowLimit.value !== undefined) && (highLimit) && (highLimit.value !== undefined)) {
                //check if limit is datapoint
                if (lowLimit.type === 2) {
                    lowLimit.value = await this.datapointApi.readDatapoint(lowLimit.value);
                }
                if (highLimit.type === 2) {
                    highLimit.value = await this.datapointApi.readDatapoint(highLimit.value);
                } 
                //return limits
                return {
                    limitLow: lowLimit.value,
                    limitHigh: highLimit.value
                }     
            }
            else {
                this._log('_getLimitValues(): get limits failed', 'ERROR');
                return;
            }
        }
        else {
            this._log('_getLimitValues(): invalid datapoint', 'ERROR');
        }
    }

    /**
     * method is used to format min and maxvalue
     * @param {*} channelSelectionMenu - menu instance for channel selection
     * @param {*} zeroLineOffsetInput - input instance for zeroline offset
     */
     async _formatZeroLineOffset(channelSelectionMenu, zeroLineOffsetInput) {
        //avoid format
        //check if inputs for zerolineoffset exist
        if ((channelSelectionMenu !== undefined) && (zeroLineOffsetInput !== undefined)) {
            //get actual selected channel
            if (this.DA_DataManager !== undefined) {
                //get visu channels
                const visuChls = this.DA_DataManager.getVisuChannels(this.graphinstanceid);
                if (visuChls !== undefined) {
                    const channel = visuChls.get(channelSelectionMenu.value);
                    //it is possible that channel is not found cause the login is done later
                    if (channel !== undefined) {
                        //check if datapoint api ready cause we need to get the source datapoint of the channel for the unit
                        if (this.datapointApi !== undefined) {
                            let realChl = this.DA_DataManager.getChannelByID(channel.chlReference.stationNumber, channel.chlReference.chlID);
                            if (realChl !== undefined) {
                                //get datapoint to get is floating point info and limit values
                                const dp = this.datapointApi.getDatapoint(realChl.srcVarID);
                                if (dp !== null) {                                
                                    //get limit values by evaluating datatype
                                    const limitValues = await this._getLimitValues(dp);
                                    if (limitValues !== undefined) {
                                        //get the unit property
                                        const unitInfo = dp.getProperties().unit;
                                        //get zeroline offset casted to correct format -> needs to be done afterwords cause it might change in the meantime
                                        const zeroLineOffset = this.DA_DataManager.getCastedValue(realChl, channel.zeroLineOffset);                                       
                                        if (unitInfo !== undefined) {
                                            const isFloatingPoint = dp.isFloatingPoint();                                            
                                            //Set limits - do not indicate overflow to be able to set values
                                            zeroLineOffsetInput.limitLow = await this._formatValue(limitValues.limitLow, unitInfo, isFloatingPoint, false);
                                            zeroLineOffsetInput.limitHigh = await this._formatValue(limitValues.limitHigh, unitInfo, isFloatingPoint, false);                               
                                            zeroLineOffsetInput.unittext = await this._getUnitText(unitInfo);
                                            //set unit info to convert value back to base unit later on
                                            zeroLineOffsetInput.unitInfo = unitInfo;
                                            //reset formatted
                                            zeroLineOffsetInput.formatted = false;                                               
                                            zeroLineOffsetInput.value = await this._formatValue(zeroLineOffset, unitInfo, isFloatingPoint);
                                            //set formatted
                                            zeroLineOffsetInput.formatted = true;                                                                                                                 
                                        }
                                        else {
                                            zeroLineOffsetInput.limitLow = limitValues.limitLow;
                                            zeroLineOffsetInput.limitHigh = limitValues.limitHigh;                                  
                                            zeroLineOffsetInput.unittext = ''; 
                                            //set unit info to convert value back to base unit later on
                                            zeroLineOffsetInput.unitInfo = unitInfo;
                                            zeroLineOffsetInput.value = zeroLineOffset; 
                                            //set formatted
                                            zeroLineOffsetInput.formatted = true;                          
                                        }                                                  
                                    }
                                    else {
                                        this._log('_formatZeroLineOffset(): get limit values failed', 'ERROR');
                                    }
                                } 
                                else {
                                    this._log('_formatZeroLineOffset(): datapoint not found', 'ERROR');
                                }                                                                   
                            }
                            else {
                                this._log('_formatZeroLineOffset(): get real channel failed', 'ERROR');
                            }                           
                        }
                        else {
                            this._log('_formatZeroLineOffset(): datapoint api not ready', 'ERROR');
                        }                                 
                    }
                }
            }    
            else {
                this._log('_formatZeroLineOffset(): invalid datamanager reference', 'ERROR');
            }                                           
        }         
    }

    /**
     * method is used to format min and maxvalue
     * @param {*} channelSelectionMenu - menu instance for channel selection
     * @param {*} zeroLineOffsetKnob - knob instance for zeroline offset
     */
     async _formatZeroLineOffsetKnob(channelSelectionMenu, zeroLineOffsetKnob) {
        //avoid format
        //check if inputs for zerolineoffset exist
        if ((channelSelectionMenu !== undefined) && (zeroLineOffsetKnob !== undefined)) {
            //get actual selected channel
            if (this.DA_DataManager !== undefined) {
                //get visu channels
                const visuChls = this.DA_DataManager.getVisuChannels(this.graphinstanceid);
                if (visuChls !== undefined) {
                    const channel = visuChls.get(channelSelectionMenu.value);
                    //it is possible that channel is not found cause the login is done later
                    if (channel !== undefined) {
                        if (zeroLineOffsetKnob.useUnconverted) {
                            zeroLineOffsetKnob.valueuc = channel.zeroLineOffset.value;
                        }
                        else {
                            zeroLineOffsetKnob.value = channel.zeroLineOffset.value;
                        }
                        let minValue, maxValue; 
                        //get infos of graph view instance
                        const graphViewInfos = this.DA_DataManager.getGraphViewInfos(this.graphinstanceid);
                        if (graphViewInfos !== undefined) {
                            let scaleRange = 0;
                            //check for mode to get scale values
                            if (graphViewInfos.mode === 'trend') {       
                                //set scale range as min and max for knob
                                if ((channel.scaleType.value < 0) || (channel.scaleType.value === channelSelectionMenu.value)) {
                                    scaleRange = channel.maxScale.value - channel.minScale.value;
                                }                            
                            }
                            else {
                                //osci mode so take value per division for scaling
                                scaleRange = channel.valuePerDivision.value * graphViewInfos.yDivisions;
                            }
                            maxValue = Math.abs(scaleRange);
                            minValue = -maxValue;                            
                        } 
                        else {
                            //don't know how to format
                            maxValue = 0;
                            minValue = 0;
                        }
                        //check if unconverted value should be used
                        if (zeroLineOffsetKnob.useUnconverted) {
                            zeroLineOffsetKnob.minimalvalueuc = minValue;
                            zeroLineOffsetKnob.maximalvalueuc = maxValue;
                        }
                        else {
                            zeroLineOffsetKnob.minimalvalue = minValue;
                            zeroLineOffsetKnob.maximalvalue = maxValue;
                        }                                                              
                    }
                }
            }    
            else {
                this._log('_formatZeroLineOffsetKnob(): invalid datamanager reference', 'ERROR');
            }                                           
        }         
    }

    /**
     * method is used to overload cc by information of actual selection
     * @param {*} vm - view model which should be overloaded
     * @param {*} channelSelectionMenu - menu instance for channel selection
     */
    async _overloadCC(vm, channelSelectionMenu) {
        //check if vm of cc is available
        if ((vm !== undefined) && (vm !== null) && (channelSelectionMenu !== undefined)) {
            //get datapoint (in real class object) for overloading cc
            if (this.propApi !== undefined) {
                try {
                    const schemeData = await this.propApi.getSchemeBranchDataWithProperty(this.id, 'overload');
                    if (schemeData !== undefined) {
                        //search scheme branches for compare value of actual selection
                        for (let i=0;i<schemeData.length;i++) {
                            if (schemeData[i].comparePropertyObject.value === channelSelectionMenu.value) {
                                vm.overload(schemeData[i].resultPropertyObject.value);
                                break;
                            }
                        }    
                    }                        
                }
                catch(error) {
                    this._log('_overloadCC(): overload cc failed -> ' + error, 'ERROR');
                }
            }
            else {
                this._log('_overloadCC(): invalid property api', 'ERROR');
            }                
        }
    }

    /**
     * gets called if value per division was changed
     * @param {*} event - event of value changed event
     */
     async _valuePerDivChanged(event) {
        //get actual selected channel
        if (this.DA_DataManager !== undefined) {
            if (this.instances !== undefined) {
                //get instance object
                const instObj = this.instances.get(event.srcElement.daCCParent);
                if (instObj !== undefined) {          
                    //check if channelselection is valid
                    if (instObj.channelSelectionMenu.value !== undefined) {                            
                        //check if element has already been formatted -> if not we ignore changed event cause it is the initial value
                        if (instObj.valuePerDivInput.formatted === true) {            
                            //get visu channels
                            const visuChls = this.DA_DataManager.getVisuChannels(this.graphinstanceid);
                            if (visuChls !== undefined) {
                                const channel = visuChls.get(instObj.channelSelectionMenu.value);
                                //it is possible that channel is not found cause the login is done later
                                if (channel !== undefined) {
                                    let realChl = this.DA_DataManager.getChannelByID(channel.chlReference.stationNumber, channel.chlReference.chlID);
                                    if (realChl !== undefined) {
                                        //get datapoint to get is floating point info
                                        const dp = this.datapointApi.getDatapoint(realChl.srcVarID);
                                        if (dp !== null) {
                                            const isFloatingPoint = dp.isFloatingPoint();
                                            let value = instObj.valuePerDivInput.value;
                                            //check if value needs to be converted back
                                            if (instObj.valuePerDivInput.unitInfo !== undefined) {
                                                value = await this._convertValueBack(value, instObj.valuePerDivInput.unitInfo, isFloatingPoint);
                                            }                            
                                            value = this.DA_DataManager.getUncastedValue(realChl, value, channel.valuePerDivision.ref);
                                            //check for complex property
                                            if (channel.valuePerDivision.ref !== undefined) {
                                                if ((this.datapointApi !== undefined) && (this.constApi !== undefined)) {
                                                    let dp;
                                                    //check if scheme
                                                    if (channel.valuePerDivision.src === this.constApi.PROP_SRC_SCHEME) {
                                                        //get selected property
                                                        const dpProp = channel.valuePerDivision.ref.getSelectedProp();
                                                        if (dpProp !== undefined) {
                                                            dp = dpProp.getDatapoint();
                                                        }
                                                        else {
                                                            this._log("_valuePerDivChanged(): failed to get selected prop", 'ERROR');
                                                        }
                                                    }
                                                    else {
                                                        //ref is datapoint
                                                        dp = channel.valuePerDivision.ref;
                                                    }
                                                    //get uncasted value
                                                    this.datapointApi.writeDataPoint(dp.getId(), value);
                                                }
                                                else {
                                                    this._log("_valuePerDivChanged(): invalid apis", 'ERROR');
                                                }
                                            }
                                            channel.valuePerDivision.value = value;                                                                
                                        }
                                        else {
                                            this._log('_valuePerDivChanged(): get datapoint failed', 'ERROR');
                                        }    
                                    }
                                    else {
                                        this._log('_valuePerDivChanged(): get real channel failed', 'ERROR');
                                    }                                                         
                                }
                            }
                            else {
                                this._log('_valuePerDivChanged(): get visuchannels failed', 'ERROR');
                            }
                        } 
                    }
                    else {
                        //no error log cause this might happens due to bad timing
                    }    
                } 
                else {
                    this._log('_valuePerDivChanged(): get instances failed', 'ERROR');
                }           
            }
            else {
                this._log('_valuePerDivChanged(): invalid instances', 'ERROR');
            }                         
        }    
        else {
            this._log('_valuePerDivChanged(): invalid datamanager reference', 'ERROR');
        }                                             
    }

    /**
     * method is used to format value per division parameter
     * @param {*} channelSelectionMenu - menu instance for channel selection
     * @param {*} valuePerDivInput - input instance for value per division
     */
     async _formatValuePerDiv(channelSelectionMenu, valuePerDivInput) {
        //check if input for value per division exist
        if ((channelSelectionMenu !== undefined) && (valuePerDivInput !== undefined)) {
            //get actual selected channel
            if (this.DA_DataManager !== undefined) {
                //get visu channels
                const visuChls = this.DA_DataManager.getVisuChannels(this.graphinstanceid);
                if (visuChls !== undefined) {
                    const channel = visuChls.get(channelSelectionMenu.value);
                    //it is possible that channel is not found cause the login is done later
                    if (channel !== undefined) {
                        //check if datapoint api ready cause we need to get the source datapoint of the channel for the unit
                        if (this.datapointApi !== undefined) {
                            let realChl = this.DA_DataManager.getChannelByID(channel.chlReference.stationNumber, channel.chlReference.chlID);
                            if (realChl !== undefined) {
                                //get limit values by evaluating datatype
                                const limitValues = this.DA_DataManager.getLimitValues(realChl.dataType);
                                if (limitValues !== undefined) {
                                    const dp = this.datapointApi.getDatapoint(realChl.srcVarID);
                                    if (dp !== null) {
                                        //get the unit property
                                        const unitInfo = dp.getProperties().unit;
                                        //get casted value -> needs to be done afterwords cause it might changes
                                        let value = this.DA_DataManager.getCastedValue(realChl, channel.valuePerDivision);                                        
                                        if (unitInfo !== undefined) {
                                            const isFloatingPoint = dp.isFloatingPoint();                                            
                                            //Set limits - do not indicate overflow to be able to set values
                                            valuePerDivInput.limitLow = await this._formatValue(limitValues.limitLow, unitInfo, isFloatingPoint, false);
                                            valuePerDivInput.limitHigh = await this._formatValue(limitValues.limitHigh, unitInfo, isFloatingPoint, false);                               
                                            valuePerDivInput.unittext = await this._getUnitText(unitInfo);
                                            //set unit info to convert value back to base unit later on
                                            valuePerDivInput.unitInfo = unitInfo;
                                            //reset formatted to avoid bigger units writin value 0
                                            valuePerDivInput.formatted = false;
                                            valuePerDivInput.value = await this._formatValue(value, unitInfo, isFloatingPoint);
                                            //set formatted
                                            valuePerDivInput.formatted = true;                                                                                                                   
                                        }
                                        else {
                                            valuePerDivInput.limitLow = limitValues.limitLow;
                                            valuePerDivInput.limitHigh = limitValues.limitHigh;                                  
                                            valuePerDivInput.unittext = '';
                                            //set unit info to convert value back to base unit later on
                                            valuePerDivInput.unitInfo = unitInfo;
                                            valuePerDivInput.value = value; 
                                            //set formatted
                                            valuePerDivInput.formatted = true;                                                                  
                                        }                                        
                                    }
                                    else {
                                        this._log('_formatValuePerDiv(): datapoint not found', 'ERROR');
                                    }                                                                                                              
                                }
                                else {
                                    this._log('_formatValuePerDiv(): get limit values failed', 'ERROR');
                                }                                  
                            }
                            else {
                                this._log('_formatValuePerDiv(): get real channel failed', 'ERROR');
                            }                     
                        }
                        else {
                            this._log('_formatValuePerDiv(): invalid datapoint api', 'ERROR');
                        }                                
                    }
                }
            }    
            else {
                this._log('_formatValuePerDiv(): invalid datamanager reference', 'ERROR');
            }  
        }
    }

    /**
     * gets called if props of vm get activated
     */
    sigOnActiveStateChange(active) {
        super.sigOnActiveStateChange(active);
        //check if initialized already
        if ((this.initialized) && (active)) {
            //initialize new
            this._init();
        }
    }

    /**
     * gets called from RT if cc scheme changes
     */
    refresh(control, force, skipPropsCheck) {
        //check if cc is our settings control
        if (control !== undefined) {
            //check if initialized already
            if (this.initialized) {
                SigPolymer.afterNextRender(control, () => {
                    //get instances of new cc
                    this._init();                      
                });
            }
        }
    }

    /**
     * method is used to format a value by information of unit
     * @param {*} value - value which should be converted
     * @param {*} unitInfo - unit property of the datapoint
     * @param {*} isFloatingPoint - info if value is evaluated as floating point
     * @param {*} indicateOverflow - if true overflow is indicated as >>>> or <<<<
     */
     async _formatValue(value, unitInfo, isFloatingPoint, indicateOverflow=true) {
        //check for valid value -> as unitinfo is also valid if undefined in case of no unit configured, we don't question that
        if (value !== undefined) {
            //check if value needs to be formatted
            if (unitInfo !== undefined) {
                //check if apis ready for formating values
                if ((this.propApi !== undefined) && (this.constApi !== undefined)) {
                    if (unitInfo.src === this.constApi.PROP_SRC_UNIT) {
                        return await this.propApi.formatValueWithUnit(unitInfo.value, value, isFloatingPoint, indicateOverflow, 0);
                    }
                    else if (unitInfo.src === this.constApi.PROP_SRC_SCHEME) {
                        const schemeVals = unitInfo.value.split(':');
                        return await this.propApi.formatValueWithUnitscheme(schemeVals[1], schemeVals[0], value, 0, isFloatingPoint, indicateOverflow, 0, false);
                    }
                    else if (unitInfo.src === this.constApi.PROP_SRC_SWITCH_PROP) {
                        //scheme and unit configured
                        if ((unitInfo.children !== undefined) && (unitInfo.children.length > 0)) {
                            let unit = 0;
                            let unitScheme = 0;
                            for (let i=0;i<unitInfo.children.length;i++) {
                                //check for unit
                                if (unitInfo.children[i].src === this.constApi.PROP_SRC_UNIT) {
                                    unit = unitInfo.children[i].value;
                                }
                                else if (unitInfo.children[i].src === this.constApi.PROP_SRC_SCHEME) {
                                    unitScheme = unitInfo.children[i].value;
                                }
                            }
                            const schemeVals = unitScheme.split(':');
                            return await this.propApi.formatValueWithUnitscheme(schemeVals[1], schemeVals[0], value, unit, isFloatingPoint, indicateOverflow, 0, false);                            
                        }
                        else {
                            this._log('_formatValue(): invalid constellation', 'ERROR');
                        }
                    }
                }
                else {
                    this._log('_formatValue(): api not ready', 'ERROR');
                }                
            }
            else {
                //value doesn't need to be formatted
                return value;
            }
        }
        else {
            this._log('_formatValue(): invalid value', 'ERROR');
        }
    }

    /**
     * method is used to convert a value back by information of unit
     * @param {*} value - value which should be converted
     * @param {*} unitInfo - unit property of the datapoint
     * @param {*} isFloatingPoint - info if value is evaluated as floating point
     */
     async _convertValueBack(value, unitInfo, isFloatingPoint) {
        //check for valid value -> as unitinfo is also valid if undefined in case of no unit configured, we don't question that
        if (value !== undefined) {
            //check if value needs to be formatted
            if (unitInfo !== undefined) {
                //check if apis ready for formating values
                if ((this.propApi !== undefined) && (this.constApi !== undefined)) {
                    if (unitInfo.src === this.constApi.PROP_SRC_UNIT) {
                        return await this.propApi.convertValueBackWithUnit(unitInfo.value, value, isFloatingPoint);
                    }
                    else if (unitInfo.src === this.constApi.PROP_SRC_SCHEME) {
                        const schemeVals = unitInfo.value.split(':');
                        return await this.propApi.convertValueBackWithUnitscheme(schemeVals[1], schemeVals[0], value, 0, isFloatingPoint, false);
                    }
                    else if (unitInfo.src === this.constApi.PROP_SRC_SWITCH_PROP) {
                        //scheme and unit configured
                        if ((unitInfo.children !== undefined) && (unitInfo.children.length > 0)) {
                            let unit = 0;
                            let unitScheme = 0;
                            for (let i=0;i<unitInfo.children.length;i++) {
                                //check for unit
                                if (unitInfo.children[i].src === this.constApi.PROP_SRC_UNIT) {
                                    unit = unitInfo.children[i].value;
                                }
                                else if (unitInfo.children[i].src === this.constApi.PROP_SRC_SCHEME) {
                                    unitScheme = unitInfo.children[i].value;
                                }
                            }
                            const schemeVals = unitScheme.split(':');
                            return await this.propApi.convertValueBackWithUnitscheme(schemeVals[1], schemeVals[0], value, unit, isFloatingPoint, false);                            
                        }
                        else {
                            this._log('_convertValueBack(): invalid constellation', 'ERROR');
                        }
                    }
                }
                else {
                    this._log('_convertValueBack(): api not ready', 'ERROR');
                }                
            }
            else {
                //value doesn't need to be formatted
                return value;
            }
        }
        else {
            this._log('_convertValueBack(): invalid value', 'ERROR');
        }
    }

     /****************************************************************************************************
      * method is used to get the unit text via a unitproperty
      *
      * @param {*} unitInfo - unit property
      * @return {String} - Unittext
      * @memberof LasalRuntimeSigControlDAChannelSettings
      ****************************************************************************************************/
     async _getUnitText(unitInfo) {
        //check for valid input
        if (unitInfo !== undefined) {
            //check if properties ready to get unit
            if ((this.propApi !== undefined) && (this.unitApi !== undefined) && (this.constApi !== undefined)) {
                let unit;
                if (unitInfo.src === this.constApi.PROP_SRC_UNIT) {
                    unit = this.unitApi.getUnit(unitInfo.value);
                }
                else if (unitInfo.src === this.constApi.PROP_SRC_SCHEME) {
                    try {
                        const schemeVals = unitInfo.value.split(':');
                        unit = await this.propApi.doScheme(schemeVals[1], schemeVals[0], false);                                            
                    }
                    catch (error) {
                        this._log('_getUnitText(): failed to get unit -> ' + error, 'ERROR');
                    }
                }
                else if (unitInfo.src === this.constApi.PROP_SRC_SWITCH_PROP) {
                    //scheme and unit configured
                    if ((unitInfo.children !== undefined) && (unitInfo.children.length > 0)) {
                        let unitScheme;
                        for (let i=0;i<unitInfo.children.length;i++) {
                            //check for unit
                            if (unitInfo.children[i].src === this.constApi.PROP_SRC_UNIT) {
                                unit = this.unitApi.getUnit(unitInfo.children[i].value);
                            }
                            else if (unitInfo.children[i].src === this.constApi.PROP_SRC_SCHEME) {
                                unitScheme = unitInfo.children[i].value;
                            }
                        }
                        if (unitScheme !== undefined) {
                            try {
                                const schemeVals = unitScheme.split(':');
                                const schemeUnit = await this.propApi.doScheme(schemeVals[1], schemeVals[0], false);  
                                //handle fallback unit
                                if (schemeUnit) unit = schemeUnit;                                                   
                            }
                            catch (error) {
                                this._log('_getUnitText(): failed to get unit -> ' + error, 'ERROR');
                            }                                               
                        }                           
                    }
                    else {
                        this._log('_getUnitText(): invalid constellation', 'ERROR');
                    }
                }
                //check if unit was found
                if (unit !== undefined) {
                    //return unit text
                    return unit.getUnitText();
                }
                else {
                    this._log('_getUnitText(): unit not found', 'ERROR');
                }
            }
            else {
                this._log('_getUnitText(): apis not ready', 'ERROR');
            }    
        }
        else {
            this._log('_getUnitText(): invalid input', 'ERROR');
        }
    }

    /***************************************************************************************************************************
     * gets called if control gets disconnected from dom
     ***************************************************************************************************************************/    
    disconnectedCallback() {
        super.disconnectedCallback();
        //remove menus from manager
        if (this.menuApi !== undefined) {
            //remove channel selection menu
            if (this.visuChlsMenu !== undefined) {
                this.menuApi.removeMenu(this.visuChlsMenu.getIndex());
            }
            //remove scale type menu from manager
            if (this.scaleTypeMenu !== undefined) {
                this.menuApi.removeMenu(this.scaleTypeMenu.getIndex());
            }
            //remove real channel menu from manager
            if (this.realChlMenu !== undefined) {
                this.menuApi.removeMenu(this.realChlMenu.getIndex());
            }
            //remove server configuration menu from manager
            if (this.serverMenuList !== undefined) {
                this.menuApi.removeMenu(this.serverMenuList.getIndex());
            }
        }
    }

}
customElements.define(LasalRuntimeSigControlDAChannelSettings.is, LasalRuntimeSigControlDAChannelSettings);