import { LasalRuntimeSigElement, SigPolymer } from '../../sigmatek/sig-element/sig-element.js';
import '../sig-control-button/sig-control-button.js';
import '../sig-control-checkbox/sig-control-checkbox.js';
import '../sig-control-slider/sig-control-slider.js';

//#region HelperClasses

class channelDesignTime {
    constructor(channelSettings, scaleSettings) {
        this.channelSettings = channelSettings;
        this.scaleSettings = scaleSettings;
    }
}

class channelSettingsDesignTime {
    constructor(lasalId, unit, channelKey, channelName, channelActive, minValue, maxValue, autosetMin, autosetMax, scalingMode, 
        channelRef, lineColor, lineSize, lineStyle, sampRate, zeroLine) {
        this.lasalId = lasalId;
        this.unit = unit;
        this.channelKey = channelKey; //channel identificator
        this.channelName = channelName; //channel name 
        this.channelActive = channelActive; //channel active
        this.minValue = minValue; //min value (when manual/reference mode is used)
        this.maxValue = maxValue; //max value (when manual/reference mode is used)
        this.autosetMin = autosetMin; //min value (when autoset mode is used)
        this.autosetMax = autosetMax; //max value (when autoset mode is used)
        this.scalingMode = scalingMode; //scaling mode - Manual, Autoset, Reference
        this.channelRef = channelRef; //channel reference identificator (from which channel limit values should be taken)
        this.lineColor = lineColor; 										   
        this.lineSize = lineSize; //1 - 5
        this.lineStyle = lineStyle; //Solid, Dash, Dot
        this.sampRate = sampRate; //time difference between values inside buffer
        this.zeroLine = zeroLine; //if zero line is active and how to draw it - None, Triangle, Line, Both
    }
}

class scaleSettingsDesignTime {
    constructor(yAxisActive, turnYAxis, axisPosition, yAxisUnitPosition) {
        this.yAxisActive = yAxisActive;
        this.turnYAxis = turnYAxis;
        this.axisPosition = axisPosition; //Axis position for the current channel
        this.yAxisUnitPosition = yAxisUnitPosition;//Y-Axis Position - Top, Bottom, Hide
    }
}


class Times{
    constructor() {
        this.starttime;
        this.endtime;
        this.forcycletime;
        this.drawing;
        this.testingareatime;
        this.difference;
        this.oldforcycletime;
    }
}

//#endregion



/**
 * `my-osci`
 * osci for synthesa
 *
 * @customElement
 * @polymer
 * @demo demo/index.html
 */
class LasalRuntimeSigDaGraphs extends LasalRuntimeSigElement {
    static get is() {
        return 'sig-control-da-graphs';
    }

    static get importMeta() {
        return import.meta;
    }
  
    /****************************************************************************************************
     * Return the component style and template as a template literal
     *
     * @readonly
     * @static
     ****************************************************************************************************/
    static get template() {
        return SigPolymer.html`
        <style include="sig-element-css">
            :host {
                color: var(--theme-sig-control-da-graphs-color, inherit);
                background-color: var(--theme-sig-control-da-graphs-background-color, transparent);
                border-color: var(--theme-sig-control-da-graphs-border-color);
                border-width: var(--theme-sig-control-da-graphs-border-width, 0px);
                border-radius: var(--theme-sig-control-da-graphs-border-radius, 0px);
                border-style: var(--theme-sig-control-da-graphs-border-style, solid);
                display: block;
                position: absolute;
                overflow: hidden
            }

            :host * {
                margin: 0;
                padding: 0
            }

            :host([isdesignmode]:hover) {
                background-color: var(--theme-sig-control-da-graphs-background-color, rgba(255, 255, 255, .3));
            }

            .sig-control-da-graphs {
                width: 100%;
                height: 100%;
                position: relative
            }

            html,
            body {
                padding: 0;
                margin: 0;
                width: 100%;
                height: 100%;
            }

            #container {
                width: 100%;
                height: 100%;
                position: absolute;
                margin: 0 auto;
            }

            #unitsArea {
                width: 100%;
                height: 0%;
                margin: 0;
                padding: 0;
            }

            #stage {
                width: 100%;
                height: 80%;
            }

            #yAxisArea1 {
                float: left;
                margin: 0;
                padding: 0;
                width: 5%;
                height: 100%;
            }

            #drawingArea {
                float: left;
                margin: 0;
                padding: 0;
                width: 95%;
                height: 100%;
            }

            #yAxisArea2 {
                float: left;
                margin: 0;
                padding: 0;
                width: 0%;
                height: 100%;
            }

            #xAxisArea {
                width: 100%;
                height: 10%;
            }

            #sliderArea {
                width: 90%;
                height: auto;
                overflow: hidden;
                margin: auto;
                transform: translateZ(1px);
            }

            #sliderAreaLeft {
                width: 70%;
                height: auto;
                float: left;
            }

            #sliderAreaRight {
                width: 30%;
                height: auto;
                float: left;
            }

            menu {
                position: absolute;
            }

            checkbox {
                position: absolute;
            }
            
            #cursorCanvas {
                /*z-index: 4;*/
                position: absolute;
                background-color: transparent;
            }

            #osciCanvas {
                /*z-index: 3;*/
                position: absolute;
                background-color: transparent;
            }

            #gridCanvas {
                color: var(--theme-sig-control-da-graphs-grid-color, transparent);
                /*z-index: 2;*/
                position: absolute;
                background-color: transparent;
            }

            #canvas_yAxisArea1 {
                color: var(--theme-sig-control-da-graphs-axis-color, transparent);
                background-color: transparent;
            }

            #canvas_yAxisArea2 {
                color: var(--theme-sig-control-da-graphs-axis-color, transparent);
                background-color: transparent;
            }

            #canvas_xAxisArea {
                color: var(--theme-sig-control-da-graphs-axis-color, transparent);
                background-color: transparent;
            }

            #canvas_unitsArea {
                position: absolute;
            }

            :host sig-control-slider {
                color: inherit;
                background-color: transparent;
                background-image: none;
                background-repeat: repeat;
                border-width: 0px;
                border-color: transparent;
                border-style: none;
                border-radius: 0px;
                
                width: 100px;
                height: 30px;

                padding: 5px;

                top: 0;
                left: 0;

                position: relative;

                margin: 5 0;
                
                --theme-sig-control-slider-hotspotarea-padding: 80px;
                --theme-sig-control-slider-scale-line-color: rgba(64, 66, 72, 1);
                --theme-sig-control-slider-bar-background-color: rgba(174, 200, 26, 1);
                --theme-sig-control-slider-bar-border-radius: 0px;
                --theme-sig-control-slider-track-background-color: rgba(64, 66, 72, 1);
                --theme-sig-control-slider-track-border-radius: 0px;
                --theme-sig-control-slider-track-height: 8px;
                --theme-sig-control-slider-handle-background-color: rgba(177, 177, 177, 1);
                --theme-sig-control-slider-handle-moving-background-color: rgba(174, 200, 26, 1);
                --theme-sig-control-slider-handle-border-radius: 2px;
                --theme-sig-control-slider-handle-border-color: rgba(64, 66, 72, 1);
                --theme-sig-control-slider-handle-border-width: 1px;
                --theme-sig-control-slider-handle-border-style: outset;
                --theme-sig-control-slider-outofrange-background-color: rgba(255, 255, 255, 0);
            }
        </style>

        <div id="container">
            <div id="unitsArea">
                <canvas id="canvas_unitsArea"></canvas>
            </div>
            <div id="stage">
                <div id="yAxisArea1">
                    <canvas id="canvas_yAxisArea1"></canvas>
                </div>
                <div id="drawingArea" on-pinchzoom="_zoomView">
                    <canvas id="gridCanvas"></canvas>
                    <canvas id="osciCanvas"></canvas>
                    <canvas id="cursorCanvas"></canvas>               
                </div>
                <div id="yAxisArea2">
                    <canvas id="canvas_yAxisArea2"></canvas>
                </div>
            </div>
            <div id="xAxisArea">
                <canvas id="canvas_xAxisArea"></canvas>
            </div>
            <div id="sliderArea">
                <!-- <div id="sliderAreaLeft"> -->
                    <sig-control-slider id="sliderTest" />
                    <!-- <input type="range" id="sliderTest" min="0" max="100" step="0.001"> -->
                <!-- </div> -->
                <!-- <div id="sliderAreaRight">
                    <sig-control-slider id="zoomSlider" />
                </div> -->
            </div>
        </div>`;
    }        

    static get properties() {
        return {
            gridlinesx: {
                type: Number,
                value: 6,
                observer: '_gridXChanged'
            },
            gridlinesy: {
                type: Number,
                value: 8,
                observer: '_gridYChanged'
            },
            gridstyle: {
                type: String,
                value: 'line',
                observer: '_gridStyleChanged'
            },
            roundingconst: {
                type: Number,
                value: 100,
                reflectToAttribute: false
            },
            unitvalueconst: {
                type: Number,
                value: 5,
                reflectToAttribute: false
            },
            textlistname: {
                type: String,
                value: "DataAnalyzer"
            },
            textlistprefix: {
                type: String,
                value: "Graphs_"
            },
            alertChannelNotChosenTop: 
            {
                type: String,
                value: ''
            },
            alertChannelNotChosenText: 
            {
                type: String,
                value: ''
            },
            cursorColors: {
                type: String,
                value: '#ffffff'
            },
            triggerPointColors: {
                type: String,
                value: '#ffffff'
            },
            timeAlertWindowCaption:{
               type: String,
               value: 'Time not available!'               
            },              
            timeAlertWindowText: {
                type: String,
                value :'User has to change the PLC'
            },
            recalcYAxis: {
                type: Boolean,
                 value: false
            },
            alertNoSpaceCaption: {
                type: String,
                value: "Not possible to display this Y-Axis"
            },
            alertNoSpaceText: {
                type: String, 
                value: "There is too many Y-Axis active! These Y-Axis can't be activated"
            },
            stationId: {
                type: Number,
                value: 0x00
            }
        };
    }

    constructor() {
        super()

        if (!super._isDesignMode()) {
            // Create shortcuts to the common apis. This makes the code more readable
            if (window.sigApi) {
                this.utilsApi = window.sigApi.sigUtils;
                this.evtMedApi = window.sigApi.eventMediator;
                this.evtApi = window.sigApi.events;
                this.tmApi = window.sigApi.textManager;
                this.smApi = window.sigApi.stationManager;
                this.dmApi = window.sigApi.datapointManager;
                this.wndApi = window.sigApi.windowManager;
            } else {
                this._log('API not ready!', 'ERROR');
            }
            this.firsttimedrawing = true;	
            this.drawingCanceled = false;				
            this.isCanvasCleared = false; 		 

            this.timesHolder = new Times();

            //these two times are used for preventing system from updating it too often
            this.actualTime = performance.now();
            this.timeOfLastUpdate = performance.now();
        }

        //#region Handlers
        this.sliderChangeHandler = () => { this.onSliderChange() };
        //this.zoomSliderChangeHandler = () => { this.onZoomSliderChange() };
        //#endregion

        //#region Fields
        this.mainOffset = 40;
        this.correctValue = true;

        //variables for the scale of the y-axis  
        this.actualMaxLeft = 0;
        this.actualMaxRight = 0;
        this.MaxLeft = 0;
        this.MaxRight = 0;
        //variables for the x-axis    
        this.XAxisTexts = [];
        this.XAxisTextWidth = 0;
        //variables for half-empty buffer
        this.oldSliderValue = -1;
        this.oldSliderRange = -1;
        this.yLengthOld = -1;
        this.finalSliderValue = -1;
        this.timer = null; //timer for checking if acknowledge is coming
        this.oneShotTimer = null; //timer for checking
        this.waitTime = 0;
        this.registerAck = 0;

        this.done = false;
        this.init = true;

        let frameRequest = null;

        //this.cursorVals = new Map();

        //zoom by Jakob
        //necessary variables
        //factor to save the factor which is calculated according to the 
        //distance from the fingers
        this.pinchZoomScaleFactor = 1;
        //flag to check if the graph is already paused
        this.zoomStopped = false;
        //variable to save the old scaling value
        this.xAxisScalingValueBefore = 0;
        //#endregion
    }
    
    ready() {
        super.ready();
        if (!super._isDesignMode() && !this.smApi.isInOfflinePreview()) {
            //this.startTimerSendEvent(); //timer for handling if PLC is registered or not

            //--- datapoint data ---
            this.servers = [];
            this.receivedServers = undefined;

            // --- local storage ---
            this.loadChannels = true;
            //this.localStorageGenHelper = this._parseGeneralSettings(); //parse general settings from local storage
            //this.localStorageChannels = this._parseChannels(); //get local storage channels
            // ---------------------

            
            if (!this.isdesignmode && !this.smApi.isInOfflinePreview()){
                window.sigApi.vm.addRenderCallback(this, () => {
                    dispatchEvent(new CustomEvent("evCursorCanvasSize", {
                        'detail': {
                            width: this.$.cursorCanvas.clientWidth,
                            height: this.$.cursorCanvas.clientHeight
                        }
                    }));
        
                    dispatchEvent(new CustomEvent("gridLinesX", {
                        'detail': {
                            gridlinesx: this.gridlinesx
                        }
                    }));
                });
            } 

            // --- slider limits set (can't be set in html code) ---
            window.sigApi.vm.addRenderCallback(this.$.sliderTest, () => {
                if (!this.isdesignmode && !this.smApi.isInOfflinePreview()) {
                    this.$.sliderTest.limitLow = 0;
                    this.$.sliderTest.limitHigh = 100; 

                    if (DataRepository.getGeneralSettings().rightToLeft == DataRepository.getRTLEnum().righttoleft) {                  
                        this.$.sliderTest.value = 100;
                    } else {                  
                        this.$.sliderTest.value = 0;
                    }
                }
            });            

            /* window.sigApi.vm.addRenderCallback(this.$.zoomSlider, () => {
                this.$.zoomSlider.limitLow = 0;
                this.$.zoomSlider.limitHigh = 100;
                //prevent ZoomStop Event to be called
                this.zoomStopped = true;
                this.$.zoomSlider.value = 0;
                this.zoomStopped = false;
            });         */
            // -----------------------------------------------------
        }

       SigPolymer.afterNextRender(this, function(params) {
            this.redrawGrid(true); //redraw grid
        }); 


        this.$.sliderTest.style.width = "100%";
        //this.$.zoomSlider.style.width = "100%";

        if (!this.isdesignmode && !this.smApi.isInOfflinePreview()) {
            window.sigApi.vm.addRenderCallback(this, () => {
                this._rendered();
            });
        
            window.sigApi.eventMediator.subscribe(
                window.sigApi.events.getInternalEvent('LANGUAGE_CHG'), () => { this._switchLang(); });
            this._switchLang();
        }
    }

    _rendered() {
        //this.redrawGrid(true); //redraw grid

        if (DataRepository.isDataLoaded()) {
            // console.log("graphs - data loaded");
            // console.log("graphs - getstatepauseresume", DataRepository.getStatePauseResume());
            if (!DataRepository.getStatePauseResume()) {
                this.$.sliderTest.value = parseFloat(DataRepository.getSliderValue());

                this._bufferListener(); //start loop with processing the data and canvas drawing

                this.init = false;
            } else {
                this._bufferListener(); //start loop with processing the data and canvas drawing

                this.init = false;
            }
        } else {
            this._bufferListener(); //start loop with processing the data and canvas drawing

            this.init = false;
        }
    }

    _switchLang() {
        //object to get the text; if textname does not exist - default value is used
        let requestObj = {[this.textlistname] : { 
            [this.textlistprefix + "alertChannelNotChosenTop"] : "Channel not chosen",
            [this.textlistprefix + "alertChannelNotChosenText"] : "Channel for snapping was not chosen!",
            [this.textlistprefix + "timeAlertWindow_caption"] : "Time not available!",
            [this.textlistprefix + "timeAlertWindow_text"] : "User has to change the PLC",
            [this.textlistprefix + "alertNoSpaceCaption"] : "Not possible to display this Y-Axis",
            [this.textlistprefix + "alertNoSpaceText"] : "There is too many Y-Axis active! These Y-Axis can´t be activated"
        }};

        //get the language code
        let lang_num = this.tmApi.getCurrentLanguage().getIndex();

        //get all the texts
        this.tmApi.getTexts(requestObj, lang_num);

        this.alertChannelNotChosenTop = requestObj[this.textlistname][this.textlistprefix + "alertChannelNotChosenTop"];
        this.alertChannelNotChosenText = requestObj[this.textlistname][this.textlistprefix + "alertChannelNotChosenText"];
        this.timeAlertWindowCaption = requestObj[this.textlistname][this.textlistprefix + "timeAlertWindow_caption"];
        this.timeAlertWindowText = requestObj[this.textlistname][this.textlistprefix + "timeAlertWindow_text"];
        this.alertNoSpaceCaption = requestObj[this.textlistname][this.textlistprefix + "alertNoSpaceCaption"];
        this.alertNoSpaceText = requestObj[this.textlistname][this.textlistprefix + "alertNoSpaceText"];
    }

    _gridXChanged() {
        if (this.isdesignmode) {
            this.redrawGrid(true);
        }
    }

    _gridYChanged() {
        if (this.isdesignmode) {
            this.redrawGrid(true);
        }
    }

    _gridStyleChanged() {
        if (this.isdesignmode) {
            this.redrawGrid(true);
        }
    }

    onSliderChange() {
        if (this.init && DataRepository.isDataLoaded() && !DataRepository.getStatePauseResume()) return;

		DataRepository.setxAxisPropertieChanged(true);											  
        DataRepository.setSliderValue(parseFloat(this.$.sliderTest.value)); 
    }

    //double tap on graphs resets the zoom factor
    onGraphDoubleClick() {      
        DataRepository.setZoomFactorValue(0);
    }

    //zoom by Jakob
    //function to handle the zoom
    _zoomView(e) {
        //calculate the maximum value which can be zoomed in according to the minimum sample rate
        //distance between two points when zooming can't be smaller than the minimum sample rate
        let maxZoomFactor = (DataRepository.getGeneralSettings().xScale * this.gridlinesx / JSManager.getMinSampleRate());
        //get the factor according to the distance between the fingers
        if (e.detail.distfactor == 1) {
            if ((this.pinchZoomScaleFactor + (e.detail.dist / 1000 * maxZoomFactor/10)) > maxZoomFactor) {
                this.pinchZoomScaleFactor = maxZoomFactor;
            } else {
                this.pinchZoomScaleFactor = this.pinchZoomScaleFactor + (e.detail.dist / 1000 * maxZoomFactor/10);
            }
        } else if (e.detail.distfactor == -1) {
            if ((this.pinchZoomScaleFactor - (e.detail.dist / 1000 * maxZoomFactor/10)) < 0) {
                this.pinchZoomScaleFactor = 0;
            } else {
                this.pinchZoomScaleFactor = this.pinchZoomScaleFactor - (e.detail.dist / 1000 * maxZoomFactor/10);
            }
        }

        //convert the factor to a zoom factor which is always a multiple of 2
        let nextZoomFactor = (2 * Math.round(this.pinchZoomScaleFactor / 2));
        //get the actual scaling value
        let xAxisScalingValue = DataRepository.getGeneralSettings().xScale * this.gridlinesx;

        //check if the zoom is still possible (not too far)
        if(nextZoomFactor * JSManager.getMinSampleRate() >= xAxisScalingValue) {
            DataRepository.setZoomFactorValue(nextZoomFactor - 2);
        } else {
            DataRepository.setZoomFactorValue(nextZoomFactor);
        }

        //if the graph is not paused yet, pause it
        if (!this.zoomStopped) {
            dispatchEvent(new CustomEvent("ZoomStop"));
            this.zoomStopped = true;
        }
    }

    onHideChannelSettings() {
        dispatchEvent(new CustomEvent("channelSettings_Changed", {
            'detail': {
                custom_info: this.$.cbChannel.checked
            }
        }));
    }

    onHideScaleSettings() {
        dispatchEvent(new CustomEvent("scaleSettings_Changed", {
            'detail': {
                custom_info: this.$.cbScale.checked
            }
        }));
    }

    connectedCallback() {
        super.connectedCallback();
        if (!this.isdesignmode && !this.smApi.isInOfflinePreview()) {
            // --- new event reg --- //    
            this.sigAddEventListener('rightToLeftChanged_Graphs', (e) => this._rightToLeftClicked(e), 'jsEvent', window);
            this.sigAddEventListener('JSMgr_Buffer_Changed', () => this._bufferListener(), 'jsEvent', window);
            this.sigAddEventListener('startButton_Clicked', () => this._startButtonListener(), 'jsEvent', window);
            this.sigAddEventListener('stopButton_Clicked', () => this._stopButtonListener(), 'jsEvent', window);
            this.sigAddEventListener('ShowRegisterAlert', () => this._showRegisterAlert(), 'jsEvent', window);
            this.sigAddEventListener('EV_TO_SPS_CLEARDATA_HELPER', () => this.clearCanvas(), 'jsEvent', window);
            this.sigAddEventListener('startStop_Changed', (e) => this._drawingHandler(e), 'jsEvent', window);
            this.sigAddEventListener('channelActive_Changed', (e) => this._channelactivechanged(e), 'jsEvent', window);
            this.sigAddEventListener('yAxisActive_Changed', (e) => this._scaleSettingsYAxisChanged(e), 'jsEvent', window);
            this.sigAddEventListener('evResetSliderValue', () => this._resetSliderValue(), 'jsEvent', window);
            this.sigAddEventListener('unload', (e) => this.unloadFcn(e), 'jsEvent', window);
            this.sigAddEventListener('dblclick', () => this.onGraphDoubleClick(), 'jsEvent', this.$.drawingArea);

            this.$.sliderTest.addEventListener('value-changed', this.sliderChangeHandler);
        }
    }

    disconnectedCallback() {
        super.disconnectedCallback();
        if (!this.isdesignmode && !this.smApi.isInOfflinePreview()) {
            this.$.sliderTest.removeEventListener('value-changed', this.sliderChangeHandler);

            if (this.frameRequest != null) {
                window.cancelAnimationFrame(this.frameRequest);
            }
        }
    }

    _resetSliderValue() {
        if (DataRepository.getGeneralSettings().rightToLeft == DataRepository.getRTLEnum().righttoleft) {
            this.$.sliderTest.value = this.$.sliderTest.limitHigh;
        } else {
            this.$.sliderTest.value = this.$.sliderTest.limitLow;
        }
    }

    serversInit() {
        this.servers = JSManager.getServers(); 
    }

    serversReceived() {
        this.receivedServers = JSManager.getReceivedServers();
    }

    _drawingHandler(e) {
        if (!e.detail.state) {
            dispatchEvent(new CustomEvent("evtCursorCanvasSize", {
                'detail': {
                    width: this.$.cursorCanvas.clientWidth,
                    height: this.$.cursorCanvas.clientHeight
                }
            }));
        }
        this.zoomStopped = false;
    }

    _channelactivechanged(e) {
        this.recalcYAxis = true;
    }

    _scaleSettingsYAxisChanged(e) {
        this.recalcYAxis = true;
    }

    //#region Cursors
    //event for getting snapX channel from cursor settings
    snapChannel_Changed(e) {
        this.cursorSettings.snapChannel = e.detail.channel;
    }

    drawingHandler(e) {
        if (e.detail.state) {
            /*this.cursorSettings.drawingHandler = false;
            dispatchEvent(new CustomEvent("disableEvent", {
                'detail': {
                    disabled: true
                }
            }));*/
        } else {
            /*this.cursorSettings.drawingHandler = true;
            dispatchEvent(new CustomEvent("axisDataEvent", {
                'detail': {
                    xGridCount: this.gridlinesx
                }
            }));
            //if snapping is chosen
            if (this.cursorSettings.snapXAxis) { 
                let cCanvasWidth = this.$.cursorCanvas.clientWidth;
                let cCanvasHeight = this.$.cursorCanvas.clientHeight;
                this.cursorSnap(DataRepository.getXSnapEnum().noChange, cCanvasWidth, cCanvasHeight);
                //this.redrawCursorCanvas();
            }
            dispatchEvent(new CustomEvent("disableEvent", {
                'detail': {
                    disabled: false
                }
            }));*/
        }
    }

    cursorWerteChanged(e) {
        this.cursorSettings.werte = e.detail.werte;
        //this.redrawCursorCanvas(); // ?
    }

    cursorDifferenceChanged(e) {
        this.cursorSettings.difference = e.detail.diff;
        //this.redrawCursorCanvas(); // ?
    }

    cursorSnapXAxisChanged(e) {
        this.cursorSettings.snapXAxis = e.detail.snapX;
    }

    cursorStepXChanged(e) {
        this.cursorSettings.stepX = e.detail.stepX;
    }

    cursorStepYChanged(e) {
        this.cursorSettings.stepY = e.detail.stepY;
    }

    cursorChgXYChanged(e) {
        if (e.detail.cursor.match('X1/Y1')) {
            this.cursorSettings.cursorActiveXY = 1;
        } else {
            this.cursorSettings.cursorActiveXY = 2;
        }
    }

    /*cursorSnap(lr, cCanvasWidth, cCanvasHeight) {
        if (this.cursorSettings.snapChannel != -1) {
            let selChan = this.cursorSettings.snapChannel;
            let sampRate = DataRepository.getChannelArray().get(parseInt(selChan)).channelSettings.sampRate;
            let xMax, xMin, xMaxMin, xPointer;
            let xValues, yValues, yPointer, xCapacity, yCapacity, yLength;
            let bufferValuesHist = JSManager.getRingBufferMapHist();
            let bufferXConstVal = JSManager.getBufferXConst();
            xValues = bufferValuesHist.get(bufferXConstVal + sampRate).buffer;
            xPointer = bufferValuesHist.get(bufferXConstVal + sampRate).pointer;
            xCapacity = bufferValuesHist.get(bufferXConstVal + sampRate).capacity;
            yValues = bufferValuesHist.get(selChan).buffer;
            yPointer = bufferValuesHist.get(selChan).pointer;
            yCapacity = bufferValuesHist.get(selChan).capacity;
            yLength = bufferValuesHist.get(selChan).length;
            xPointer == 0 ? xMax = xValues[xValues.length - 1] : xMax = xValues[xPointer - 1];
            let xStep = ((DataRepository.getGeneralSettings().xScale) / 10);
            xMin = (xMax - (xStep * 10));
            xMaxMin = xMax - xMin;
            let k_x = (cCanvasWidth / xMaxMin);
            let d_x = -(xMin * k_x);
            let localMin = 0;
            let localMax = 0;

            if (DataRepository.getChannelArray().get(selChan).channelSettings.scalingMode == "Autoset") {
                localMin = DataRepository.getChannelArray().get(selChan).channelSettings.autosetMin;
                localMax = DataRepository.getChannelArray().get(selChan).channelSettings.autosetMax;
            } else if (DataRepository.getChannelArray().get(selChan).channelSettings.scalingMode == "Manual") {
                localMin = DataRepository.getChannelArray().get(selChan).channelSettings.minValue;
                localMax = DataRepository.getChannelArray().get(selChan).channelSettings.maxValue;
            } else { //reference

            }

            let maxmin = localMax - localMin;
            let k_c = (cCanvasHeight / maxmin);
            let d_c = -(localMin * k_c);
            let xBufferSelected = [];
            let yBufferSelected = [];

            if ((DataRepository.getSliderValue() == 100 && 
                DataRepository.getGeneralSettings().rightToLeft == DataRepository.getRTLEnum().righttoleft) || 
                (DataRepository.getSliderValue() == 0 && DataRepository.getGeneralSettings().rightToLeft == DataRepository.getRTLEnum().lefttoright)) {
                if (yPointer == 0 || yLength != yCapacity) {
                    for (let b = 0; b < xValues.length; b++) {
                        if (xValues[b] >= xMin) {
                            xBufferSelected.push(xValues[b]);
                            yBufferSelected.push(yValues[b]);
                        }
                    }
                } else {
                    for (let pn = yPointer; pn < yValues.length; pn++) {
                        if (xValues[pn] >= xMin) {
                            xBufferSelected.push(xValues[pn]);
                            yBufferSelected.push(yValues[pn]);
                        }
                    }
                    for (let pr = 0; pr < yPointer; pr++) {
                        if (xValues[pr] >= xMin) {
                            xBufferSelected.push(xValues[pr]);
                            yBufferSelected.push(yValues[pr]);
                        }
                    }
                }
            }

            if (this.cursorSettings.cursorActiveXY == 1) {
                if (this.cursorSettings.cursorX1) {
                    let xBufPosition;
                    if (lr == DataRepository.getXSnapEnum().left) {
                        this.cursorSettings.snapHelperX1 -= this.cursorSettings.stepX;
                        xBufPosition = this.cursorSettings.snapHelperX1 / sampRate; //calculate position in buffer from sample rate
                        //if xBufPosition is not in array => going out of array, change to the first value
                        if (typeof xBufferSelected[xBufPosition] == 'undefined' || xBufferSelected[xBufPosition] === null) {
                            xBufPosition = 0;
                            this.cursorSettings.snapHelperX1 = xBufPosition * sampRate;
                        }
                    } else if (lr == DataRepository.getXSnapEnum().right) {
                        this.cursorSettings.snapHelperX1 += this.cursorSettings.stepX;
                        xBufPosition = this.cursorSettings.snapHelperX1 / sampRate; //calculate position in buffer from sample rate
                        //if xBufPosition is not in array => going out of array, change to the last value
                        if (typeof xBufferSelected[xBufPosition] == 'undefined' || xBufferSelected[xBufPosition] === null) {
                            xBufPosition = xBufferSelected.length - 1;
                            this.cursorSettings.snapHelperX1 = xBufPosition * sampRate;
                        }
                    } else { //noChange
                        this.cursorSettings.snapHelperX1 = 0;
                        xBufPosition = this.cursorSettings.snapHelperX1 / sampRate;
                    }
                    if (DataRepository.getGeneralSettings().rightToLeft != DataRepository.getRTLEnum().righttoleft) { 
                        this.cursorSettings.cursorX1_coor = ((k_x * xBufferSelected[xBufPosition]) + d_x);
                    }
                    else {
                        this.cursorSettings.cursorX1_coor = cCanvasWidth - (((k_x * xBufferSelected[xBufPosition]) + d_x));
                    }
                    this.cursorSettings.cursorY1_coor = cCanvasHeight - ((k_c * yBufferSelected[xBufPosition]) + d_c);
                }
            } else {
                if (this.cursorSettings.cursorX2) {
                    let xBufPosition;
                    if (lr == DataRepository.getXSnapEnum().left) {
                        this.cursorSettings.snapHelperX2 -= this.cursorSettings.stepX;
                        xBufPosition = this.cursorSettings.snapHelperX2 / sampRate; //calculate position in buffer from sample rate
                        //if xBufPosition is not in array => going out of array, change to the first value
                        if (typeof xBufferSelected[xBufPosition] == 'undefined' || xBufferSelected[xBufPosition] === null) {
                            xBufPosition = 0;
                            this.cursorSettings.snapHelperX2 = xBufPosition * sampRate;
                        }
                    } else if (lr == DataRepository.getXSnapEnum().right) {
                        this.cursorSettings.snapHelperX2 += this.cursorSettings.stepX;
                        xBufPosition = this.cursorSettings.snapHelperX2 / sampRate; //calculate position in buffer from sample rate
                        //if xBufPosition is not in array => going out of array, change to the last value
                        if (typeof xBufferSelected[xBufPosition] == 'undefined' || xBufferSelected[xBufPosition] === null) {
                            xBufPosition = xBufferSelected.length - 1;
                            this.cursorSettings.snapHelperX2 = xBufPosition * sampRate;
                        }
                    } else {//noChange
                        this.cursorSettings.snapHelperX2 = 0;
                        xBufPosition = this.cursorSettings.snapHelperX2 / sampRate;
                    }
                    if (DataRepository.getGeneralSettings().rightToLeft != DataRepository.getRTLEnum().righttoleft) {
                        this.cursorSettings.cursorX2_coor = ((k_x * xBufferSelected[xBufPosition]) + d_x);
                    }
                    else {
                        this.cursorSettings.cursorX2_coor = cCanvasWidth - (((k_x * xBufferSelected[xBufPosition]) + d_x));
                    }
                    this.cursorSettings.cursorY2_coor = cCanvasHeight - ((k_c * yBufferSelected[xBufPosition]) + d_c);
                }
            }
            //this.redrawCursorCanvas();
        } else {
            this.wndApi.systemWindow_alert(this.alertChannelNotChosenText, this.alertChannelNotChosenTop, 2);
        }
    }*/

    //cursor 'Left' button pressed
    cursorMoveLeft() {
        let cCanvasWidth = this.$.cursorCanvas.clientWidth; //get canvas width
        let cCanvasHeight = this.$.cursorCanvas.clientHeight; //get canvas height
        let stepX = this.cursorSettings.stepX * (cCanvasWidth / this.gridlinesx); //calculate the step (according the grid divisions)

        //if (!this.cursorSettings.snapXAxis) { // if snapping axis is not enabled
            if (this.cursorSettings.cursorActiveXY == 1) { //if X1/Y1 cursors are active
                if (this.cursorSettings.cursorX1) { //if X1 is used
                    if (this.cursorSettings.cursorX1_coor != 0 && ((this.cursorSettings.cursorX1_coor - stepX) >= 0)) { //when cursor is not zero or will be outside the boundaries after next step
                        this.cursorSettings.cursorX1_coor -= stepX;
                        this.getCursorData(this.cursorSettings.cursorActiveXY);     
                    } else {
                        this.cursorSettings.cursorX1_coor = 0;
                        this.getCursorData(this.cursorSettings.cursorActiveXY);     
                    }
                }
            } else {
                if (this.cursorSettings.cursorX2) {
                    if (this.cursorSettings.cursorX2_coor != 0 && ((this.cursorSettings.cursorX2_coor - stepX) >= 0)) { //when cursor is not zero or will be outside the boundaries after next step
                        this.cursorSettings.cursorX2_coor -= stepX;
                        this.getCursorData(this.cursorSettings.cursorActiveXY);     
                    } else {
                        this.cursorSettings.cursorX2_coor = 0;
                        this.getCursorData(this.cursorSettings.cursorActiveXY);   
                    }
                }
            }
            //this.redrawCursorCanvas();
        /*} else {
            this.cursorSnap(this.XSnapEnum.left, cCanvasWidth, cCanvasHeight);
        }*/
    }

    //cursor 'Right" button pressed
    cursorMoveRight() {
        /*let canv = this.$.cursorCanvas;
        let xMax = canv.clientWidth;
        let xMin = 0;
        let xMaxMin = xMax - xMin;
        let k_x = (this.generalSettings.xScale / xMaxMin);
        let d_x = -(xMin * k_x);
        let bufferValuesHist = JSManager.getRingBufferMapHist();
        let bufferXConstVal = JSManager.getBufferXConst();*/

        let cCanvasWidth = this.$.cursorCanvas.clientWidth;
        let cCanvasHeight = this.$.cursorCanvas.clientHeight;

        //if (!this.cursorSettings.snapXAxis) {
            if (this.cursorSettings.cursorActiveXY == 1) {
                if (this.cursorSettings.cursorX1) {
                    if (this.cursorSettings.cursorX1_coor != cCanvasWidth && ((this.cursorSettings.cursorX1_coor + this.cursorSettings.stepX) <= cCanvasWidth)) {
                        this.cursorSettings.cursorX1_coor += this.cursorSettings.stepX * (cCanvasWidth / this.gridlinesx);
                        this.getCursorData(this.cursorSettings.cursorActiveXY);                             
                    } else {
                        this.cursorSettings.cursorX1_coor = cCanvasWidth;
                        this.getCursorData(this.cursorSettings.cursorActiveXY);
                    }
                }
            } else {
                if (this.cursorSettings.cursorX2) {
                    if (this.cursorSettings.cursorX2_coor != cCanvasWidth && ((this.cursorSettings.cursorX2_coor + this.cursorSettings.stepX) <= cCanvasWidth)) {
                        this.cursorSettings.cursorX2_coor += this.cursorSettings.stepX * (cCanvasWidth / this.gridlinesx);
                        this.getCursorData(this.cursorSettings.cursorActiveXY);
                    } else {
                        this.cursorSettings.cursorX2_coor = cCanvasWidth;
                        this.getCursorData(this.cursorSettings.cursorActiveXY);
                    }
                }
            }
            //this.redrawCursorCanvas();
        /*} else {
            this.cursorSnap(this.XSnapEnum.right, cCanvasWidth, cCanvasHeight);
        }*/

        //console.log(bufferValuesHist);                

        //recalculate values for both cursors (according to canvas size)
        /*let testVal1 = k_x * this.cursorSettings.cursorX1_coor + d_x;
        let testVal2 = k_x * this.cursorSettings.cursorX2_coor + d_x;

        //recalculate values according to scale
        let recalcTestVal1 = this.generalSettings.xScale - testVal1;
        let recalcTestVal2 = this.generalSettings.xScale - testVal2;

        console.log("--- Test Val 1 ---");
        console.log(testVal1);
        console.log("--- Recalc Test Val 1 ---");
        console.log(recalcTestVal1);

        console.log("--- Test Val 2 ---");
        console.log(testVal2);
        console.log("--- Recalc Test Val 2 ---");
        console.log(recalcTestVal2);

        let sampleRateArr = [];*/

        //let interpValue = new Map();

        /*for (let [key, value] of bufferValuesHist) 
        {
            if (typeof key === 'string' || key instanceof String) //find all sample rates
            {
                console.log("Interpolated string!");

                if (key.includes(bufferXConstVal))
                {
                    console.log(value);

                    console.log("Split: " + parseInt(key.split(bufferXConstVal)[1]));                            
                    interpValue.set(parseInt(key.split(bufferXConstVal)[1]), new interpolationData(value.buffer[value.pointer - 1], value.buffer[value.pointer - 1] - recalcTestVal1, value.buffer[value.pointer-1], value.buffer[value.pointer - 1] - recalcTestVal2));
                    console.log(interpValue);
                    console.log(recalcTestVal1);
                    console.log(recalcTestVal2);
                }
            }
        }*/

        /*for (let [key, value] of bufferValuesHist)
        {
            if (!isNaN(key))
            {
                if (!this.cursorVals.has(key)) this.cursorVals.set(key, new interpolationData());

                console.log("Cursor Active: " + this.cursorSettings.cursorActiveXY);
                
                console.log("Key: " + key);

                let sampRate = this.channelArray.get(key).channelSettings.sampRate;

                let srVals = bufferValuesHist.get(bufferXConstVal + sampRate.toString());

                if (this.cursorSettings.cursorActiveXY == 1) //if cursor X1/Y1 is active
                {
                    console.log(srVals);

                    let maxBuffVal1 = srVals.buffer[srVals.pointer - 1];

                    console.log("--- Max Buff Value 1 ---");
                    console.log(maxBuffVal1);

                    let expBuffVal1 = srVals.buffer[srVals.pointer - 1] - recalcTestVal1;

                    console.log("--- Exp Buff Value 1 ---");
                    console.log(expBuffVal1);

                    let dataIndex1 = this.isInArray(expBuffVal1, srVals.buffer);

                    console.log("--- Data Index 1 ---");
                    console.log(dataIndex1);

                    if (dataIndex1 == -1) //if value is not in the array
                    {
                        let closestVals = this.getClosest(srVals.buffer, expBuffVal1);

                        console.log("--- Closest Vals ---");
                        console.log(closestVals);

                        let min = value.buffer[closestVals[1]];
                        let max = value.buffer[closestVals[3]];

                        console.log("--- Min Y ---");
                        console.log(min);

                        console.log("--- Max Y ---");
                        console.log(max);

                        this.cursorVals.get(key).cursorX1Value = expBuffVal1;

                        let maxmin = closestVals[2]-closestVals[0];
                        let exprecalcval = closestVals[2] - expBuffVal1;

                        let frac = exprecalcval / maxmin;

                        console.log("MaxMin: " + maxmin);
                        console.log("ExpreCalcVal: " + exprecalcval);
                        console.log("Frac: " + frac);

                        this.cursorVals.get(key).cursorY1Value = this.lerp(min, max, frac);

                        console.log("Lerp: " + this.cursorVals.get(key).cursorY1Value);

                        let closestValsTest = this.getClosest([10000, 15000, 20000], 11599.2566);
                        console.log(closestValsTest);
                    }
                    else
                    {
                        this.cursorVals.get(key).cursorY1Value = value.buffer[dataIndex1];

                        console.log("Value: " + value.buffer[dataIndex1]);


                    }

                    //console.log(yVals);
                } 
                else //if cursor X2/Y2 is active
                {
                    let maxBuffVal2 = srVals.buffer[srVals.pointer - 1];

                    console.log("--- Max Buff Value 2 ---");
                    console.log(maxBuffVal2);

                    let expBuffVal2 = srVals.buffer[srVals.pointer - 1] - recalcTestVal2;

                    console.log("--- Exp Buff Value 2 ---");
                    console.log(expBuffVal2);

                    let dataIndex2 = this.isInArray(expBuffVal2, srVals.buffer);

                    console.log("--- Data Index 2 ---");
                    console.log(dataIndex2);

                    if (dataIndex2 == -1) //if value is not in the array
                    {
                        let closestVals = this.getClosest(srVals.buffer, expBuffVal2);

                        console.log("--- Closest Vals ---");
                        console.log(closestVals);

                        let min = value.buffer[closestVals[1]];
                        let max = value.buffer[closestVals[3]];

                        console.log("--- Min Y ---");
                        console.log(min);

                        console.log("--- Max Y ---");
                        console.log(max);

                        this.cursorVals.get(key).cursorX2Value = expBuffVal2;
                    
                        let maxmin = closestVals[2]-closestVals[0];
                        let exprecalcval = closestVals[2] - expBuffVal2;

                        let frac = exprecalcval / maxmin;

                        console.log("MaxMin: " + maxmin);
                        console.log("ExpreCalcVal: " + exprecalcval);
                        console.log("Frac: " + frac);

                        this.cursorVals.get(key).cursorY2Value = this.lerp(min, max, frac);

                        console.log("Lerp: " + this.cursorVals.get(key).cursorY2Value );

                        let closestValsTest = this.getClosest([10000, 15000, 20000], 11599.2566);
                        console.log(closestValsTest);
                    }
                    else
                    {
                        this.cursorVals.get(key).cursorY2Value = value.buffer[dataIndex2];

                        console.log("Value: " + value.buffer[dataIndex2]);
                    }
                }
            }
        }*/

        /* for (let [key, value] of bufferValuesHist) {
            if (typeof key === 'string' || key instanceof String)
            {
                console.log('STRING');
                if (key.includes(bufferXConstVal))
                {
                    let maxBuffVal = value.buffer[value.pointer - 1];
                    let expBuffVal = value.buffer[value.pointer - 1] - recalcTestVal1;

                    console.log("testVal1: " + testVal1);
                    console.log("recalcTestVal1: " + recalcTestVal1);
                    console.log("maxBuffVal:" + maxBuffVal);
                    console.log("expBuffVal: " + expBuffVal);

                    let dataIndex;
                    let data;
                    let dataVals = [];

                    dataIndex = this.isInArray(expBuffVal, value.buffer);

                    console.log("----data index------");
                    console.log(dataIndex);
                    console.log("--------------------");

                    if (dataIndex != -1)
                    {
                        console.log("NOT INTERPOLATING!");         

                        data = expBuffVal;

                        for (let [key, value] of bufferValuesHist)
                        {
                            if (!isNaN(key)) //if key is number
                            {
                                dataVals.push(value.buffer[dataIndex]);
                            }
                        }
                    }
                    else
                    {
                        console.log("INTERPOLATING!");

                        data = this.getClosest(value.buffer, expBuffVal);

                        for (let [key, value] of bufferValuesHist)
                        {
                            if (!isNaN(key)) //if key is number
                            {
                                let intDataMin = -1;
                                let intDataMax = -1;
                                let intVal = 1;

                                console.log("DATA");
                                console.log(data);
                                console.log(value);

                                let min = value.buffer[data[1]];
                                let max = value.buffer[data[3]];

                                let maxmin = data[2]-data[0];
                                let exprecalcval = data[2] - expBuffVal;

                                let frac = exprecalcval / maxmin;

                                console.log("Min: " + min);
                                console.log("Max: " + max);
                                console.log("MaxMin: " + maxmin);
                                console.log("ExPreCalcVal: " + exprecalcval);
                                console.log("Frac: " + frac);

                                let lerpval = this.lerp(min, max, frac);

                                console.log("Lerp: " + lerpval);

                            }
                        }
                    }

                    console.log("-------Data----------");
                    console.log(data);
                    console.log("---------------------");

                    console.log("------DataVals--------");
                    console.log(dataVals);
                    console.log("----------------------");

                    console.log("-------------------------");
                    console.log(value.buffer[value.pointer - 1]);
                    console.log("-------------------------");
                }
            }
        }

        console.log(testVal1);
        console.log(testVal2);*/
    }

    getCursorData(cursorType) {
        let canv = this.$.cursorCanvas;
        let xMax = canv.clientWidth;
        let xMin = 0;
        let xMaxMin = xMax - xMin;
        let k_x = (DataRepository.getGeneralSettings().xScale * this.gridlinesx / xMaxMin);
        let d_x = -(xMin * k_x);
        let bufferValuesHist = JSManager.getRingBufferMapHist(); //get buffer historical data
        let bufferXConstVal = JSManager.getBufferXConst(); //get x constant
        let noValueConst = "-";

        let testVal;

        if (cursorType == 1) testVal = k_x * this.cursorSettings.cursorX1_coor + d_x; //recalculate values for both cursors (according to canvas size)
        else testVal = k_x * this.cursorSettings.cursorX2_coor + d_x; //recalculate values for both cursors (according to canvas size)

        let recalcTestVal = DataRepository.getGeneralSettings().xScale * this.gridlinesx - testVal; //recalculate values according to scale

        for (let [key, value] of bufferValuesHist)
        {
            if (!isNaN(key))
            {
                if (!this.cursorVals.has(key)) this.cursorVals.set(key, new interpolationData()); //if there is not cursor data in map, add the new cursor value

                let sampRate = DataRepository.getChannelArray().get(key).channelSettings.sampRate;
                let srVals = bufferValuesHist.get(bufferXConstVal + sampRate.toString());

                let maxBuffVal = srVals.buffer[srVals.pointer - 1]; //max value from buffer
                let expBuffVal = srVals.buffer[srVals.pointer - 1] - recalcTestVal;  //expected value from buffer
                let dataIndex = this._isInArray(expBuffVal, srVals.buffer); //test if cursor value is in array (-1 if not)

                if (dataIndex == -1)
                {
                    let closestVals = this.getClosest(srVals.buffer, expBuffVal); //calculate closest values with their indexes

                    let min = value.buffer[closestVals[1]]; //lower boundary around expected value index
                    let max = value.buffer[closestVals[3]]; //upper boundary around expected value index

                    let maxmin = closestVals[2] - closestVals[0]; //difference between lower and upper boundary value
                    let exprecalcval = closestVals[2] - expBuffVal; //expected val from range

                    let frac = exprecalcval / maxmin; //get fraction value for interpolation
                    let lerp = this._lerp(min, max, frac); //linear interpolation

                    if (cursorType == 1)
                    { 
                        this.cursorVals.get(key).cursorX1Value = expBuffVal;
                        if (this.cursorVals.get(key).cursorX2Value != '-') this.cursorVals.get(key).cursorXDiffValue = Math.abs(this.cursorVals.get(key).cursorX2Value - this.cursorVals.get(key).cursorX1Value);
                        this.cursorVals.get(key).cursorY1Value = lerp;
                        if (this.cursorVals.get(key).cursorY2Value != '-') this.cursorVals.get(key).cursorYDiffValue = Math.abs(this.cursorVals.get(key).cursorY2Value - this.cursorVals.get(key).cursorY1Value);
                    }
                    else
                    {
                        this.cursorVals.get(key).cursorX2Value = expBuffVal;
                        if (this.cursorVals.get(key).cursorX1Value != '-') this.cursorVals.get(key).cursorXDiffValue = Math.abs(this.cursorVals.get(key).cursorX2Value - this.cursorVals.get(key).cursorX1Value);
                        this.cursorVals.get(key).cursorY2Value = lerp;
                        if (this.cursorVals.get(key).cursorY1Value != '-') this.cursorVals.get(key).cursorYDiffValue = Math.abs(this.cursorVals.get(key).cursorY2Value - this.cursorVals.get(key).cursorY1Value);
                    } 
                }
                else
                {                           
                    let yVal = value.buffer[dataIndex]; //take yvalue directly from buffer 

                    if (cursorType == 1)
                    { 
                        this.cursorVals.get(key).cursorX1Value = expBuffVal;
                        if (this.cursorVals.get(key).cursorX2Value != '-') this.cursorVals.get(key).cursorXDiffValue = Math.abs(this.cursorVals.get(key).cursorX2Value - this.cursorVals.get(key).cursorX1Value);
                        this.cursorVals.get(key).cursorY1Value = yVal;
                        if (this.cursorVals.get(key).cursorY2Value != '-') this.cursorVals.get(key).cursorYDiffValue = this.cursorVals.get(key).cursorY2Value - this.cursorVals.get(key).cursorY1Value;
                    }
                    else
                    {
                        this.cursorVals.get(key).cursorX2Value = expBuffVal;
                        if (this.cursorVals.get(key).cursorX1Value != '-') this.cursorVals.get(key).cursorXDiffValue = this.cursorVals.get(key).cursorX2Value - this.cursorVals.get(key).cursorX1Value;
                        this.cursorVals.get(key).cursorY2Value = yVal;
                        if (this.cursorVals.get(key).cursorY1Value != '-') this.cursorVals.get(key).cursorYDiffValue = this.cursorVals.get(key).cursorY2Value - this.cursorVals.get(key).cursorY1Value;
                    } 
                }
            }
        }

        dispatchEvent(new CustomEvent("cursorDataChanged", {
                'detail': {
                    data: this.cursorVals
                }
            }));
    }

    //helper methods for getClosest method - get Lower Bound
    lowerBound(arr, x, from=0, to=arr.length) {
        if(from >= to) return to-1;
        let m = Math.floor( (from+to)/2 );
        if(arr[m] < x) return this.lowerBound(arr, x, m+1, to);
        return this.lowerBound(arr, x, from, m);
    }

    //helper method for getClosest method - get Upper Bound
    upperBound(arr, x, from=0, to=arr.length) {
        if(from >= to) return to;
        let m = Math.floor( (from+to)/2 );
        if(arr[m] > x) return this.upperBound(arr, x, from, m);
        return this.upperBound(arr, x, m+1, to);
    }

    //get closest number with index
    getClosest(a, x) {
        let lb = this.lowerBound(a, x),
            ub = this.upperBound(a, x, lb+1),
            res = [];
        if(lb >= 0)
        {
            res.push(a[lb]);
            res.push(lb);
        }
        if(ub < a.length)
        {
            res.push(a[ub]);
            res.push(ub);
        } 
        return res;
    }

    //return index of array if it's in array if not return -1
    _isInArray(value, array) {
        return array.indexOf(value);
    }

    //linear interpolation
    _lerp(a, b, f) {
        return a + f * (b - a);
    }

    /*getClosestValues(array, value)
    {
        var lo = -1, hi = array.length;

        while (hi - lo > 1) {
            var mid = Math.round((lo + hi)/2);
            if (array[mid] <= value) {
                lo = mid;
            } else {
                hi = mid;
            }
        }

        if (array[lo] == value) hi = lo;
        return [array[lo], array[hi], lo, hi];
    }*/

    //cursor 'Down' button pressed
    cursorMoveDown() {
        let canvHeight = this.$.cursorCanvas.height;
        //if (!this.cursorSettings.snapXAxis) {
        if (this.cursorSettings.cursorActiveXY == 1) {
            if (this.cursorSettings.cursorY1) {
                if (this.cursorSettings.cursorY1_coor != canvHeight && ((this.cursorSettings.cursorY1_coor + this.cursorSettings.stepY) <= canvHeight)) {
                    this.cursorSettings.cursorY1_coor += this.cursorSettings.stepY
                } else {
                    this.cursorSettings.cursorY1_coor = canvHeight;
                }
            }
        } else {
            if (this.cursorSettings.cursorY2) {
                if (this.cursorSettings.cursorY2_coor != canvHeight && ((this.cursorSettings.cursorY2_coor + this.cursorSettings.stepY) <= canvHeight)) {
                    this.cursorSettings.cursorY2_coor += this.cursorSettings.stepY;
                } else {
                    this.cursorSettings.cursorY2_coor = canvHeight;
                }
            }
        }
            //this.redrawCursorCanvas();
        /*} else {
            if (this.cursorSettings.snapChannel != -1) {
                let selChan = this.cursorSettings.snapChannel;
                let sampRate = this.channelArray.get(parseInt(selChan)).channelSettings.sampRate;
                let xMax, xMin, xMaxMin, xPointer;
                let xValues, yValues, yPointer, xCapacity, yCapacity, yLength;
                let bufferValuesHist = JSManager.getRingBufferMapHist();
                let bufferXConstVal = JSManager.getBufferXConst();
                xValues = bufferValuesHist.get(bufferXConstVal + sampRate).buffer;
                xPointer = bufferValuesHist.get(bufferXConstVal + sampRate).pointer;
                xCapacity = bufferValuesHist.get(bufferXConstVal + sampRate).capacity;
                yValues = bufferValuesHist.get(selChan).buffer;
                yPointer = bufferValuesHist.get(selChan).pointer;
                yCapacity = bufferValuesHist.get(selChan).capacity;
                yLength = bufferValuesHist.get(selChan).length;
                xPointer == 0 ? xMax = xValues[xValues.length - 1] : xMax = xValues[xPointer - 1];
                let xStep = ((this.generalSettings.xScale) / 10);
                xMin = (xMax - (xStep * 10));
                xMaxMin = xMax - xMin;
                let k_x = (cCanvasWidth / xMaxMin);
                let d_x = -(xMin * k_x);
                let localMin = 0;
                let localMax = 0;

                if (this.channelArray.get(selChan).channelSettings.useAutoset) {
                    localMin = this.channelArray.get(selChan).channelSettings.autosetMin;
                    localMax = this.channelArray.get(selChan).channelSettings.autosetMax;
                } else {
                    localMin = this.channelArray.get(selChan).channelSettings.minValue;
                    localMax = this.channelArray.get(selChan).channelSettings.maxValue;
                }

                let maxmin = localMax - localMin;
                let k_c = (cCanvasHeight / maxmin);
                let d_c = -(localMin * k_c);
                let xBufferSelected = [];
                let yBufferSelected = [];

                if (this.sliderValue == 100) {
                    if (yPointer == 0 || yLength != yCapacity) {
                        for (let b = 0; b < xValues.length; b++) {
                            if (xValues[b] >= xMin) {
                                xBufferSelected.push(xValues[b]);
                                yBufferSelected.push(yValues[b]);
                            }
                        }
                    } else {
                        for (let pn = yPointer; pn < yValues.length; pn++) {
                            if (xValues[pn] >= xMin) {
                                xBufferSelected.push(xValues[pn]);
                                yBufferSelected.push(yValues[pn]);
                            }
                        }
                        for (let pr = 0; pr < yPointer; pr++) {
                            if (xValues[pr] >= xMin) {
                                xBufferSelected.push(xValues[pr]);
                                yBufferSelected.push(yValues[pr]);
                            }
                        }
                    }
                }
                if (this.cursorSettings.cursorActiveXY == 1) {
                    if (this.cursorSettings.cursorX1) {
                        this.cursorSettings.snapHelperX1 -= this.cursorSettings.stepX;
                        let xBufPosition = this.cursorSettings.snapHelperX1 / sampRate; //calculate position in buffer from sample rate
                        if (this.generalSettings.rightToLeft != this.RTLEnum.rightToLeft) {
                            this.cursorSettings.cursorX1_coor = ((k_x * xBufferSelected[xBufPosition]) + d_x);
                        } else {
                            this.cursorSettings.cursorX1_coor = cCanvasWidth - (((k_x * xBufferSelected[xBufPosition]) + d_x));
                        }
                        this.cursorSettings.cursorY1_coor = cCanvasHeight - ((k_c * yBufferSelected[xBufPosition]) + d_c);
                    }
                } else {
                    if (this.cursorSettings.cursorX2) {
                        this.cursorSettings.snapHelperX2 -= this.cursorSettings.stepX;
                        let xBufPosition = this.cursorSettings.snapHelperX2 / sampRate; //calculate position in buffer from sample rate
                        if (this.generalSettings.rightToLeft != this.RTLEnum.rightToLeft) {
                            this.cursorSettings.cursorX2_coor = ((k_x * xBufferSelected[xBufPosition]) + d_x);
                        } else {
                            this.cursorSettings.cursorX2_coor = cCanvasWidth - (((k_x * xBufferSelected[xBufPosition]) + d_x));
                        }
                        this.cursorSettings.cursorY2_coor = cCanvasHeight - ((k_c * yBufferSelected[xBufPosition]) + d_c);
                    }
                }
                //this.redrawCursorCanvas();
            } else {
                this.wndApi.systemWindow_alert('Channel for snapping was not chosen!', 'Channel not chosen', 2);
            }
        }*/
    }

    //cursor 'Up' button pressed
    cursorMoveUp() {
        //if (!this.cursorSettings.snapXAxis) {
            if (this.cursorSettings.cursorActiveXY == 1) {
                if (this.cursorSettings.cursorY1) {
                    if (this.cursorSettings.cursorY1_coor != 0 && ((this.cursorSettings.cursorY1_coor - this.cursorSettings.stepY) >= 0)) {
                        this.cursorSettings.cursorY1_coor -= this.cursorSettings.stepY;
                    } else {
                        this.cursorSettings.cursorY1_coor = 0;
                    }
                }
            } else {
                if (this.cursorSettings.cursorY2) {
                    if (this.cursorSettings.cursorY2_coor != 0 && ((this.cursorSettings.cursorY2_coor - this.cursorSettings.stepY) >= 0)) {
                        this.cursorSettings.cursorY2_coor -= this.cursorSettings.stepY;
                    } else {
                        this.cursorSettings.cursorY2_coor = 0;
                    }
                }
            }
            //this.redrawCursorCanvas();
        //}
    }

    //#endregion

    clearCanvas() {
        this.isCanvasCleared = true;

        /* if (this.frameRequest != null) {
            this.frameRequest = window.cancelAnimationFrame(this.frameRequest);
        } */

        if (DataRepository.getGeneralSettings().rightToLeft == DataRepository.getRTLEnum().righttoleft) {
            this.$.sliderTest.value = 100;
            DataRepository.setSliderValue(this.$.sliderTest.value);
        } 
        else {
            this.$.sliderTest.value = 0;
            DataRepository.setSliderValue(this.$.sliderTest.value);
        } 

        this._clearOsciCanvas();
        //debugger;

        this.done = false;

        //this._bufferListener();
    }

    _clearOsciCanvas() {
        let canv = this.$.osciCanvas;
        let context = canv.getContext('2d');
        context.canvas.width = this.$.drawingArea.clientWidth;
        context.canvas.height = this.$.drawingArea.clientHeight;
        context.clearRect(0, 0, canv.width, canv.height); //Clear the oscis
    }

    // --- functions for converting enums to string and back (because JSON.stringify ignores them) ---
    _yAxisPositionString(channel) {
        if (channel.scaleSettings.axisPosition == DataRepository.getYAxisEnum().right) return 'right';
        else if (channel.scaleSettings.axisPosition == DataRepository.getYAxisEnum().left) return 'left';
        else return 'none';
    }

    _yAxisUnitPositionString(channel) {
        if (channel.scaleSettings.yAxisUnitPosition == DataRepository.getYAxisPositionEnum().top) return 'top';
        else if (channel.scaleSettings.yAxisUnitPosition == DataRepository.getYAxisPositionEnum().bottom) return 'bottom';
        else return 'hide';
    }    

    _yAxisPositionEnum(scale) {
        if (scale.axisPosition == 'right') return DataRepository.getYAxisEnum().right;
        else if (scale.axisPosition == 'left') return DataRepository.getYAxisEnum().left;
        else return DataRepository.getYAxisEnum().none;
    }

    _yAxisUnitPositionEnum(scale) {
        if (scale.yAxisUnitPosition == 'top') return DataRepository.getYAxisPositionEnum().top;
        else if (scale.yAxisUnitPosition == 'bottom') return DataRepository.getYAxisPositionEnum().bottom;
        else return DataRepository.getYAxisPositionEnum().hide;
    }

    // -----------------------------------------------------------------------------------------------     

    unload(e) {
        clearInterval(this.timer);
        this.timer = null;
    }

    /*selectedChannel_Changed(e) {
        DataRepository.setSelectedChannel(e.detail.channel);
        if (DataRepository.getChannelArray().size != 0) {
            dispatchEvent(new CustomEvent("channelSettingsUpdate", {
                'detail': {
                    channelSettings: DataRepository.getChannelArray().get(DataRepository.getSelectedChannel()).channelSettings
                }
            }));
            dispatchEvent(new CustomEvent("scaleSettingsValue_Changed", {
                'detail': {
                    scaleSettings: DataRepository.getChannelArray().get(DataRepository.getSelectedChannel()).scaleSettings
                }
            }));
        }
    }*/

    //_scaleXValueChanged(e) {
        //DataRepository.getGeneralSettings().xScale = e.detail.scaleX;
        //DataRepository.setGeneralSettings(DataRepository.getGeneralSettings().rightToLeft, e.detail.scaleX, DataRepository.getGeneralSettings().xUnits);
    /* _changeSliderValue(e) {
        this.$.zoomSlider.value = 0;
    } */

    _yAxisChanged() {
        if (DataRepository.getGeneralSettings().rightToLeft == DataRepository.getRTLEnum().lefttoright) {
            if (!DataRepository.getChannelArray().get(DataRepository.getSelectedChannel()).scaleSettings.yAxisActive || 
                DataRepository.getChannelArray().get(DataRepository.getSelectedChannel()).channelSettings.scalingMode == "Reference") {
                DataRepository.changeYAxisPosition(DataRepository.getSelectedChannel(), DataRepository.getYAxisEnum().none);
            } /* else if (!DataRepository.getChannelArray().get(DataRepository.getSelectedChannel()).scaleSettings.turnYAxis) {
                DataRepository.changeYAxisPosition(DataRepository.getSelectedChannel(), DataRepository.getYAxisEnum().right);
            }  else {
                DataRepository.changeYAxisPosition(DataRepository.getSelectedChannel(), DataRepository.getYAxisEnum().left);
            }*/
        } else {
            if (!DataRepository.getChannelArray().get(DataRepository.getSelectedChannel()).scaleSettings.yAxisActive || 
                DataRepository.getChannelArray().get(DataRepository.getSelectedChannel()).channelSettings.scalingMode == "Reference") {
                DataRepository.changeYAxisPosition(DataRepository.getSelectedChannel(), DataRepository.getYAxisEnum().none);
            } /* else if (!DataRepository.getChannelArray().get(DataRepository.getSelectedChannel()).scaleSettings.turnYAxis) {
                DataRepository.changeYAxisPosition(DataRepository.getSelectedChannel(), DataRepository.getYAxisEnum().left);
            } else {
                DataRepository.changeYAxisPosition(DataRepository.getSelectedChannel(), DataRepository.getYAxisEnum().right);
            }*/ 
        }
    }

    /*_channelActiveChanged(e) {
        if (DataRepository.getChannelArray().size != 0) {
            DataRepository.changeChannelActive(this.selectedChannel, e.detail.channelactive);
        }

        dispatchEvent(new CustomEvent("channelActiveGraphs_Changed", {'detail': {
            channelActive: e.detail.channelactive,
            channelNumber: this.selectedChannel
        }}));		 
    }*/

    //right to left changed in general settings
    _rightToLeftClicked(e) {
        if (e.detail.rightToLeft == DataRepository.getRTLEnum().lefttoright) { //left to right
            //DataRepository.getGeneralSettings().rightToLeft = DataRepository.getRTLEnum().leftToRight;
            //DataRepository.setGeneralSettings(DataRepository.getRTLEnum().leftToRight, DataRepository.getGeneralSettings().xScale, DataRepository.getGeneralSettings().xUnits);

            this.$.sliderTest.limitLow = 0; //set low limit to 0
            this.$.sliderTest.value = 0; 
            DataRepository.setSliderValue(this.$.sliderTest.value);
        } else { //right to left
            //DataRepository.getGeneralSettings().rightToLeft = DataRepository.getRTLEnum().rightToLeft;
            //DataRepository.setGeneralSettings(DataRepository.getRTLEnum().rightToLeft, DataRepository.getGeneralSettings().xScale, DataRepository.getGeneralSettings().xUnits);

            this.$.sliderTest.limitHigh = 100; //set high limit to 100
            this.$.sliderTest.value = 100; 
            DataRepository.setSliderValue(this.$.sliderTest.value);
        }        
    }

    deleteYAxisCanvas() {          									 
        this.$.canvas_yAxisArea1.getContext('2d').clearRect(0, 0, this.$.canvas_yAxisArea1.width, this.$.canvas_yAxisArea1.height);
        this.$.canvas_yAxisArea2.getContext('2d').clearRect(0, 0, this.$.canvas_yAxisArea2.width, this.$.canvas_yAxisArea2.height);
    }

    _designerOnResize() {
        SigPolymer.afterNextRender(this, function(params) {
            this.redrawGrid(true);
        });
    }

    _designerOnAppliedCSSValue(cssObj) {
        let prop = '--theme-sig-control-da-graphs-axis-color';
        if (cssObj.hasOwnProperty(prop)) {
            this.$.canvas_xAxisArea.style.color = cssObj[prop];
        }
        SigPolymer.afterNextRender(this, function(params) {
            this.redrawGrid(true);
        });
    }

    redrawGrid(redrawAxis) {

        let textColor, fontFamily, fontSize, font;
        if (redrawAxis) {
            textColor = getComputedStyle(this).color;
            fontFamily = getComputedStyle(this).fontFamily;
            fontSize = getComputedStyle(this).fontSize;
            font = fontSize + " " + fontFamily;
        }

        this.$.gridCanvas.getContext('2d').canvas.width = this.$.drawingArea.clientWidth;
        this.$.gridCanvas.getContext('2d').canvas.height = this.$.drawingArea.clientHeight;
        this.$.osciCanvas.getContext('2d').canvas.width = this.$.drawingArea.clientWidth;
        this.$.osciCanvas.getContext('2d').canvas.height = this.$.drawingArea.clientHeight;
        this.$.cursorCanvas.getContext('2d').canvas.width = this.$.drawingArea.clientWidth;
        this.$.cursorCanvas.getContext('2d').canvas.height = this.$.drawingArea.clientHeight;

        this._drawGrid();

        if (redrawAxis) {
            this.$.canvas_yAxisArea1.width = this.$.yAxisArea1.clientWidth;
            this.$.canvas_yAxisArea1.height = this.$.yAxisArea1.clientHeight;
            this.$.canvas_yAxisArea2.width = this.$.yAxisArea2.clientWidth;
            this.$.canvas_yAxisArea2.height = this.$.yAxisArea2.clientHeight;
            this.$.canvas_xAxisArea.width = this.$.xAxisArea.clientWidth;
            this.$.canvas_xAxisArea.height = this.$.xAxisArea.clientHeight;
            this.$.canvas_unitsArea.width = this.$.unitsArea.clientWidth;
            this.$.canvas_unitsArea.height = this.$.unitsArea.clientHeight;

            this.drawXAxis(textColor, 0, 1, 0.1, font, redrawAxis);
			//console.log("redrawGrid");						  
            this.deleteYAxisCanvas();
            let chanDesignTime = new channelDesignTime(
                new channelSettingsDesignTime(0, undefined, 1, "testChan", true, 0, 100, 0, 1, "Own", false, 1, textColor,15600128, 1, "Solid", 1, "None"),
                new scaleSettingsDesignTime(1, 0, Symbol("right"), Symbol("hide")));
            this.drawYAxis(chanDesignTime, textColor, font, redrawAxis, 0, 0, 0);
        }
    }

    _drawGrid() {
        let context = this.$.gridCanvas.getContext('2d');
        context.clearRect(0, 0, this.$.gridCanvas.width, this.$.gridCanvas.height);

        //grid width and height 
        let bw = this.$.gridCanvas.clientWidth; //700; 
        let bh = this.$.gridCanvas.clientHeight; //560; 
        let zero = this.$.gridCanvas.clientHeight / 2;

        context.moveTo(0, zero);
        context.beginPath();

        let x = bw / (parseInt(this.gridlinesx));
        for (let i = 0; i < parseInt(this.gridlinesx - 1); i++) {
            context.moveTo(x, 0);
            context.lineTo(x, bh);
            x += bw / (parseInt(this.gridlinesx));
        }

        x = bh / (parseInt(this.gridlinesy));
        for (let i = 0; i < parseInt(this.gridlinesy - 1); i++) {
            context.moveTo(0, x);
            context.lineTo(bw, x);
            x += bh / (parseInt(this.gridlinesy));
        }

        if (this.gridstyle == "dot") {
            context.setLineDash([1, 1]);
        } else {
            context.setLineDash([]);
        }
        context.strokeStyle = getComputedStyle(this.$.gridCanvas).color;
        context.stroke();
        context.closePath();
    }

    /*startTimerSendEvent() {
        this.waitTime = performance.now();
        if (!super._isDesignMode() && !this.smApi.isInOfflinePreview()) {
            if (this.timer == null) {
                this.timer = setInterval(this.acknHandler.bind(this), 300);
            }
        }
    }*/

    _startButtonListener() {
        if (!super._isDesignMode() && !this.smApi.isInOfflinePreview()) {
            //this.startTimerSendEvent();
        }
    }

    /*acknHandler() {
        dispatchEvent(new CustomEvent("EV_TO_SPS_HELPER"));
        if (performance.now() - this.waitTime > 2000) {
            clearInterval(this.timer);
            this.timer = null;
            this.registerAck = 0;
            this.wndApi.systemWindow_alert(this.alertPLCNotActiveText, this.alertPLCNotActiveTop, 2);
        } else {
            if (JSManager.getRegisterAck() == 1) {
                this.registerAck = 1;
                clearInterval(this.timer);
                this.timer = null;
            }
        }
    }*/

    _stopButtonListener() {
        this.registerAck = 0;
        JSManager.setRegisterAck(0);
        dispatchEvent(new CustomEvent("EV_TO_SPS_UNREGISTER_HELPER"));
    }

    drawXAxis(textColor, xMin, xMax, xStep, font, redrawAxis) {
        let stepReal, i, j;
        let context = this.$.canvas_xAxisArea.getContext('2d');

        context.clearRect(0, 0, this.$.canvas_xAxisArea.width, this.$.canvas_xAxisArea.height);

        let drawingArea_width = this.$.drawingArea.clientWidth;
        let yAxis1Area_width = this.$.yAxisArea1.clientWidth;

        context.beginPath();
        this.changeXAxisLine(context, drawingArea_width, yAxis1Area_width);

        context.strokeStyle = getComputedStyle(this.$.canvas_xAxisArea).color;
        context.stroke();
        context.closePath();

        stepReal = this.$.drawingArea.clientWidth / (parseInt(this.gridlinesx));
        context.textBaseline = 'top';
        context.font = font;
        context.fillStyle = textColor;
        context.textAlign = "center";

        //------- draw text of x-axis ---------------
        this.XAxisTexts = [];
        this.XAxisTextWidth = 0;

        for (i = 0; i < (parseInt(this.gridlinesx) + 1); i++) {
            this.getXAxisTexts(context, i, xMin, xStep, redrawAxis);
        }

        if (!super._isDesignMode() && !this.smApi.isInOfflinePreview()) {
            if (DataRepository.getGeneralSettings().rightToLeft == DataRepository.getRTLEnum().lefttoright) {
                this.XAxisTexts.reverse();
            }
        }

        let loop_step = 1;
        if ((this.XAxisTextWidth / (parseInt(this.gridlinesx) + 1)) >= stepReal / 2) {
            loop_step = 2;
        }

        if ((this.XAxisTextWidth / (parseInt(this.gridlinesx) + 1)) > stepReal) {
            loop_step = 5;
        }

        for (i = 0; i < (parseInt(this.gridlinesx) + 1); i += loop_step) {
            this.drawXAxisTexts(context, yAxis1Area_width, i, stepReal);
        }
        //-------------------------------------------
        for (j = 0; j <= (parseInt(this.gridlinesx)); j++) {
            context.beginPath();
            this.changeXAxisLines(context, j, stepReal, yAxis1Area_width);
            context.strokeStyle = getComputedStyle(this.$.canvas_xAxisArea).color;
            context.stroke();
            context.closePath();
        }
    }

    changeXAxisLines(stageContext, j, stepReal, startPoint) {
        stageContext.moveTo(startPoint + (j * stepReal), 0);
        stageContext.lineTo(startPoint + (j * stepReal), 10);
    }

    getXAxisTexts(stageContext, i, xMin, xStep, redrawAxis) {
        let txt = "";
        if (redrawAxis) {
            txt = "x" + i.toString();
        } else {
            if (DataRepository.getGeneralSettings().timeType == 0) {
                txt = this._valueDivisor(((xMin + (i * xStep)))).toFixed(2) + " " + this._getxUnitText(DataRepository.getGeneralSettings().xUnits);
            } else {
                txt = this._valueDivisorTime(xMin, xStep, i);
            }

        }
        this.XAxisTexts.push(txt);
        this.XAxisTextWidth += stageContext.measureText(txt).width;
    }

    _getxUnitText(xUnit) {
        if (xUnit == "μs/div") return "μs";
        else if (xUnit == "ms/div") return "ms";
        else if (xUnit == "second/div") return "s";
        else if (xUnit == "minute/div") return "min";
        else if (xUnit == "hour/div") return "h";
        else if (xUnit == "day/div") return "d";
    }

    _valueDivisor(value) {
        const hours = 24;
        const min = 60;
        const thsnd = 1000;

        if (DataRepository.getGeneralSettings().xUnits == "μs/div") return value;
        else if (DataRepository.getGeneralSettings().xUnits == "ms/div") return value/thsnd;
        else if (DataRepository.getGeneralSettings().xUnits == "second/div") return value/Math.pow(thsnd, 2);
        else if (DataRepository.getGeneralSettings().xUnits == "minute/div") return value/(Math.pow(thsnd, 2)*min);
        else if (DataRepository.getGeneralSettings().xUnits == "hour/div") return value/(Math.pow(thsnd, 2)*Math.pow(min, 2));
        else return value/(Math.pow(thsnd, 2)*Math.pow(min, 2)*hours);
    }

    _valueDivisorTime(xMin, xStep, i) {
        let channelInfo = JSManager.getChannelInfo();

        let year = channelInfo.get(1).year;     
        let month = channelInfo.get(1).month;   
        let day = channelInfo.get(1).day;  
        let hour = channelInfo.get(1).hour;     
        let minute  = channelInfo.get(1).minute;  
        let second = channelInfo.get(1).second;  
        let millisecond = channelInfo.get(1).millisecond;

        let newDate = new Date(year + 
                               "-" + 
                               String(month).padStart(2,'0') +
                               "-" +
                               String(day).padStart(2,'0') + 
                               "T" + 
                               String(hour).padStart(2,'0') + 
                               ":" + 
                               String(minute).padStart(2,'0') + 
                               ":" + 
                               String(second).padStart(2,'0') + 
                               "." + 
                               String(millisecond).padStart(3,'0'));

        xMin = Math.abs(xMin);
        let myDate = newDate - xMin/1000 + i*xStep/1000;
        let thisDate = new Date(myDate);

        if(isNaN(thisDate)) {       
            window.sigApi.datapointManager.writeDataPoint('1:Schemevars1.DA_AlertTextScheme',5);    //message not implemented
            dispatchEvent(new CustomEvent("evtIsTimeAlertWindowOpen", {
                'detail': {
                    opened: this.wndApi.openWindow(0) /* this.wndApi.systemWindow_alert(this.timeAlertWindowText, this.timeAlertWindowCaption, 2) */
                }
            }));
        } else {
            if (DataRepository.getGeneralSettings().timeType == 1) {
                if (DataRepository.getGeneralSettings().timeFormat == 0) {
                    return String(thisDate.getDate()).padStart(2,'0') + 
                           "." + 
                           String(thisDate.getMonth()+1).padStart(2,'0') + 
                           "." + 
                           String(thisDate.getUTCFullYear()).padStart(2,'0') + 
                           " " + 
                           String(thisDate.getHours()).padStart(2,'0') + 
                           ":" + 
                           String(thisDate.getMinutes()).padStart(2,'0') + 
                           ":" + 
                           String(thisDate.getSeconds()).padStart(2,'0');
                } else if (DataRepository.getGeneralSettings().timeFormat == 1) {
                    return String(thisDate.getDate()).padStart(2,'0') + 
                           "." + 
                           String(thisDate.getMonth()+1).padStart(2,'0') + 
                           " " + 
                           String(thisDate.getHours()).padStart(2,'0') + 
                           ":" + 
                           String(thisDate.getMinutes()).padStart(2,'0') + 
                           ":" + 
                           String(thisDate.getSeconds()).padStart(2,'0');
                }    
            } else if (DataRepository.getGeneralSettings().timeType == 2) {
                if (DataRepository.getGeneralSettings().timeFormat == 0) {
                    return String(thisDate.getDate()).padStart(2,'0') + 
                           "." + 
                           String(thisDate.getMonth()+1).padStart(2,'0') + 
                           "." + 
                           String(thisDate.getUTCFullYear()).padStart(2,'0');
                } else if (DataRepository.getGeneralSettings().timeFormat == 1) {
                    return String(thisDate.getDate()).padStart(2,'0') + 
                           "." + 
                           String(thisDate.getMonth()+1).padStart(2,'0');
                }
            } else if (DataRepository.getGeneralSettings().timeType == 3){
                if (DataRepository.getGeneralSettings().timeFormat == 0) {
                    return String(thisDate.getHours()).padStart(2,'0') + 
                           ":" + 
                           String(thisDate.getMinutes()).padStart(2,'0') + 
                           ":" + 
                           String(thisDate.getSeconds()).padStart(2,'0');
                }
                else if (DataRepository.getGeneralSettings().timeFormat == 1) {
                    return String(thisDate.getHours()).padStart(2,'0') + 
                           ":" + 
                           String(thisDate.getMinutes()).padStart(2,'0');
                }
            }
        }        
    }

    drawXAxisTexts(stageContext, yAxis1Area_width, i, stepReal) {
        let x_offset = 0;
        if (i == 0) {
            x_offset = stageContext.measureText(this.XAxisTexts[i]).width / 2 + 3;
        }
        if (i == parseInt(this.gridlinesx)) {
            x_offset = stageContext.measureText(this.XAxisTexts[i]).width / 2 * (-1) - 3;
        }
        stageContext.fillText(this.XAxisTexts[i], yAxis1Area_width + i * stepReal + x_offset, 15);
    }
    
    changeXAxisLine(stageContext, drawingArea_width, yAxis1Area_width) {
        stageContext.moveTo(yAxis1Area_width, 0);
        stageContext.lineTo((drawingArea_width + yAxis1Area_width), 0);
    }

    drawYAxis(channel, textColor, font, redrawAxis, offsetLeft, offsetRight, d_c) {
        let step, stepReal, i, j, localMin, localMax, canvas, context;

        if (this.isdesignmode || this.smApi.isInOfflinePreview()) {
            if (channel.scaleSettings.axisPosition.toString().includes("left")) {
                canvas = this.$.canvas_yAxisArea1;
                context = canvas.getContext('2d');
            } else {
                canvas = this.$.canvas_yAxisArea2;
                context = canvas.getContext('2d');
            }
        } else {
            if (channel.scaleSettings.axisPosition.toString() == DataRepository.getYAxisEnum().left.toString()) {
                canvas = this.$.canvas_yAxisArea1;
                context = canvas.getContext('2d');
            } else {
                canvas = this.$.canvas_yAxisArea2;
                context = canvas.getContext('2d');
            }
        }

        localMin = channel.channelSettings.minValue;
        localMax = channel.channelSettings.maxValue;

        context.font = font;
        context.fillStyle = channel.channelSettings.lineColorString;
        context.textBaseline = 'top';
        let lineWidth = 10;

        if (channel != undefined) {
            let _canvClientWidth = this.$.osciCanvas.clientWidth;

            if (this.isdesignmode || this.smApi.isInOfflinePreview()) {
                if (!channel.scaleSettings.axisPosition.toString().includes("none")) {
                    if (!channel.scaleSettings.yAxisUnitPosition.toString().includes("hide")) { //if yAxisUnitPosition should be drawn, draw, otherwise skip                    
                        this.changeYAxisUnitPosition(channel.channelSettings.channelKey, 
                                                     channel.scaleSettings.axisPosition, 
                                                     channel.scaleSettings.yAxisUnitPosition, 
                                                     _canvClientWidth, 
                                                     lineWidth, 
                                                     channel);
                    }
                }
            } else {
                if (channel.scaleSettings.axisPosition != DataRepository.getYAxisEnum().none) {
                    if (channel.scaleSettings.yAxisUnitPosition != DataRepository.getYAxisPositionEnum().hide) { //if yAxisUnitPosition should be drawn, draw, otherwise skip                    
                        this.changeYAxisUnitPosition(channel.channelSettings.channelKey, 
                                                     channel.scaleSettings.axisPosition, 
                                                     channel.scaleSettings.yAxisUnitPosition,
                                                    _canvClientWidth, 
                                                    lineWidth, 
                                                    channel);
                    }
                }
            }
        }
        
        //MRSC die oberste y- Beschriftung
        context.textAlign = 'left';
        this.changeYAxisTextsPosition(context, 
                                      channel.scaleSettings.axisPosition, 
                                      canvas.width, 
                                      localMax, 
                                      redrawAxis, 
                                      lineWidth, 
                                      channel.channelSettings.channelKey);
        step = (localMax - localMin) / (parseInt(this.gridlinesy));
        stepReal = canvas.clientHeight / (parseInt(this.gridlinesy));
        //let stepRealText = canvas.clientHeight / (parseInt(this.gridlinesy));
        context.textBaseline = 'middle';
        
        //MRSC alle y - Beschriftungen außer die oberste
        for (i = 1; i <= (parseInt(this.gridlinesy)); i++) {
            this.changeYAxisMainTextPosition(context, 
                                             channel.scaleSettings.axisPosition,
                                             canvas.width, 
                                             localMax, 
                                             i, 
                                             step, 
                                             stepReal, 
                                             redrawAxis, 
                                             lineWidth, 
                                             channel);
        }
        
        context.beginPath();
        this.changeYAxisMainLinePosition(context, 
                                         channel.scaleSettings.axisPosition, 
                                         canvas.clientWidth, 
                                         canvas.clientHeight,
                                         redrawAxis);
        context.strokeStyle = getComputedStyle(this.$.canvas_xAxisArea).color;
        //context.strokeStyle = channel.channelSettings.lineColor;
        context.stroke();
        context.closePath();
        
        for (j = 0; j <= (parseInt(this.gridlinesy)); j++) {
            context.beginPath();
            this.changeYAxisLinesPosition(channel.scaleSettings.axisPosition, 
                                          canvas.clientWidth, 
                                          j, 
                                          stepReal, 
                                          context,
                                          redrawAxis);
            context.strokeStyle = getComputedStyle(this.$.canvas_xAxisArea).color;
            context.stroke();
            context.closePath();
        }               

        if ((channel.channelSettings.zeroLine == "Both" || 
             channel.channelSettings.zeroLine == "Triangle") && 
             channel.scaleSettings.yAxisActive) { //if triangle is chosen

            let minCountValue, maxCountValue;

            if (DataRepository.getUnits().size != 0 && channel.channelSettings.unit != undefined) {
                if (channel.channelSettings.unit.unit == undefined) {
                        minCountValue = channel.channelSettings.minValue;
                        maxCountValue = channel.channelSettings.maxValue;
                } else {
                    if (channel.channelSettings.unit.unit.formula == undefined) {
                        minCountValue = channel.channelSettings.unit.unit.formatValue(channel.channelSettings.minValue);
                        maxCountValue = channel.channelSettings.unit.unit.formatValue(channel.channelSettings.maxValue);
                    } else {
                        minCountValue = channel.channelSettings.unit.unit.formatValue(channel.channelSettings.unit.unit.convertValue(channel.channelSettings.minValue));
                        maxCountValue = channel.channelSettings.unit.unit.formatValue(channel.channelSettings.unit.unit.convertValue(channel.channelSettings.maxValue));
                    }
                }				
            } else {
                minCountValue = channel.channelSettings.minValue;
                maxCountValue = channel.channelSettings.maxValue;
            }

            if (maxCountValue >= 0 && minCountValue <= 0) {
                let k_c = canvas.height/(maxCountValue - minCountValue);
                let d_c = - (minCountValue * k_c);
                let yVal = canvas.height - ((k_c * 0) + d_c); //shortened formula for calculating zero position (canvas_height - (kc*0-dc))

                if (channel.scaleSettings.axisPosition == DataRepository.getYAxisEnum().right) {
                    context.beginPath();
                    context.fillStyle = channel.channelSettings.lineColorString;
                    context.moveTo(10, yVal - 5); // pick up "pen," reposition at 300 (horiz), 0 (vert)
                    context.lineTo(10, yVal + 5); // draw straight down (from 300,0) to 200px
                    context.lineTo(0, yVal); // draw up toward right (100 half of 200)
                    context.fill(); // connect and fill
                    context.closePath();
                }
                else if (channel.scaleSettings.axisPosition == DataRepository.getYAxisEnum().left) {
                    context.beginPath();
                    context.fillStyle = channel.channelSettings.lineColorString;
                    context.moveTo(canvas.width - 10, yVal - 5); // pick up "pen," reposition at 300 (horiz), 0 (vert)
                    context.lineTo(canvas.width - 10, yVal + 5); // draw straight down (from 300,0) to 200px
                    context.lineTo(canvas.width, yVal); // draw up toward right (100 half of 200)
                    context.fill(); // connect and fill
                    context.closePath();
                }
            }
        }
    }

    changeYAxisTextsPosition(stageContext, axisPosition, stageCanvas_Width, localMax, redrawAxis, lineWidth, channelKey) {
        let txt = localMax;
        let unit, parameterValues;
        let yAxisHeight = this.$.canvas_yAxisArea1.clientHeight;

        if (!redrawAxis) { 
            if (DataRepository.getUnits().size != 0) {
                unit = DataRepository.getChannelArray().get(channelKey).channelSettings.unit.unit;
                parameterValues = DataRepository.getChannelArray().get(channelKey).channelSettings.unit.unitValues;
            }
        }

        if (redrawAxis) {
            txt = "y" + (parseInt(this.gridlinesy)).toString();
        } else {
            if (DataRepository.getUnits().size != 0 && unit != undefined) {
                if (unit.formula == undefined) txt = unit.formatValue(txt).toString();
                else {
                    txt = unit.formatValue(unit.convertValue(txt));
                }
            } else txt = (Math.round(txt * this.roundingconst) / this.roundingconst).toFixed(2).toString();
        }

        let txt_width = stageContext.measureText(txt).width;
        let txt_height = parseInt(stageContext.font.match(/\d+/), 10);

        if (redrawAxis) {
            if (axisPosition == Symbol("right")) {
                stageContext.fillText(txt, this.MaxRight + lineWidth, yAxisHeight*0.0125);
                if ((lineWidth + txt_width + this.unitvalueconst) > this.actualMaxRight) {
                    this.actualMaxRight = lineWidth + txt_width + this.unitvalueconst;
                }
            } else if (axisPosition == Symbol("left")) {
                stageContext.fillText(txt, stageCanvas_Width - this.MaxLeft - txt_width - lineWidth, yAxisHeight*0.0125);
                if ((lineWidth + txt_width + this.unitvalueconst) > this.actualMaxLeft) {
                    this.actualMaxLeft = lineWidth + txt_width + this.unitvalueconst;
                }
            }
        } else {
            if (axisPosition == DataRepository.getYAxisEnum().right) {
                stageContext.fillText(txt, this.MaxRight + lineWidth, yAxisHeight*0.0125);
                if ((lineWidth + txt_width + this.unitvalueconst) > this.actualMaxRight) {
                    this.actualMaxRight = lineWidth + txt_width + this.unitvalueconst;
                }
            } else if (axisPosition == DataRepository.getYAxisEnum().left) {
                stageContext.fillText(txt, stageCanvas_Width - this.MaxLeft - txt_width - lineWidth, yAxisHeight*0.0125);
                if ((lineWidth + txt_width + this.unitvalueconst) > this.actualMaxLeft) {
                    this.actualMaxLeft = lineWidth + txt_width + this.unitvalueconst;
                }
            }
        }
    }

    changeYAxisMainTextPosition(stageContext, axisPosition, stageCanvas_Width, localMax, i, step, stepReal, redrawAxis, lineWidth, channel) {
        let txt = localMax - i * step;
        let offset_up = 0;
        let unit, parameterValues;
        
        if (!redrawAxis) { 
            if (DataRepository.getUnits().size != 0) {
                if (channel.channelSettings.unit == undefined) return;
                unit = channel.channelSettings.unit.unit;
                parameterValues = channel.channelSettings.unit.unitValues;
            }
        }

        if (redrawAxis) {
            let val = (parseInt(this.gridlinesy)) - i;
            txt = "y" + val;
        } else {
            if (DataRepository.getUnits().size != 0 && unit != undefined)
            {
                if (unit.formula == undefined) txt = (Math.round(txt * this.roundingconst) / this.roundingconst).toFixed(2).toString();
                else {
                    txt = unit.formatValue(unit.convertValue(txt));
                }
            } 
            else txt = (Math.round(txt * this.roundingconst) / this.roundingconst).toFixed(2).toString();
        }

        let txt_width = stageContext.measureText(txt).width;
        let txt_height = parseInt(stageContext.font.match(/\d+/), 10);

        if (i == (parseInt(this.gridlinesy))) {
            offset_up = txt_height / 2;
        }

        if (!redrawAxis) { 
            if (axisPosition == DataRepository.getYAxisEnum().right) {
                stageContext.fillStyle = channel.channelSettings.lineColorString;
                stageContext.fillText(txt, this.MaxRight + lineWidth, 0 + i * stepReal - offset_up);
                if ((lineWidth + txt_width + this.unitvalueconst) > this.actualMaxRight) {
                    this.actualMaxRight = lineWidth + txt_width + this.unitvalueconst;
                }
            } else if (axisPosition == DataRepository.getYAxisEnum().left) {
                stageContext.fillStyle = channel.channelSettings.lineColorString;
                stageContext.fillText(txt, stageCanvas_Width - this.MaxLeft - txt_width - lineWidth, 0 + i * stepReal - offset_up);
                if ((lineWidth + txt_width + this.unitvalueconst) > this.actualMaxLeft) {
                    this.actualMaxLeft = lineWidth + txt_width + this.unitvalueconst;
                }
            }
        } else {
            if (axisPosition.toString().includes("right")) {
                stageContext.fillStyle = channel.channelSettings.lineColorString;
                stageContext.fillText(txt, this.MaxRight + lineWidth, 0 + i * stepReal - offset_up);
                if ((lineWidth + txt_width + this.unitvalueconst) > this.actualMaxRight) {
                    this.actualMaxRight = lineWidth + txt_width + this.unitvalueconst;
                }
            } else if (axisPosition.toString().includes("left")) {
                stageContext.fillStyle = channel.channelSettings.lineColorString;
                stageContext.fillText(txt, stageCanvas_Width - this.MaxLeft - txt_width - lineWidth, 0 + i * stepReal - offset_up);
                if ((lineWidth + txt_width + this.unitvalueconst) > this.actualMaxLeft) {
                    this.actualMaxLeft = lineWidth + txt_width + this.unitvalueconst;
                }
            }
        }
    }

    changeYAxisMainLinePosition(stageContext, axisPosition, canv_ClientWidth, canv_ClientHeight, redrawAxis) {
        if (!redrawAxis) {
            if (axisPosition == DataRepository.getYAxisEnum().right) {
                stageContext.moveTo(this.MaxRight, 0);
                stageContext.lineTo(this.MaxRight, canv_ClientHeight);
            } else if (axisPosition == DataRepository.getYAxisEnum().left) {
                stageContext.moveTo(canv_ClientWidth - this.MaxLeft, 0);
                stageContext.lineTo(canv_ClientWidth - this.MaxLeft, canv_ClientHeight);
            }
        } else {
            if (axisPosition.toString().includes("right")) {
                stageContext.moveTo(this.MaxRight, 0);
                stageContext.lineTo(this.MaxRight, canv_ClientHeight);
            } else if (axisPosition.toString().includes("left")) {
                stageContext.moveTo(canv_ClientWidth - this.MaxLeft, 0);
                stageContext.lineTo(canv_ClientWidth - this.MaxLeft, canv_ClientHeight);
            }
        }
    }

    changeYAxisLinesPosition(axisPosition, canv_ClientWidth, j, stepReal, stageContext, redrawAxis) {
        let xContext = this.$.canvas_xAxisArea.getContext('2d');

        if (!redrawAxis) {
            if (axisPosition == DataRepository.getYAxisEnum().right) {
                if (j == (parseInt(this.gridlinesy))) {
                    xContext.beginPath();
                    let yAxisWidth = this.$.canvas_yAxisArea1.clientWidth;
                    let drawWidth = this.$.osciCanvas.clientWidth;
                    xContext.moveTo(yAxisWidth + drawWidth + this.MaxRight, 0);
                    xContext.lineTo(yAxisWidth + drawWidth + this.MaxRight + 10, 0);
                    xContext.strokeStyle = getComputedStyle(this.$.canvas_xAxisArea).color;
                    xContext.stroke();
                    xContext.closePath();
                } else {
                    stageContext.moveTo(0 + this.MaxRight, 0 + j * stepReal);
                    stageContext.lineTo(10 + this.MaxRight, 0 + j * stepReal);
                }
            } else if (axisPosition == DataRepository.getYAxisEnum().left) {
                if (j == (parseInt(this.gridlinesy))) {
                    xContext.beginPath();
                    xContext.moveTo(canv_ClientWidth - 10 - this.MaxLeft, 0);
                    xContext.lineTo(canv_ClientWidth - this.MaxLeft, 0);
                    xContext.strokeStyle = getComputedStyle(this.$.canvas_xAxisArea).color;
                    xContext.stroke();
                    xContext.closePath();
                } else {
                    stageContext.moveTo(canv_ClientWidth - 10 - this.MaxLeft, 0 + j * stepReal);
                    stageContext.lineTo(canv_ClientWidth - this.MaxLeft, 0 + j * stepReal);
                }
            }
        } else {
            if (axisPosition.toString().includes("right")) {
                if (j == (parseInt(this.gridlinesy))) {
                    xContext.beginPath();
                    let yAxisWidth = this.$.canvas_yAxisArea1.clientWidth;
                    let drawWidth = this.$.osciCanvas.clientWidth;
                    xContext.moveTo(yAxisWidth + drawWidth + this.MaxRight, 0);
                    xContext.lineTo(yAxisWidth + drawWidth + this.MaxRight + 10, 0);
                    xContext.strokeStyle = getComputedStyle(this.$.canvas_xAxisArea).color;
                    xContext.stroke();
                    xContext.closePath();
                } else {
                    stageContext.moveTo(0 + this.MaxRight, 0 + j * stepReal);
                    stageContext.lineTo(10 + this.MaxRight, 0 + j * stepReal);
                }
            } else if (axisPosition.toString().includes("left")) {
                if (j == (parseInt(this.gridlinesy))) {
                    xContext.beginPath();
                    xContext.moveTo(canv_ClientWidth - 10 - this.MaxLeft, 0);
                    xContext.lineTo(canv_ClientWidth - this.MaxLeft, 0);
                    xContext.strokeStyle = getComputedStyle(this.$.canvas_xAxisArea).color;
                    xContext.stroke();
                    xContext.closePath();
                } else {
                    stageContext.moveTo(canv_ClientWidth - 10 - this.MaxLeft, 0 + j * stepReal);
                    stageContext.lineTo(canv_ClientWidth - this.MaxLeft, 0 + j * stepReal);
                }
            }
        }
    }

    changeYAxisUnitPosition(channelKey, axisPosition, yAxisUnitPosition, canv_ClientWidth, lineWidth, channel) {
        if (!this.isdesignmode && !this.smApi.isInOfflinePreview()) {
            if (DataRepository.getUnits() != undefined) {
                if (DataRepository.getChannelArray().get(channelKey) == undefined) return;
                let unit = DataRepository.getChannelArray().get(channelKey).channelSettings.unit;
                if (unit != undefined) {
                    if (unit.unitName != undefined) {
                        let unitName = unit.unitText;
    
                        let txt_width;
                        let txt_height;
    
                        const unitDistance = 13; // with 7.5 the unit name is cut on the top
                        const corrFactor = 10;
    
                        if (axisPosition == DataRepository.getYAxisEnum().left) { //left
                            if (yAxisUnitPosition == DataRepository.getYAxisPositionEnum().top) {
                                let canvasTop = this.$.canvas_unitsArea;
                                let contextTop = canvasTop.getContext('2d');
    
                                txt_width = contextTop.measureText(unitName).width;
                                txt_height = parseInt(contextTop.font.match(/\d+/), 10);
    
                                contextTop.beginPath();
                                contextTop.textAlign = 'right';
                                contextTop.textBaseline = "middle"; 
                                contextTop.fillStyle = channel.channelSettings.lineColorString;
                                contextTop.fillText(unitName, this.$.canvas_yAxisArea1.clientWidth - this.MaxLeft - lineWidth - corrFactor, unitDistance);
                                contextTop.fill();
                                contextTop.closePath();
    
                                if ((lineWidth + txt_width + this.unitvalueconst) > this.actualMaxLeft) {
                                    this.actualMaxLeft = lineWidth + txt_width + this.unitvalueconst * 2;
                                }
                            } else {
                                let canvasX = this.$.canvas_xAxisArea;
                                let contextX = canvasX.getContext('2d');
    
                                txt_width = contextX.measureText(unitName).width;
                                txt_height = parseInt(contextX.font.match(/\d+/), 10);
    
                                contextX.beginPath();
                                contextX.textAlign = 'right';
                                contextX.fillStyle = channel.channelSettings.lineColorString;
                                contextX.fillText(unitName, this.$.canvas_yAxisArea1.clientWidth - this.MaxLeft - lineWidth - corrFactor, unitDistance);
                                contextX.fill();
                                contextX.closePath();
    
                                if ((lineWidth + txt_width + this.unitvalueconst) > this.actualMaxLeft) {
                                    this.actualMaxLeft = lineWidth + txt_width + this.unitvalueconst * 2;
                                }
                            }
                        } else { //right
                            if (yAxisUnitPosition == DataRepository.getYAxisPositionEnum().top) {
                                let canvasTop = this.$.canvas_unitsArea;
                                let contextTop = canvasTop.getContext('2d');
    
                                txt_width = contextTop.measureText(unitName).width;
                                txt_height = parseInt(contextTop.font.match(/\d+/), 10);
    
                                contextTop.beginPath();
                                contextTop.textAlign = 'left';
                                contextTop.textBaseline = "middle";
                                contextTop.fillStyle = channel.channelSettings.lineColorString;
                                contextTop.fillText(unitName, this.$.yAxisArea1.clientWidth + canv_ClientWidth + this.MaxRight + lineWidth, unitDistance);
                                contextTop.fill();
                                contextTop.closePath();
    
                                if ((lineWidth + txt_width + this.unitvalueconst) > this.actualMaxRight) {
                                    this.actualMaxRight = lineWidth + txt_width + this.unitvalueconst;
                                }
    
                            } else {
                                let canvasX = this.$.canvas_xAxisArea;
                                let contextX = canvasX.getContext('2d');
    
                                txt_width = contextX.measureText(unitName).width;
                                txt_height = parseInt(contextX.font.match(/\d+/), 10);
    
                                contextX.beginPath();
                                contextX.textAlign = 'left';
                                contextX.fillStyle = channel.channelSettings.lineColorString;
                                contextX.fillText(unitName, this.$.yAxisArea1.clientWidth + canv_ClientWidth + this.MaxRight + lineWidth, unitDistance);
                                contextX.fill();
                                contextX.closePath();
    
                                if ((lineWidth + txt_width + this.unitvalueconst) > this.actualMaxRight) {
                                    this.actualMaxRight = lineWidth + txt_width + this.unitvalueconst;
                                }
                            }
                        }
                    }
                }
            }
        }        
    }

    //function for redrawing cursor canvas
    _redrawCursorCanvas() {
        if (DataRepository.getCursorSettings().drawingHandler) {
            let canvas = this.$.cursorCanvas;
            let ctx = canvas.getContext('2d');
            ctx.canvas.width = this.$.drawingArea.clientWidth;
            ctx.canvas.height = this.$.drawingArea.clientHeight;
            ctx.font = getComputedStyle(this).fontSize + " " + getComputedStyle(this).fontFamily;

            requestAnimationFrame(function() {
                ctx.save();

                if (DataRepository.getCursorSettings().cursorX1) {
                    this._drawCursorX1(ctx, canvas);

                    if(DataRepository.getCursorSettings().werte == DataRepository.getLabelPositionEnum().left){      
                        this._drawValueX1Left(ctx,canvas);
                    }
    
                    if(DataRepository.getCursorSettings().werte == DataRepository.getLabelPositionEnum().right){
                        this._drawValueX1Right(ctx,canvas);
                    }
    
                    if(DataRepository.getCursorSettings().difference == DataRepository.getLabelPositionEnum().left){
                        this._drawDiffX1Left(ctx,canvas);
                    }
    
                    if(DataRepository.getCursorSettings().difference == DataRepository.getLabelPositionEnum().right){
                        this._drawDiffX1Right(ctx,canvas);
                    }
                }

                if (DataRepository.getCursorSettings().cursorX2) {
                    this._drawCursorX2(ctx, canvas);

                    if(DataRepository.getCursorSettings().werte == DataRepository.getLabelPositionEnum().left){      
                        this._drawValueX2Left(ctx,canvas);
                    }
    
                    if(DataRepository.getCursorSettings().werte == DataRepository.getLabelPositionEnum().right){
                        this._drawValueX2Right(ctx,canvas);
                    }
    
                    if(DataRepository.getCursorSettings().difference == DataRepository.getLabelPositionEnum().left){
                        this._drawDiffX2Left(ctx,canvas);
                    }
    
                    if(DataRepository.getCursorSettings().difference == DataRepository.getLabelPositionEnum().right){
                        this._drawDiffX2Right(ctx,canvas);
                    }
                }

                if (DataRepository.getCursorSettings().cursorY1 && 
                    DataRepository.getCursorSettings().ySelectedChannel != 0) {
                    this._drawCursorY1(ctx, canvas);
                }

                if (DataRepository.getCursorSettings().cursorY2 && 
                    DataRepository.getCursorSettings().ySelectedChannel != 0) {
                    this._drawCursorY2(ctx, canvas);
                }

                ctx.restore();
            }.bind(this));
        }
    }

    _drawCursorX1(ctx, canvas) {
        ctx.beginPath();
        ctx.moveTo(DataRepository.getCursorSettings().cursorX1_coor, 0);
        ctx.lineTo(DataRepository.getCursorSettings().cursorX1_coor, canvas.height);
        ctx.strokeStyle = this.cursorColors;
        ctx.lineWidth = 1;
        ctx.stroke();
        ctx.closePath();
    }

    _drawCursorX2(ctx, canvas) {
        ctx.beginPath();
        ctx.moveTo(DataRepository.getCursorSettings().cursorX2_coor, 0);
        ctx.lineTo(DataRepository.getCursorSettings().cursorX2_coor, canvas.height);
        ctx.strokeStyle = this.cursorColors;
        ctx.lineWidth = 1;
        ctx.stroke();
        ctx.closePath();
    }

    _drawCursorY1(ctx, canvas) {
        ctx.beginPath();
        ctx.moveTo(0, DataRepository.getCursorSettings().cursorY1_coor);
        ctx.lineTo(canvas.width, DataRepository.getCursorSettings().cursorY1_coor);
        ctx.strokeStyle = this.cursorColors;
        ctx.lineWidth = 1;
        ctx.stroke();
        ctx.closePath();
    }

    _drawCursorY2(ctx, canvas) {
        ctx.beginPath();
        ctx.moveTo(0, DataRepository.getCursorSettings().cursorY2_coor);
        ctx.lineTo(canvas.width, DataRepository.getCursorSettings().cursorY2_coor);
        ctx.strokeStyle = this.cursorColors;
        ctx.lineWidth = 1;
        ctx.stroke();
        ctx.closePath();
    }

    _drawValueX1Left(ctx,canvas){
        ctx.beginPath();
        let txt = DataRepository.getCursorValues().get(1).cursorX1Value;
        ctx.fillStyle = this.cursorColors;
        ctx.fillText(txt, (parseInt(DataRepository.getCursorSettings().cursorX1_coor)-parseInt(ctx.measureText(txt).width) - 15),  parseInt(ctx.font) + 10);
        ctx.closePath();
    }

    _drawValueX1Right(ctx,canvas){
        ctx.beginPath();
        let txt = DataRepository.getCursorValues().get(1).cursorX1Value;
        ctx.fillStyle = this.cursorColors;
        ctx.fillText(txt, (parseInt(DataRepository.getCursorSettings().cursorX1_coor) + 15), parseInt(ctx.font) + 10);
        ctx.closePath();
    }

    _drawValueX2Left(ctx,canvas){
        ctx.beginPath();
        let txt = DataRepository.getCursorValues().get(1).cursorX2Value;
        ctx.fillStyle = this.cursorColors;
        ctx.fillText(txt, (parseInt(DataRepository.getCursorSettings().cursorX2_coor)-parseInt(ctx.measureText(txt).width) - 15), canvas.height - parseInt(ctx.font) - 20);
        ctx.closePath();
    }

    _drawValueX2Right(ctx,canvas){
        ctx.beginPath();
        let txt = DataRepository.getCursorValues().get(1).cursorX2Value;
        ctx.fillStyle = this.cursorColors;
        ctx.fillText(txt, (parseInt(DataRepository.getCursorSettings().cursorX2_coor) + 15), canvas.height - parseInt(ctx.font) - 20);
        ctx.closePath();
    }

    _drawDiffX1Left(ctx,canvas){
        ctx.beginPath();
        let txt = DataRepository.getCursorValues().get(1).cursorXDiffValue == undefined ? "-" : DataRepository.getCursorValues().get(1).cursorXDiffValue;
        ctx.fillStyle = this.cursorColors;
        //console.log(parseInt(ctx.font));
        ctx.fillText(txt, (parseInt(DataRepository.getCursorSettings().cursorX1_coor) - parseInt(ctx.measureText(txt).width) - 15), (parseInt(ctx.font) + 30));
        ctx.closePath();
    }

    _drawDiffX1Right(ctx,canvas){
        ctx.beginPath();
        let txt = DataRepository.getCursorValues().get(1).cursorXDiffValue == undefined ? "-" : DataRepository.getCursorValues().get(1).cursorXDiffValue;
        ctx.fillStyle = this.cursorColors;
        ctx.fillText(txt, (parseInt(DataRepository.getCursorSettings().cursorX1_coor) + 15), parseInt(ctx.font) + 30);
        ctx.closePath();
    }
 
    _drawDiffX2Left(ctx,canvas){
        ctx.beginPath();
        let txt = DataRepository.getCursorValues().get(1).cursorXDiffValue == undefined ? "-" : DataRepository.getCursorValues().get(1).cursorXDiffValue;
        ctx.fillStyle = this.cursorColors;
        ctx.fillText(txt, (parseInt(DataRepository.getCursorSettings().cursorX2_coor) - parseInt(ctx.measureText(txt).width) - 15), canvas.height - 12);
        ctx.closePath();
    }

    _drawDiffX2Right(ctx,canvas){
        ctx.beginPath();
        let txt = DataRepository.getCursorValues().get(1).cursorXDiffValue == undefined ? "-" : DataRepository.getCursorValues().get(1).cursorXDiffValue;
        ctx.fillStyle = this.cursorColors;
        ctx.fillText(txt, (parseInt(DataRepository.getCursorSettings().cursorX2_coor) + 15), canvas.height - 12);
        ctx.closePath();
    }

    canvas_triangle(ctx, fromx, fromy, tox, toyupper, toylower){
        ctx.beginPath();
        ctx.moveTo(fromx, fromy);
        ctx.lineTo(tox, toyupper);
        ctx.lineTo(tox, toylower);
        ctx.closePath();
        ctx.fill();                                    
    }

    //check if the top canvas should be displayed (if units are drawn on the top once at least)
    _checkTopCanvas() {
        for (let [k, v] of DataRepository.getChannelArray()) {
            if (v.scaleSettings.yAxisUnitPosition == DataRepository.getYAxisPositionEnum().top) return true;                 
        }

        return false;
    }

    _arraySwap(arr) {
        let newArr = [];

        for (let i = arr.length-1; i >= 0; i--) {
            newArr.push(arr[i]);
        }

        return newArr; 
    }

    _bufferListener() {
        //console.log("_bufferListener");

        if (!this.done && JSManager.getRingBufferMapHist().size > 0) {
            //console.log("_bufferListener inside");

            this.frameRequest = window.requestAnimationFrame(this.testAnimation.bind(this)); //start loop with processing the data and canvas drawing
            this.done = true;
        }
    }

    _getChannelKeyMinSampleRate(bufferValuesHist, minSampleRate) {
        for (let [k, v] of bufferValuesHist) {
            if (v.sampRateArr == minSampleRate) return k;
        }

        return undefined;
    }

    testAnimation(timestamp) {
        if (this.timesHolder.startTime) {
            let newstart = performance.now();
            //console.log(newstart, this.timesHolder.startTime);         
            this.timesHolder.difference = newstart - this.timesHolder.startTime;
            this.timesHolder.startTime = newstart;            
        } else {
            this.timesHolder.startTime = performance.now();
            this.timesHolder.difference = 0;
        }

        let cycleTime = 0;

        if (!this.registerAck) {
            if (JSManager.getRegisterAck() == 1) {
                //console.log("good");
                this.registerAck = 1;
            }
        }

        if (this.registerAck) {        
            this.actualTime = performance.now();       
            //clear data handling
            if (JSManager.getCanvasDrawing()) { //&& Math.abs(this.actualTime - this.timeOfLastUpdate) > DaUserData.getUpdateTime()) { //Add Channels
                let bufferValuesHist = JSManager.getRingBufferMapHist();
                let bufferXConstVal = JSManager.getBufferXConst();
                let maxSampleRate = JSManager.getMaxSampleRate();
                let minSampleRate = JSManager.getMinSampleRate();
                let channelInfo = JSManager.getChannelInfo();
                //let channelVal = channelInfo.values().next().value;
                let channelKey = this._getChannelKeyMinSampleRate(channelInfo, minSampleRate);
                let channelVal = channelInfo.get(channelKey);

                if (bufferValuesHist.get(channelKey) != undefined) {
                    //console.log("we are here - undefined");
/*                     console.log("clear data error handling");
                    console.log("clear data - buffer values", bufferValuesHist); */
                    //Clear data error handling (if no data are available, then break)          

                    if (DataRepository.isDataLoaded() && bufferValuesHist.size != 0) {                   
                        //requestAnimationFrame(function() {
                        let textColor = getComputedStyle(this).color;
                        let predefineTextColor = '';
                        let fontSize = getComputedStyle(this).fontSize;
                        let fontFamily = getComputedStyle(this).fontFamily;
                        let font = fontSize + " " + fontFamily;
                        let canv = this.$.osciCanvas;
                        let ctx = canv.getContext('2d');

                        ctx.canvas.width = this.$.drawingArea.clientWidth;
                        ctx.canvas.height = this.$.drawingArea.clientHeight;
                        ctx.save();
                        ctx.imageSmoothingEnabled = false;
                        ctx.clearRect(0, 0, canv.width, canv.height);
                        ctx.beginPath();

                        let i, v;
                        let j, step, stepReal;
                        let leftYAxis = 0;
                        let rightYAxis = 0;

                        for (let [k, v] of DataRepository.getChannelArray()) {
                            if (DataRepository.getChannelArray().get(k).channelSettings.channelActive) {
                                if (DataRepository.getChannelArray().get(k).scaleSettings.axisPosition == DataRepository.getYAxisEnum().left) {
                                    leftYAxis++;
                                } else if (DataRepository.getChannelArray().get(k).scaleSettings.axisPosition == DataRepository.getYAxisEnum().right) {
                                    rightYAxis++;
                                }
                            }
                        }

                        this.$.yAxisArea1.style.width = this.MaxLeft + "px";
                        this.$.yAxisArea2.style.width = this.MaxRight + "px";
                        this.$.drawingArea.style.width = (this.$.container.clientWidth - this.MaxLeft - this.MaxRight) + "px";

    /*                     if (this.$.container.clientWidth == 0) {
                            window.cancelAnimationFrame(this.frameRequest);
                            return;
                        }  */

                        if ((this.MaxLeft + this.MaxRight) > this.$.container.clientWidth) {
                            //console.log("Error message");
                            if (DataRepository.getSelectedChannel() != "") {
                                /* this.wndApi.systemWindow_alert(this.alertNoSpaceText, this.alertNoSpaceCaption, 2);  */
                                window.sigApi.datapointManager.writeDataPoint('1:Schemevars1.DA_AlertTextScheme',6);
                                this.wndApi.openWindow(0);
                                DataRepository.setScaleSettingsYAxisActivated(false, DataRepository.getSelectedChannel());

                                dispatchEvent(new CustomEvent("evNoSpace_setYAxisInactive", { 'detail': {                              
                                        scaleSettings: DataRepository.getChannelArray().get(DataRepository.getSelectedChannel()).scaleSettings                        
                                    }                               
                                }));
                            }
                        }

                        /*if (this.$.yAxisArea1.clientWidth + this.$.yAxisArea2.clientWidth > this.$.drawingArea.clientWidth) {
                            if (DataRepository.getSelectedChannel() != "") {                                                  
                                this.wndApi.systemWindow_alert(this.alertNoSpaceText, this.alertNoSpaceCaption, 2);                      
                                DataRepository.setChannelInactive();                       
                            }
                        }*/

                        this.$.canvas_yAxisArea1.getContext('2d').canvas.width = this.$.yAxisArea1.clientWidth;
                        this.$.canvas_yAxisArea2.getContext('2d').canvas.width = this.$.yAxisArea2.clientWidth;
                        this.$.cursorCanvas.getContext('2d').canvas.width = this.$.drawingArea.clientWidth;
                        this.$.osciCanvas.getContext('2d').canvas.width = this.$.drawingArea.clientWidth;
                        
                        this.redrawGrid(false);
                        let startValue = 0;
                        let xValues = [];
                        let xPointer;
                        let xCapacity;
                        let xLength;
                        let xBuffValues = [];
                        let xMax = -1;
                        let xMin = -1;
                        let xMinGraphs = -1;
                        let xMaxGraphs = 0;
                        let xMaxMinGraphs, kxGraphs, dxGraphs;
                        let xMaxMin, xMaxMinAll, xMaxAll, xMinAll, k_x, d_x;
                        let oldx = 0;
                        let oldy = 0;
                        let min, max;
                        let offsetYleft = 0;
                        let offsetYright = 0;

                        let globalOverflow = false;

                        this.deleteYAxisCanvas();
                        this.MaxLeft = 0;
                        this.MaxRight = 0;
                        ctx.stroke();
                        ctx.closePath();

                        let xAxisScalingValue = DataRepository.getGeneralSettings().xScale * this.gridlinesx;
                        if((DataRepository.getZoomFactorValue() * JSManager.getMinSampleRate()) < xAxisScalingValue) { 
                            xAxisScalingValue -= (DataRepository.getZoomFactorValue() * JSManager.getMinSampleRate());
                        }
                        let globalStartValue, globalEndIndex, globalStartIndex, globalEndValue, xGlobalPointer, xGlobalLength, borderVal, firstBuffVal, xGlobalCapacity, xGlobalMax;
                        xGlobalPointer = bufferValuesHist.get(bufferXConstVal + minSampleRate).pointer;
                        xGlobalLength = bufferValuesHist.get(bufferXConstVal + minSampleRate).length;
                        xGlobalCapacity = bufferValuesHist.get(bufferXConstVal + minSampleRate).capacity;
                        xGlobalMax = bufferValuesHist.get(bufferXConstVal + minSampleRate).pointer != 0 ? bufferValuesHist.get(bufferXConstVal + minSampleRate).buffer[bufferValuesHist.get(bufferXConstVal + minSampleRate).pointer - 1]
                                                                                                        : bufferValuesHist.get(bufferXConstVal + minSampleRate).buffer[bufferValuesHist.get(bufferXConstVal + minSampleRate).length - 1];
                        //relative amount of values in percentage of the buffer which can be displayed on the graph
                        //(-1 because the first values in the buffer needs to be reached also)                                                                              
                        borderVal = (((xAxisScalingValue / minSampleRate)) / (xGlobalLength - 1)) * 100;
    /*                     console.log("borderVal", borderVal);
                        console.log("sliderVal", DataRepository.getSliderValue()); */
                                                                                                        //borderVal = (((xAxisScalingValue / minSampleRate) + 1) / (xGlobalLength - 1)) * 100;
                        //borderVal = (xAxisScalingValue / (minSampleRate * (xGlobalLength - 1))) * 100;

                        // --- slider boundaries --- ///
                        this.yLengthSlider = bufferValuesHist.get(channelKey).length;
                        this.ySampRateSlider = channelVal.sampRateArr;

                        //console.log("yLength", bufferValuesHist.get(channelKey).length);
                        //console.log("ySampRate", channelVal.sampRateArr);
                        //console.log("xAxisScalingValue", xAxisScalingValue);               

                        if ((this.yLengthSlider * this.ySampRateSlider) <= (xAxisScalingValue) + channelVal.sampRateArr) {
                            if (DataRepository.getGeneralSettings().rightToLeft == DataRepository.getRTLEnum().righttoleft) {
                                if (!this.$.sliderTest.disabled) {
                                    DataRepository.setSliderValue(100);
                                    this.$.sliderTest.value = 100;
                                    this.$.sliderTest.disabled = true;
                                }
                            } else {
                                if (!this.$.sliderTest.disabled) {
                                    DataRepository.setSliderValue(0);
                                    this.$.sliderTest.value = 0;
                                    this.$.sliderTest.disabled = true;
                                }
                            }
                        } else {
                            if (DataRepository.getGeneralSettings().rightToLeft == DataRepository.getRTLEnum().righttoleft) {
                                this.oldSliderRange = this.$.sliderTest.limitHigh;
                                this.oldSliderValue = this.$.sliderTest.value;

                                this.$.sliderTest.disabled = false;
                                //this.$.sliderTest.limitLow = ((xAxisScalingValue) / (this.yLengthSlider * this.ySampRateSlider)) * 100;
                                this.$.sliderTest.limitLow = 0;
                                //console.log("limitLow", ((xAxisScalingValue) / (this.yLengthSlider * this.ySampRateSlider)) * 100);
                                this.$.sliderTest.limitHigh = 100 - borderVal;
                            } else {
                                this.oldSliderRange = this.$.sliderTest.limitLow;
                                this.oldSliderValue = this.$.sliderTest.value;

                                this.$.sliderTest.disabled = false;
                                this.$.sliderTest.limitLow = borderVal;
                                //this.$.sliderTest.limitHigh = 100 - (((xAxisScalingValue) / (this.yLengthSlider * this.ySampRateSlider)) * 100);
                                this.$.sliderTest.limitHigh = 100;
                                //console.log("limitHigh", 100 - (((xAxisScalingValue) / (this.yLengthSlider * this.ySampRateSlider)) * 100));
                            }
                        }

                        //moving the slider, so it stays at the same position when the xAxisScalingValue is changed
                        if (DataRepository.getGeneralSettings().rightToLeft == DataRepository.getRTLEnum().righttoleft &&
                                this.oldSliderRange != this.$.sliderTest.limitHigh) {

                                    if (this.xAxisScalingValueBefore != 0 && this.xAxisScalingValueBefore != xAxisScalingValue) {
                                        let factor = this.xAxisScalingValueBefore / xAxisScalingValue;
                                        if (factor > 1.0) {
                                            let dist = (this.$.sliderTest.limitHigh - this.oldSliderRange) / 2;
                                            let newVal = parseFloat(this.$.sliderTest.value) + dist;
                                            if (newVal < this.$.sliderTest.limitLow) newVal = this.$.sliderTest.limitHigh;
                                            this.$.sliderTest.value = newVal;
                                            DataRepository.setSliderValue(this.$.sliderTest.value); 
                                        } else {
                                            let dist = (this.oldSliderRange - this.$.sliderTest.limitHigh) / 2;
                                            let newVal = parseFloat(this.$.sliderTest.value) - dist;
                                            if (newVal > this.$.sliderTest.limitHigh) newVal = this.$.sliderTest.limitHigh;
                                            this.$.sliderTest.value = newVal;
                                            DataRepository.setSliderValue(this.$.sliderTest.value); 
                                        }
                                    } else {
                                        let divisor = (100 - this.oldSliderRange);
                                        if (divisor == 0) divisor = 100;
                                        this.$.sliderTest.value = 100 - ((100 - this.oldSliderValue) / divisor * (100 - this.$.sliderTest.limitHigh));
                                        DataRepository.setSliderValue(this.$.sliderTest.value);
                                    }
                            } else if (DataRepository.getGeneralSettings().rightToLeft == DataRepository.getRTLEnum().lefttoright &&
                                this.oldSliderRange != this.$.sliderTest.limitLow) {
                                if (this.xAxisScalingValueBefore != 0 && this.xAxisScalingValueBefore != xAxisScalingValue) {
                                    let factor = this.xAxisScalingValueBefore / xAxisScalingValue;
                                    if (factor > 1.0) {
                                        let dist = (this.oldSliderRange - this.$.sliderTest.limitLow) / 2;
                                        let newVal = parseFloat(this.$.sliderTest.value) - dist;
                                        if (newVal < this.$.sliderTest.limitLow) newVal = this.$.sliderTest.limitLow;
                                        this.$.sliderTest.value = newVal;
                                        DataRepository.setSliderValue(this.$.sliderTest.value); 
                                    } else {
                                        let dist = (this.$.sliderTest.limitLow - this.oldSliderRange) / 2;
                                        let newVal = parseFloat(this.$.sliderTest.value) + dist;
                                        if (newVal > this.$.sliderTest.limitHigh) newVal = this.$.sliderTest.limitHigh;
                                        this.$.sliderTest.value = newVal;
                                        DataRepository.setSliderValue(this.$.sliderTest.value); 
                                    }
                                } else {
                                    if (this.oldSliderRange == 0) {
                                        this.$.sliderTest.value = this.$.sliderTest.limitLow;
                                    } else {
                                        this.$.sliderTest.value = this.oldSliderValue / this.oldSliderRange * this.$.sliderTest.limitLow;
                                    }
                                    DataRepository.setSliderValue(this.$.sliderTest.value);
                            }
                        }

                        if (this._checkTopCanvas()) { //check if top canvas should be displayed or hidden
                            this.$.unitsArea.style.height = '5%';
                            this.$.unitsArea.style.width = '100%';
                            this.$.canvas_unitsArea.width = this.$.unitsArea.clientWidth;
                            this.$.canvas_unitsArea.height = this.$.unitsArea.clientHeight;
                            this.$.canvas_unitsArea.getContext('2d').font = font;

                            this.$.stage.style.height = '75%';
                            this.$.canvas_yAxisArea1.height = this.$.yAxisArea1.clientHeight;
                            this.$.canvas_yAxisArea2.height = this.$.yAxisArea2.clientHeight;
                        } else {
                            this.$.unitsArea.style.height = '0%';
                            this.$.unitsArea.style.width = '100%';
                            this.$.canvas_unitsArea.width = this.$.unitsArea.clientWidth;
                            this.$.canvas_unitsArea.height = this.$.unitsArea.clientHeight;

                            this.$.stage.style.height = '80%';
                            this.$.canvas_yAxisArea1.height = this.$.yAxisArea1.clientHeight;
                            this.$.canvas_yAxisArea2.height = this.$.yAxisArea2.clientHeight;
                        }

                        //getting globalEndValue when the slider is points to the newest value in the buffer and the buffer is full
                        if ((DataRepository.getSliderValue() == 100 && 
                                    DataRepository.getGeneralSettings().rightToLeft == DataRepository.getRTLEnum().righttoleft) ||
                                    (DataRepository.getSliderValue() == 0 && DataRepository.getGeneralSettings().rightToLeft == DataRepository.getRTLEnum().lefttoright) ||
                                    (DataRepository.getSliderValue() <= borderVal && 
                                    DataRepository.getGeneralSettings().rightToLeft == DataRepository.getRTLEnum().lefttoright /* &&
                                    xGlobalCapacity == (xGlobalLength) */)  || 
                                    (DataRepository.getSliderValue() >= (100 - borderVal) && 
                                    DataRepository.getGeneralSettings().rightToLeft == DataRepository.getRTLEnum().righttoleft /* &&
                                    xGlobalCapacity == (xGlobalLength) */)) {
                            globalEndValue = (bufferValuesHist.get(bufferXConstVal + minSampleRate).pointer != 0) ? bufferValuesHist.get(bufferXConstVal + minSampleRate).buffer[bufferValuesHist.get(bufferXConstVal + minSampleRate).pointer - 1]
                                                                                                                : bufferValuesHist.get(bufferXConstVal + minSampleRate).buffer[bufferValuesHist.get(bufferXConstVal + minSampleRate).length - 1];


    /*                         console.log("globalEndValue", globalEndValue); */
                        } else {
                            //getting globalEndValue and globalStartValue when the slider is not pointing to the newest value in the buffer
                            if (DataRepository.getGeneralSettings().rightToLeft == DataRepository.getRTLEnum().righttoleft) {
                                if (xGlobalLength != xGlobalCapacity) {
                                    globalStartIndex = ((xGlobalLength - Math.ceil((bufferValuesHist.get(bufferXConstVal + minSampleRate).length) * ((100 - DataRepository.getSliderValue()) / 100))) + (xGlobalPointer - xGlobalLength) + xGlobalCapacity) % xGlobalCapacity;
                                    globalStartValue = bufferValuesHist.get(bufferXConstVal + minSampleRate).buffer[globalStartIndex];
                                } else {
                                    globalStartIndex = Math.ceil(((bufferValuesHist.get(bufferXConstVal + minSampleRate).length - 1) * ((100 - DataRepository.getSliderValue()) / 100)));
                                    globalStartValue = bufferValuesHist.get(bufferXConstVal + minSampleRate).buffer[((xGlobalLength - 1) - globalStartIndex + xGlobalPointer) % xGlobalLength];
                                }
                                
                                globalEndValue = globalStartValue + xAxisScalingValue;

                                //here cases with wrong sample rates has to be handled (problem with slider zero then)
                                if (xGlobalLength != xGlobalCapacity && globalEndValue > bufferValuesHist.get(bufferXConstVal + minSampleRate).buffer[xGlobalPointer - 1]) {
                                    globalEndValue = (bufferValuesHist.get(bufferXConstVal + minSampleRate).pointer != 0) ? bufferValuesHist.get(bufferXConstVal + minSampleRate).buffer[bufferValuesHist.get(bufferXConstVal + minSampleRate).pointer - 1]
                                                                                                                        : bufferValuesHist.get(bufferXConstVal + minSampleRate).buffer[bufferValuesHist.get(bufferXConstVal + minSampleRate).length - 1];

                                    globalOverflow = true;

    /*                                 console.log("globalOverflow"); */
                                }
    /* 
                                console.log("globalEndValue", globalEndValue);
                                console.log("globalStartIndex", globalStartIndex);
                                console.log("globalStartValue", globalStartValue);

                                console.log("xGlobalLength == xGlobalCapacity", xGlobalLength == xGlobalCapacity);  */
                            } else {
                                if (xGlobalLength != xGlobalCapacity) {
                                    globalStartIndex = ((xGlobalLength - Math.ceil((bufferValuesHist.get(bufferXConstVal + minSampleRate).length) * ((DataRepository.getSliderValue()) / 100))) + (xGlobalPointer - xGlobalLength) + xGlobalCapacity) % xGlobalCapacity;
                                    globalStartValue = bufferValuesHist.get(bufferXConstVal + minSampleRate).buffer[globalStartIndex];
                                    //globalStartValue = bufferValuesHist.get(bufferXConstVal + minSampleRate).buffer[((xGlobalLength - 1) - globalStartIndex + xGlobalPointer) % xGlobalLength + (bufferValuesHist.get(bufferXConstVal + minSampleRate).capacity - bufferValuesHist.get(bufferXConstVal + minSampleRate).length)];
                                } else {
                                    globalStartIndex = Math.ceil(((bufferValuesHist.get(bufferXConstVal + minSampleRate).length - 1) * (DataRepository.getSliderValue() / 100)));
                                    globalStartValue = bufferValuesHist.get(bufferXConstVal + minSampleRate).buffer[((xGlobalLength - 1) - globalStartIndex + xGlobalPointer) % xGlobalLength];
                                }
                                
                                globalEndValue = globalStartValue + xAxisScalingValue;

                                //here cases with wrong sample rates has to be handled
                                if (xGlobalLength != xGlobalCapacity && globalEndValue > bufferValuesHist.get(bufferXConstVal + minSampleRate).buffer[xGlobalPointer - 1]) {
                                    globalEndValue = (bufferValuesHist.get(bufferXConstVal + minSampleRate).pointer != 0) ? bufferValuesHist.get(bufferXConstVal + minSampleRate).buffer[bufferValuesHist.get(bufferXConstVal + minSampleRate).pointer - 1]
                                                                                                                        : bufferValuesHist.get(bufferXConstVal + minSampleRate).buffer[bufferValuesHist.get(bufferXConstVal + minSampleRate).length - 1];

                                    globalOverflow = true;

    /*                                 console.log("globalOverflow"); */
                                }

    /*                             console.log("globalEndValue", globalEndValue);
                                console.log("globalStartIndex", globalStartIndex);
                                console.log("globalStartValue", globalStartValue);

                                console.log("xGlobalLength == xGlobalCapacity", xGlobalLength == xGlobalCapacity); */
                            } 
                        }

                        //MRSC Kanäle durchlaufen
                        let start = performance.now();
                        
                        for (let [keyA, valuesA] of DataRepository.getChannelArray()) {
                            ctx.beginPath();
                            let xBufferSelected = [];
                            let yBufferSelected = [];

                            if (DataRepository.getChannelArray().get(keyA).channelSettings.channelActive) {
                                let yValues = [];
                                let yValuesToPush = [];
                                let yPointer;
                                let yCapacity;
                                let yLength;
                                let yBuffValues = [];
                                let sampRate;
                                xValues = [];
                                yCapacity = bufferValuesHist.get(keyA).capacity;
                                yLength = bufferValuesHist.get(keyA).length;

                                let afterIfElse = performance.now();

                                if ((DataRepository.getSliderValue() == 100 && 
                                DataRepository.getGeneralSettings().rightToLeft == DataRepository.getRTLEnum().righttoleft) ||
                                (DataRepository.getSliderValue() == 0 && 
                                DataRepository.getGeneralSettings().rightToLeft == DataRepository.getRTLEnum().lefttoright) ||
                                (DataRepository.getSliderValue() <= borderVal && 
                                DataRepository.getGeneralSettings().rightToLeft == DataRepository.getRTLEnum().lefttoright /* && 
                                yCapacity == yLength */) || 
                                (DataRepository.getSliderValue() >= (100 - borderVal) && 
                                DataRepository.getGeneralSettings().rightToLeft == DataRepository.getRTLEnum().righttoleft ||
                                globalOverflow /* &&
                                yCapacity == yLength */)) {
                                    yValues = bufferValuesHist.get(DataRepository.getChannelArray().get(keyA).channelSettings.channelKey).buffer;
                                    yPointer = bufferValuesHist.get(DataRepository.getChannelArray().get(keyA).channelSettings.channelKey).pointer;
                                    sampRate = channelInfo.get(keyA).sampRateArr;
                                    xValues = bufferValuesHist.get(bufferXConstVal + sampRate).buffer;
                                    xPointer = bufferValuesHist.get(bufferXConstVal + sampRate).pointer;
                                    if (xMin == -1) {
                                        //xPointer == 0 ? xMax = xValues[xValues.length - 1] : xMax = xValues[xPointer - 1];
                                        xMax = globalEndValue;
                                        let xStep = (((xAxisScalingValue)) / (parseInt(this.gridlinesx)));
                                        xMin = (xMax - (xStep * (parseInt(this.gridlinesx))));
                                        xMaxMin = xMax - xMin;
                                        k_x = ((canv.clientWidth) / xMaxMin); //calculating the constant for filling the canvas with max and min value
                                        d_x = -(xMin * k_x); //calculating the constant for filling the canvas with max and min value 
                                        xMaxGraphs = 0;
                                        xMinGraphs = (xMaxGraphs - (xStep * (parseInt(this.gridlinesx))));
                                        if (DaUserData.getExperimentalTestanimation()){
                                            if (DataRepository.getxAxisPropertieChanged()){
                                                this.drawXAxis(textColor, xMinGraphs, xMaxGraphs, xStep, font, false);
                                            }
                                        } else {
                                            this.drawXAxis(textColor, xMinGraphs, xMaxGraphs, xStep, font, false);
                                        }

    /*                                     console.log("xMin", xMin);
                                        console.log("xMaxMin", xMaxMin);
                                        console.log("xMax", xMax); */
                                    }
                                } else {
                                    //console.log(yBuffValues);
                                    yBuffValues = bufferValuesHist.get(keyA).buffer;
                                    yPointer = bufferValuesHist.get(keyA).pointer;
                                    sampRate = channelInfo.get(keyA).sampRateArr;
                                    xLength = bufferValuesHist.get(bufferXConstVal + sampRate).length;
                                    xBuffValues = bufferValuesHist.get(bufferXConstVal + sampRate).buffer;
                                    xPointer = bufferValuesHist.get(bufferXConstVal + sampRate).pointer;
                                    xCapacity = bufferValuesHist.get(bufferXConstVal + sampRate).capacity;

                                    let lastOverwrittenValueX = bufferValuesHist.get(bufferXConstVal + sampRate).lastOverwrittenValue;
                                    let lastOverwrittenValueY = bufferValuesHist.get(keyA).lastOverwrittenValue;

                                    //xValues.push(lastOverwrittenValueX);
                                    //yValuesToPush.push(lastOverwrittenValueY);
                                    //console.log("Push13",lastOverwrittenValueY);

                                    if (sampRate != JSManager.getMinSampleRate()) {
    /*                                     let endIndex = (xLength / xGlobalLength) * globalEndIndex;
                                        console.log("xLength", xLength);
                                        console.log("xGlobalLength", xGlobalLength);
                                        console.log("endIndex", globalEndIndex);

                                        let desiredIndexes = [Math.floor(endIndex), Math.floor(endIndex) + 1]; */

                                        let actualMinDistance = Number.MAX_VALUE;
                                        let realLocalEndIndex = -1;

                                        //temporary values used for cases with not enough values
                                        let tempMinDistance = Number.MAX_VALUE;
                                        let tempRealLocalEndIndex = -1;

                                        if (xCapacity != xLength && xLength > xPointer) {
                                            // console.log("case 1");
                                            for (let i = xCapacity - (xLength - xPointer); i < xCapacity; i++) {
                                                if (actualMinDistance > Math.abs(globalEndValue - xBuffValues[i]) &&  
                                                    globalEndValue <= xBuffValues[i]) {
                                                    actualMinDistance = Math.abs(globalEndValue - xBuffValues[i]);
                                                    realLocalEndIndex = i;
                                                }
                                            }

                                            for (let i = 0; i < xPointer; i++) {
                                                if (actualMinDistance > Math.abs(globalEndValue - xBuffValues[i]) &&  
                                                    globalEndValue <= xBuffValues[i]) {
                                                    actualMinDistance = Math.abs(globalEndValue - xBuffValues[i]);
                                                    realLocalEndIndex = i;
                                                }
                                            }
                                        } else {
                                            // console.log("case 2");
                                            for (let i = 0; i < xLength; i++) { //look for the nearest (nearest bigger) value/index which is closest/same to globalendvalue
                                                // console.log("actualMinDistance", Math.abs(globalEndValue - xBuffValues[i]));
                                                // console.log("actualMinDistance > Math.abs(globalEndValue - xBuffValues[i])", actualMinDistance > Math.abs(globalEndValue - xBuffValues[i]));
                                                // console.log("globalEndValue <= xBuffValues[i]",  globalEndValue <= xBuffValues[i]);
                                                // console.log("i", i);
                                                if (Math.abs(globalEndValue - xBuffValues[i]) < tempMinDistance) {
                                                    tempMinDistance = Math.abs(globalEndValue - xBuffValues[i]);
                                                    tempRealLocalEndIndex = i;
                                                }

                                                if (actualMinDistance > Math.abs(globalEndValue - xBuffValues[i]) &&  
                                                    globalEndValue <= xBuffValues[i]) {
                                                    actualMinDistance = Math.abs(globalEndValue - xBuffValues[i]);
                                                    realLocalEndIndex = i;
                                                }                                                  
                                            }
                                        }

                                        // console.log("realLocalEndIndex", realLocalEndIndex);

                                        // if (realLocalEndIndex == -1) {
                                        //     console.log("here");
                                        //     actualMinDistance = tempMinDistance;
                                        //     realLocalEndIndex = tempRealLocalEndIndex;
                                        //     console.log("here and here");

                                        //     console.log("tempMinDistance", tempMinDistance);
                                        //     console.log("realLocalEndIndex", realLocalEndIndex);
                                        //     console.log("tempRealLocalEndIndex", tempRealLocalEndIndex);
                                        // }

                                        // console.log("realLocalEndIndex", realLocalEndIndex);
                                        // console.log("globalEndValue", globalEndValue);

                                        let estimatedStartIndex;
                                        if (realLocalEndIndex != -1) {
                                            estimatedStartIndex = Math.round(realLocalEndIndex - (xAxisScalingValue / sampRate)); 
                                        } else {
                                            estimatedStartIndex = Math.round(tempRealLocalEndIndex - (xAxisScalingValue / sampRate)); 
                                        }
                                        let bufferEstStartIndex, correctedGlobalStartValue; 

                                        if (realLocalEndIndex == -1) {
                                            actualMinDistance = tempMinDistance;
                                            realLocalEndIndex = tempRealLocalEndIndex;
                                            correctedGlobalStartValue = globalStartValue + actualMinDistance;
                                            /* console.log("globalStartValue", globalStartValue);
                                            console.log("correctedGlobalStartValue", correctedGlobalStartValue);
                                            console.log("corrected Value", (globalStartValue + actualMinDistance)); */
                                        } else {
                                            correctedGlobalStartValue = globalStartValue;
                                        }
                                        
                                        // console.log("estimatedStartIndex", estimatedStartIndex);

                                        if (xCapacity != xLength && xLength > xPointer) {
                                            bufferEstStartIndex = (estimatedStartIndex + xCapacity) % xCapacity;
                                        } else {
                                            bufferEstStartIndex = (estimatedStartIndex + xLength) % xLength;
                                        } 

                                        // console.log("estimatedStartIndex", estimatedStartIndex);
                                        // console.log("bufferEstStartIndex", bufferEstStartIndex);

                                        let realLocalStartIndex;
                                        actualMinDistance = Number.MAX_VALUE;                                   
                                        
                                        //if the slower channels oldest value is bigger than the globalStartValue use the 
                                        //oldest value of the buffer as first xPoint
                                        if (globalStartValue < xBuffValues[xPointer]) {
                                            realLocalSttVartIndex = xPointer;                                                                                                                            
                                            xValues.push(lastOverwrittenValueX);                                   
                                            yValuesToPush.push(lastOverwrittenValueY);
                                            xValues.push(xBuffValues[xPointer]);                                   
                                            yValuesToPush.push(yBuffValues[xPointer]);
                                            // console.log("Push11",yBuffValues[xPointer], xBuffValues[xPointer],globalStartValue, xPointer, realLocalStartIndex);

                                            //console.log("i am here");
                                        } else {                
                                            //console.log("i am there");

                                            //there are three possibilities:
                                            //the value before the estimation is the closest to the globalStartValue
                                            if (xCapacity != xLength && xLength > xPointer) {
                                                if (xBuffValues[((bufferEstStartIndex + xCapacity - 1) % xCapacity)] <= correctedGlobalStartValue && 
                                                    actualMinDistance > Math.abs(xBuffValues[((bufferEstStartIndex + xCapacity - 1) % xCapacity)] - correctedGlobalStartValue)) {
                                                    realLocalStartIndex = ((bufferEstStartIndex + xCapacity - 1) % xCapacity);
                                                    actualMinDistance = Math.abs(xBuffValues[((bufferEstStartIndex + xCapacity - 1) % xCapacity)] - correctedGlobalStartValue);
                                                }
                                            } else {
                                                //console.log("case 1-1");

                                                if (xBuffValues[((bufferEstStartIndex + xLength - 1) % xLength)] <= correctedGlobalStartValue && 
                                                    actualMinDistance > Math.abs(xBuffValues[((bufferEstStartIndex + xLength - 1) % xLength)] - correctedGlobalStartValue)) {
                                                    realLocalStartIndex = ((bufferEstStartIndex + xLength - 1) % xLength);
                                                    actualMinDistance = Math.abs(xBuffValues[((bufferEstStartIndex + xLength - 1) % xLength)] - correctedGlobalStartValue);
                                                }
                                            }

                                            //the value of the estimation is the exactly the globalStartValue
                                            if (xBuffValues[bufferEstStartIndex] <= correctedGlobalStartValue && 
                                                actualMinDistance > Math.abs(xBuffValues[bufferEstStartIndex] - correctedGlobalStartValue)) {
                                                //console.log("case 1-2");            

                                                realLocalStartIndex = bufferEstStartIndex;
                                                actualMinDistance = Math.abs(xBuffValues[bufferEstStartIndex] - correctedGlobalStartValue);
                                            }

                                            if (xCapacity != xLength && xLength > xPointer) {
                                                //the value after the estimation is the exactly the globalStartValue
                                                if (xBuffValues[((bufferEstStartIndex + xCapacity + 1) % xCapacity)] <= correctedGlobalStartValue && 
                                                    actualMinDistance > Math.abs(xBuffValues[((bufferEstStartIndex + xCapacity + 1) % xCapacity)] - correctedGlobalStartValue)) {
                                                    realLocalStartIndex = ((bufferEstStartIndex + xCapacity + 1) % xCapacity);
                                                    actualMinDistance = Math.abs(xBuffValues[((bufferEstStartIndex + xCapacity + 1) % xCapacity)] - correctedGlobalStartValue);
                                                }
                                            } else {
                                                //the value after the estimation is the exactly the globalStartValue
                                                if (xBuffValues[((bufferEstStartIndex + xLength + 1) % xLength)] <= correctedGlobalStartValue && 
                                                    actualMinDistance > Math.abs(xBuffValues[((bufferEstStartIndex + xLength + 1) % xLength)] - correctedGlobalStartValue)) {

                                                    //console.log("case 1-3");
                                                    realLocalStartIndex = ((bufferEstStartIndex + xLength + 1) % xLength);
                                                    actualMinDistance = Math.abs(xBuffValues[((bufferEstStartIndex + xLength + 1) % xLength)] - correctedGlobalStartValue);
                                                }
                                            }

                                            realLocalStartIndex = realLocalStartIndex-1;
                                            //console.log("Real local start Index",realLocalStartIndex);
                                            //realLocalEndIndex = realLocalEndIndex-1;

                                            xValues.push(xBuffValues[realLocalStartIndex]);
                                            yValuesToPush.push(yBuffValues[realLocalStartIndex]);

                                            //console.log("realLocalStartIndex", realLocalStartIndex);

                                            if(xBuffValues[realLocalStartIndex] != globalStartValue) {
                                                let newYValue;
                                                
                                                if (xCapacity != xLength && xLength > xPointer) {
                                                    //interpolate
                                                    newYValue = this._lerp(yBuffValues[realLocalStartIndex], 
                                                        yBuffValues[(realLocalStartIndex + 1 + xCapacity) % xCapacity], 
                                                        (globalStartValue - xBuffValues[realLocalStartIndex]) / (xBuffValues[(realLocalStartIndex + 1 + xCapacity) % xCapacity] - xBuffValues[realLocalStartIndex]));
                                                } else {
                                                    //interpolate
                                                    newYValue = this._lerp(yBuffValues[realLocalStartIndex], 
                                                                        yBuffValues[(realLocalStartIndex + 1 + xLength) % xLength], 
                                                                        (globalStartValue - xBuffValues[realLocalStartIndex]) / (xBuffValues[(realLocalStartIndex + 1 + xLength) % xLength] - xBuffValues[realLocalStartIndex]));
                                                }
                                                //MRSC
                                                //xValues[0] = globalStartValue;
                                                //yValuesToPush[0] = newYValue;
                                            }
                                        }

                                        let i = 0;

                                        if (realLocalStartIndex > realLocalEndIndex) {
                                            for (i = realLocalStartIndex + 1; i < xBuffValues.length; i++) {
                                                xValues.push(xBuffValues[i]);
                                                yValuesToPush.push(yBuffValues[i]);
                                            }
                                            for (i = 0; i < realLocalEndIndex; i++) {
                                                xValues.push(xBuffValues[i]);
                                                yValuesToPush.push(yBuffValues[i]);
                                            }
                                        } else {
                                            for (i = realLocalStartIndex + 1; i < realLocalEndIndex; i++) {
                                                xValues.push(xBuffValues[i]);
                                                yValuesToPush.push(yBuffValues[i]);
                                            }
                                        }

                                        let idx; 
                                        if (xCapacity != xLength && xLength > xPointer) {
                                            idx = (i + xCapacity) % xCapacity;
                                        } else {
                                            idx = (i + xLength) % xLength;
                                        } 

                                        xValues.push(xBuffValues[idx]);
                                        yValuesToPush.push(yBuffValues[idx]);

                                        if(xBuffValues[idx] != globalEndValue) {
                                            //interpolate
                                            let newYValue;  
                                            if (xCapacity != xLength && xLength > xPointer) {
                                                newYValue = this._lerp(yBuffValues[idx], 
                                                                        yBuffValues[(idx - 1 + xCapacity) % xCapacity], 
                                                                        (globalEndValue - xBuffValues[idx]) / (xBuffValues[(idx - 1 + xCapacity) % xCapacity] - xBuffValues[idx]));
                                            } else {
                                                newYValue = this._lerp(yBuffValues[idx], 
                                                                        yBuffValues[(idx - 1 + xLength) % xLength], 
                                                                        (globalEndValue - xBuffValues[idx]) / (xBuffValues[(idx - 1 + xLength) % xLength] - xBuffValues[idx]));
                                            }   
                                            //MRSC
                                            //xValues[xValues.length - 1] = globalEndValue;
                                            //yValuesToPush[xValues.length - 1] = newYValue;
                                        }

                                        /* console.log(xValues);
                                        console.log(yValuesToPush);
    */
                                        // if (xValues.includes(NaN)) debugger;                           
                                        // if (yValuesToPush.includes(NaN)) debugger;
                                    } else {
                                        xValues.push(globalStartValue);
                                        let i;
                                        let pushedyIndex = [];

                                        if(xGlobalCapacity == xGlobalLength) {
                                            yValuesToPush.push(yBuffValues[(xGlobalLength - 1 - globalStartIndex + xPointer) % xLength]);

                                            //console.log("Push5",yBuffValues[(xGlobalLength - 1 - globalStartIndex + xPointer) % xLength]);
                                            
                                            //start from globalstartindex + 1
                                            i = (xGlobalLength - 1 - globalStartIndex + xPointer + 1) % xLength;
                                        } else {
                                            yValuesToPush.push(yBuffValues[globalStartIndex]);
                                            pushedyIndex.push(globalStartIndex);
                                            //start from globalstartindex + 1
                                            i = (globalStartIndex + 1) % xGlobalCapacity;
                                        }
                                        
                                        let breaked = false;

                                        //add values between global start value and global end value (excluding them)
                                        while (xBuffValues[i] < globalEndValue) {
                                            xValues.push(xBuffValues[i]);
                                            yValuesToPush.push(yBuffValues[i]);
                                            //console.log("Push3",yBuffValues[i]);

                                            if (xGlobalCapacity == xGlobalLength) {
                                                i = ((i + 1) % xLength);
                                            } else {
                                                i = ((i + 1) % xGlobalCapacity)
                                            }
                                            //globalEndValue is not in the buffer 
                                            //this is possible because the xScaling can be weird
                                            if (xGlobalCapacity == xGlobalLength) {
                                                if (xBuffValues[i] < xBuffValues[((i - 1) % xLength)]) {
                                                    breaked = true;
                                                    break;
                                                }
                                            } else {
                                                if (xBuffValues[i] < xBuffValues[((i - 1) % xGlobalCapacity)]) {
                                                    breaked = true;
                                                    break;
                                                }
                                            }

                                        }

                                        if (!breaked) {
                                            //add global end value or expected global end value
                                            xValues.push(xBuffValues[i]);
                                            yValuesToPush.push(yBuffValues[i]);
                                            //console.log("Push2",yBuffValues[i]);

                                            //if global end value is not on the last place of the values array, interpolate to get the global end value data
                                            if (xBuffValues[i] != globalEndValue) {
                                                let ihelp;
                                                if(xGlobalCapacity == xGlobalLength){
                                                    ihelp = xLength;
                                                } else {
                                                    ihelp = xGlobalCapacity;
                                                }

                                                let newYValue = this._lerp(yBuffValues[(i - 1 + ihelp) % ihelp],
                                                    yBuffValues[i],
                                                    (globalEndValue - xBuffValues[(i - 1 + ihelp) % ihelp]) / (xBuffValues[i] - xBuffValues[(i - 1 + ihelp) % ihelp]));

                                                xValues[xValues.length - 1] = globalEndValue;
                                                yValuesToPush[yValuesToPush.length - 1] = newYValue;
                                            }
                                        }
                                    }

                                    //console.log("after moving data", performance.now() - this.actualTime);

                                    xMinAll = xBuffValues[xPointer];
                                    xMaxAll = xBuffValues[xPointer - 1];
                                    xMaxGraphs = 0;
                                    xMinGraphs = -(xLength * sampRate);                             

                                    //let midVal = xPointer + endIndex; 
                                    let realEndIndex = xPointer + globalEndIndex; //real end value (consider the fact that all arrays in map are actually the ring buffers)

                                    if (realEndIndex >= xLength) {
                                        realEndIndex = realEndIndex - xLength;
                                    }

                                    let startArrIndex = realEndIndex - ((xAxisScalingValue) / sampRate);

                                    if (xMin == -1) {
                                        if ((DataRepository.getSliderValue() == 100 && 
                                            DataRepository.getGeneralSettings().rightToLeft == DataRepository.getRTLEnum().righttoleft) || 
                                            (DataRepository.getSliderValue() == 0 && DataRepository.getGeneralSettings().rightToLeft == DataRepository.getRTLEnum().lefttoright) ||
                                            (DataRepository.getSliderValue() <= borderVal && 
                                            DataRepository.getGeneralSettings().rightToLeft == DataRepository.getRTLEnum().lefttoright) /* &&
                                            yCapacity == yLength */ || 
                                            (DataRepository.getSliderValue() >= (100 - borderVal) && 
                                            DataRepository.getGeneralSettings().rightToLeft == DataRepository.getRTLEnum().righttoleft) /* &&
                                            yCapacity == yLength */ ||
                                            globalOverflow) {
                                            xPointer == 0 ? xMax = xValues[xValues.length - 1] : xMax = xValues[xPointer - 1];
                                        } else {
                                            //xPointer == 0 ? xMax = xValues[xValues.length - 1] : xMax = xValues[xPointer - 1];
                                            xMax = globalEndValue;
                                        }
                                        let xStep = ((xAxisScalingValue) / (parseInt(this.gridlinesx)));
                                        xMin = (xMax - (xStep * (parseInt(this.gridlinesx))));
                                        xMaxMin = xMax - xMin;
                                        k_x = (canv.clientWidth / xMaxMin); //calculating the constant for filling the canvas with max and min value
                                        d_x = -(xMin * k_x); //calculating the constant for filling the canvas with max and min value 

                                        if (DaUserData.getExperimentalTestanimation()) {
                                            if (DataRepository.getxAxisPropertieChanged()) {
                                                this.drawXAxis(textColor, xMin - xGlobalMax, xMax - xGlobalMax, xStep, font, false);
                                            }
                                        } else {
                                            this.drawXAxis(textColor, xMin - xGlobalMax, xMax - xGlobalMax, xStep, font, false);
                                        }

                                        // console.log("xMin", xMin);
                                        // console.log("xMax", xMax);
                                        // console.log("xMaxMin", xMaxMin); 
                                    }                             
                                }

                                let localMin = 0;
                                let localMax = 0;
                                localMin = DataRepository.getChannelArray().get(keyA).channelSettings.minValue;
                                localMax = DataRepository.getChannelArray().get(keyA).channelSettings.maxValue;

                                let maxmin = localMax - localMin;
                                let k_c = (canv.clientHeight / maxmin); //calculating the constant for filling the canvas with max and min value
                                let d_c = -(localMin * k_c); //calculating the constant for filling the canvas with max and min value
                                if (DaUserData.getExperimentalTestanimation()) {
                                    if (DataRepository.getyAxisPropertieChanged()) {
                                        this.actualMaxLeft = 0;
                                        this.actualMaxRight = 0;
                                        this.drawYAxis(DataRepository.getChannelArray().get(keyA), textColor, font, false, offsetYleft, offsetYright, d_c);
    /*                                     console.log("Test animation y1", this.$.canvas_yAxisArea1.width);
                                        console.log("Test animation y2", this.$.canvas_yAxisArea2.width); */
                                        this.MaxLeft = this.MaxLeft + this.actualMaxLeft;
                                        this.MaxRight = this.MaxRight + this.actualMaxRight;
                                        
                                    }
                                } else {
                                    this.actualMaxLeft = 0;
                                    this.actualMaxRight = 0;
                                    this.drawYAxis(DataRepository.getChannelArray().get(keyA), textColor, font, false, offsetYleft, offsetYright, d_c);
                                    this.MaxLeft = this.MaxLeft + this.actualMaxLeft;
                                    this.MaxRight = this.MaxRight + this.actualMaxRight;
                                }
                                
                                if (DataRepository.getChannelArray().get(keyA).scaleSettings.axisPosition == DataRepository.getYAxisEnum().right) {
                                    offsetYright = offsetYright + (this.$.container.clientWidth * 0.06);
                                } else if (DataRepository.getChannelArray().get(keyA).scaleSettings.axisPosition == DataRepository.getYAxisEnum().left) {
                                    offsetYleft = offsetYleft + (this.$.container.clientWidth * 0.06);
                                }

                                if ((DataRepository.getSliderValue() == 100 && 
                                    DataRepository.getGeneralSettings().rightToLeft == DataRepository.getRTLEnum().righttoleft) || 
                                    (DataRepository.getSliderValue() == 0 && DataRepository.getGeneralSettings().rightToLeft == DataRepository.getRTLEnum().lefttoright) ||
                                    (DataRepository.getSliderValue() <= borderVal && 
                                    DataRepository.getGeneralSettings().rightToLeft == DataRepository.getRTLEnum().lefttoright /* &&
                                    xGlobalCapacity == (xGlobalLength) */) || 
                                    (DataRepository.getSliderValue() >= (100 - borderVal) && 
                                    DataRepository.getGeneralSettings().rightToLeft == DataRepository.getRTLEnum().righttoleft /* &&
                                    xGlobalCapacity == (xGlobalLength) */) ||
                                    globalOverflow) {
                                        if (yPointer == 0) {
                                            //console.log("yPointer == 0");
                                            for (let b = 0; b < xValues.length; b++) {
                                                if (xValues[b] >= xMin) {
                                                    xBufferSelected.push(xValues[b]);
                                                    yBufferSelected.push(yValues[b]);
                                                } else if (b != xValues.length - 1) {
                                                    if (xValues[b] < xMin && xValues[b+1] > xMin) {
                                                        xBufferSelected.push(xMin);
                                                        yBufferSelected.push(this._lerp(yValues[b], yValues[b+1], JSManager.getMinSampleRate()/sampRate));
                                                    }
                                                }
                                            }

                                            // if (xBufferSelected.includes(NaN)) debugger;
                                
                                            // if (yBufferSelected.includes(NaN)) debugger;
                                        } else if (yLength != yCapacity) { //if yLength != yCapacity && yPointer is not zero
                                            //console.log("yLength != yCapacity");
                                            let udx = -1;
                                            let xHelper = [], yHelper = [];
                                            for (let b = xPointer - 1; b != -1; b--) {
                                                if (xValues[b] >= (globalEndValue - xAxisScalingValue)) { //push the values till the end
                                                    xHelper.push(xValues[b]);
                                                    yHelper.push(yValues[b]);
                                                } else { 
                                                    udx = b; //save index for later checking
                                                
                                                    if (xHelper[xHelper.length - 1] != (globalEndValue - xAxisScalingValue) && b != -1) { //if we have different sample rate (different multiples) than the xAxisScalingValue is set to
    /*                                                     console.log("xHelper", xHelper);
                                                        console.log("xHelper last val", xHelper[xHelper.length - 1]);
                                                        console.log("diff", (globalEndValue - xAxisScalingValue));
                                                        console.log("globalEndValue", globalEndValue);
                                                        console.log("xAxisScalingValue", xAxisScalingValue); */
                                                    
                                                        let lerpFracTop = (Math.abs(xHelper[xHelper.length - 1] - (globalEndValue - xAxisScalingValue)));
                                                        let lerpFracDown = (Math.abs(xValues[b] - xValues[b+1]));

    /*                                                     console.log("lerpFracTop", lerpFracTop);
                                                        console.log("lerpFracDown", lerpFracDown); */
                                                        
                                                        let lerpFrac = 1 - (lerpFracTop / lerpFracDown); //create fraction for interpolation

                                                        xHelper.push(this._lerp(xValues[b], xValues[b+1], lerpFrac));
                                                        yHelper.push(this._lerp(yValues[b], yValues[b+1], lerpFrac));
                                                    }

                                                    break;
                                                }
                                            }    

                                            if (udx == -1 && xValues.length != xHelper.length) { //if overflow is happening (we have also historical values, so indexes are coming from the end of the ringbuffer)
                                                for (let b = xValues.length-1; true; b--) {
                                                    if(xValues[b] == undefined) {
                                                        break;
                                                    }

                                                    if(xValues[b] >= (globalEndValue - xAxisScalingValue)) {  //push the values till the condition is ok
                                                        xHelper.push(xValues[b]);
                                                        yHelper.push(yValues[b]);
                                                    } else { 
                                                        udx = b; 

                                                        if (xHelper[xHelper.length - 1] != (globalEndValue - xAxisScalingValue)) {
                                                            let incrIndex = (b+1 != xValues.length) ? b+1 : 0; //if overflow is happening 

                                                            /* console.log("xHelper", xHelper);
                                                            console.log("xHelper last val", xHelper[xHelper.length - 1]);
                                                            console.log("diff", (globalEndValue - xAxisScalingValue));
                                                            console.log("globalEndValue", globalEndValue);
                                                            console.log("xAxisScalingValue", xAxisScalingValue); */

                                                            let lerpFracTop = (Math.abs(xHelper[xHelper.length - 1] - (globalEndValue - xAxisScalingValue)));
                                                            let lerpFracDown = (Math.abs(xValues[b] - xValues[incrIndex]));
    /* 
                                                            console.log("lerpFracTop", lerpFracTop);
                                                            console.log("lerpFracDown", lerpFracDown); */

                                                            let lerpFrac = 1 - (lerpFracTop / lerpFracDown);

                                                            xHelper.push(this._lerp(xValues[b], xValues[incrIndex], lerpFrac));
                                                            yHelper.push(this._lerp(yValues[b], yValues[incrIndex], lerpFrac));
                                                        }

                                                        break;
                                                    }   
                                                }
                                            }

                                            //swap the arrays (they are pushed in wrong direction)
                                            xBufferSelected = this._arraySwap(xHelper);
                                            yBufferSelected = this._arraySwap(yHelper);

                                            //pull request test

                                            // console.log("xBufferSelected", xBufferSelected);
                                            // console.log("yBufferSelected", yBufferSelected);

                                            // if (xBufferSelected.includes(NaN)) debugger;
                                
                                            // if (yBufferSelected.includes(NaN)) debugger;
                                        } else {
                                            // console.log("0 - case nr.3");

                                            let lerpRatio;

                                            for (let pn = yPointer; pn < yValues.length; pn++) {
                                                if (xValues[pn] >= xMin) {
                                                    xBufferSelected.push(xValues[pn]);
                                                    yBufferSelected.push(yValues[pn]);

                                                    if (sampRate == "500000") {
                                                        // console.log("xMin", xMin);
                                                        // console.log("xValues[pn]", xValues[pn]);
                                                        // console.log("yValues[pn]", yValues[pn]);
                                                    }
                                                } else if (pn != yValues.length - 1) {
                                                    if (xValues[pn] < xMin && xValues[pn+1] > xMin) {
                                                        lerpRatio = 1 - ((xValues[pn+1] - xMin) / sampRate); //calculating ratio for interpolating the oldest value 
                                                                                                                            //(difference between bigger value and minimum allowed value (calculated from "fastest" sample rate))
                                                                                                                            //divided by actual sample rate (resp. difference between two samples in buffer)

                                                        xBufferSelected.push(xMin);
                                                        // yBufferSelected.push(this._lerp(yValues[pn], yValues[pn+1], JSManager.getMinSampleRate()/sampRate));

                                                        yBufferSelected.push(this._lerp(yValues[pn], yValues[pn+1], lerpRatio));
                                                        // console.log("yValues[pn]", yValues[pn]);
                                                        // console.log("yValues[pn+1]", yValues[pn+1]);
                                                        // console.log("ratio for lerp", lerpRatio);
                                                        // console.log("lerp", this._lerp(yValues[pn], yValues[pn+1], lerpRatio));

                                                    }
                                                } else if (pn == yValues.length - 1) {
                                                    if (xValues[pn] < xMin && xValues[0] > xMin) {
                                                        lerpRatio = 1 - ((xValues[0] - xMin) / sampRate); //calculating ratio for interpolating the oldest value 
                                                        //(difference between bigger value and minimum allowed value (calculated from "fastest" sample rate))
                                                        //divided by actual sample rate (resp. difference between two samples in buffer)
                                                        //MRSC commented 2
                                                        xBufferSelected.push(xMin);
                                                        yBufferSelected.push(this._lerp(yValues[pn], yValues[0], lerpRatio));
                                                        // console.log("yValues[pn]", yValues[pn]);
                                                        // console.log("yValues[pn+1]", yValues[pn+1]);
                                                        // console.log("ratio for lerp", lerpRatio);
                                                        // console.log("lerp", this._lerp(yValues[pn], yValues[pn+1], lerpRatio));
                                                    }
                                                }
                                            }

                                            for (let pr = 0; pr < yPointer; pr++) {
                                                if (xValues[pr] >= xMin) {
                                                    xBufferSelected.push(xValues[pr]);
                                                    yBufferSelected.push(yValues[pr]);

                                                    if (sampRate == "500000") {
                                                        // console.log("xMin", xMin);
                                                        // console.log("xValues[pn]", xValues[pr]);
                                                        // console.log("yValues[pn]", yValues[pr]);
                                                    }
                                                } else if (pr != yValues.length - 1) {
                                                    if (xValues[pr] < xMin && xValues[pr+1] > xMin) {
                                                        lerpRatio = 1 - ((xValues[pr+1] - xMin) / sampRate); //calculating ratio for interpolating the oldest value 
                                                        //(difference between bigger value and minimum allowed value (calculated from "fastest" sample rate))
                                                        //divided by actual sample rate (resp. difference between two samples in buffer)

                                                        xBufferSelected.push(xMin);
                                                        yBufferSelected.push(this._lerp(yValues[pr], yValues[pr+1], lerpRatio));

                                                        // console.log("yValues[pr]", yValues[pr]);
                                                        // console.log("yValues[pr+1]", yValues[pr+1]);
                                                        // console.log("ratio for lerp", lerpRatio);
                                                        // console.log("lerp", this._lerp(yValues[pr], yValues[pr+1], lerpRatio));
                                                    }
                                                }
                                            }

                                            // console.log("xValues", xBufferSelected);
                                            // console.log("yValues", yBufferSelected);

                                        // if (xBufferSelected.includes(NaN)) debugger;
                                
                                        // if (yBufferSelected.includes(NaN)) debugger;
                                    }
                                } else {
                                    xBufferSelected = xValues;
                                    yBufferSelected = yValuesToPush;

                                    let diff = xBufferSelected[2] - xBufferSelected[1];
                                    xBufferSelected[0] = xBufferSelected[1] - diff;

                                    // console.log("xBufferSelected", xBufferSelected);
                                    // console.log("yBufferSelected", yBufferSelected);

                                    // if (xBufferSelected.includes(NaN)) debugger;                           
                                    // if (yBufferSelected.includes(NaN)) debugger;
                                }

                                //console.log("without drawing", performance.now() - this.actualTime);

                                // console.log("localMin", localMin);
                                // console.log("localMax", localMax);


                                // if (xBufferSelected.includes(NaN)) debugger;
                                
                                // if (yBufferSelected.includes(NaN)) debugger;
//MRSC
    /*                             console.log("xBufferSelected", xBufferSelected);
                                console.log("yBufferSelected", yBufferSelected); */

                                let noDrawCounter = 0;
                                let drawCounter = 0;

                                //MRSC zeichne Trigger mit kx + d
                                //Werte sollten allerdings richtig sein

                                this.timesHolder.oldforcycletime = this.timesHolder.forcycletime;
                                this.timesHolder.forcycletime = performance.now() - start;
                                let drawStart = performance.now();                           

                                //console.log("x Values",xBufferSelected);
                                //console.log("y Values",yBufferSelected);

                                let lifTime = performance.now();

                                for (let j = 0; j < xBufferSelected.length; j++) {
                                    //if (yBufferSelected[j] >= localMin && yBufferSelected[j] <= localMax) {                                                                    
                                    let x;
                                    if (DataRepository.getGeneralSettings().rightToLeft == DataRepository.getRTLEnum().righttoleft) {
                                        x = ((k_x * xBufferSelected[j]) + d_x);
                                    } else {
                                        x = canv.width - (((k_x * xBufferSelected[j]) + d_x));
                                    }

                                    let y = canv.height - ((k_c * yBufferSelected[j]) + d_c);                                  
                                    
                                    if ((j == 0) && (DataRepository.getTriggerRaisedInformation())) {
                                        ctx.moveTo(x, y);
                                    }
                                                         
                                    if (!this.correctValue) {
                                        ctx.moveTo(x, y);
                                        this.correctValue = true;
                                    }

                                    if ((Math.floor(x) != Math.floor(oldx)) || (Math.floor(y) != Math.floor(oldy))) {
                                        ctx.lineTo(x, y);
                                        oldx = x;
                                        oldy = y;
                                        drawCounter++;
                                    } else { //comment                  
                                        noDrawCounter += 1;
                                    }
                                    //oldx = x;
                                    //oldy = y;										

                                    if (j == xBufferSelected.length - 1) {
                                        ctx.strokeStyle = DataRepository.getChannelArray().get(keyA).channelSettings.lineColorString;
                                        ctx.lineWidth = DataRepository.getChannelArray().get(keyA).channelSettings.lineSize;
                                        if (DataRepository.getChannelArray().get(keyA).channelSettings.lineStyle == "Dash") {
                                            ctx.setLineDash([10, 10]);
                                        } else if (DataRepository.getChannelArray().get(keyA).channelSettings.lineStyle == "Dotted") {
                                            ctx.setLineDash([DataRepository.getChannelArray().get(keyA).channelSettings.lineSize, DataRepository.getChannelArray().get(keyA).channelSettings.lineSize]);
                                        } else {
                                            ctx.setLineDash([]);
                                        }
                                        ctx.stroke();
                                        ctx.closePath();
                                    }
                                }

                                //console.log("one drawing cycle", performance.now() - lifTime);
                                cycleTime += performance.now() - lifTime;

                                //console.log("DrawCounter", drawCounter, noDrawCounter);

                                if (DataRepository.getChannelArray().get(keyA).channelSettings.zeroLine == "Line" || 
                                    DataRepository.getChannelArray().get(keyA).channelSettings.zeroLine == "Both") {
                                    let minCountValue, maxCountValue;

                                    if (DataRepository.getUnits().size != 0 && DataRepository.getChannelArray().get(keyA).channelSettings.unit != undefined) {
                                        if (DataRepository.getChannelArray().get(keyA).channelSettings.unit.unit == undefined) {																													  
                                            minCountValue = DataRepository.getChannelArray().get(keyA).channelSettings.minValue;																																														  
                                            maxCountValue = DataRepository.getChannelArray().get(keyA).channelSettings.maxValue;										 
                                        } else {
                                            if (DataRepository.getChannelArray().get(keyA).channelSettings.unit.unit.formula == undefined) {
                                                minCountValue = DataRepository.getChannelArray().get(keyA).channelSettings.unit.unit.formatValue(DataRepository.getChannelArray().get(keyA).channelSettings.minValue);
                                                maxCountValue = DataRepository.getChannelArray().get(keyA).channelSettings.unit.unit.formatValue(DataRepository.getChannelArray().get(keyA).channelSettings.maxValue);
                                            } else {
                                                minCountValue = DataRepository.getChannelArray().get(keyA).channelSettings.unit.unit.formatValue(DataRepository.getChannelArray().get(keyA).channelSettings.unit.unit.convertValue(DataRepository.getChannelArray().get(keyA).channelSettings.minValue));
                                                maxCountValue = DataRepository.getChannelArray().get(keyA).channelSettings.unit.unit.formatValue(DataRepository.getChannelArray().get(keyA).channelSettings.unit.unit.convertValue(DataRepository.getChannelArray().get(keyA).channelSettings.maxValue));
                                            }
                                        }
                                    } else {
                                        minCountValue = DataRepository.getChannelArray().get(keyA).channelSettings.minValue;
                                        maxCountValue = DataRepository.getChannelArray().get(keyA).channelSettings.maxValue;									 
                                    } 

                                    if (maxCountValue >= 0 && minCountValue <= 0) {
                                        let k_c = canv.height/(maxCountValue - minCountValue);
                                        let d_c = - (minCountValue * k_c);
                                        let zeroVal = canv.height - ((k_c * 0) + d_c); //shortened formula for calculating zero position (canvas_height - (kc*0-dc))

                                        ctx.beginPath();

                                        ctx.moveTo(0, zeroVal);
                                        ctx.lineTo(canv.width, zeroVal);
                                        ctx.moveTo(oldx, oldy);

                                        ctx.strokeStyle = DataRepository.getChannelArray().get(keyA).channelSettings.lineColorString;
                                        ctx.lineWidth = DataRepository.getChannelArray().get(keyA).channelSettings.lineSize;
                                        if (DataRepository.getChannelArray().get(keyA).channelSettings.lineStyle == "Dash") {
                                            ctx.setLineDash([10, 10]);
                                        } else if (DataRepository.getChannelArray().get(keyA).channelSettings.lineStyle == "Dotted") {
                                            ctx.setLineDash([DataRepository.getChannelArray().get(keyA).channelSettings.lineSize, DataRepository.getChannelArray().get(keyA).channelSettings.lineSize]);
                                        } else {
                                            ctx.setLineDash([]);
                                        }
                                        ctx.stroke();
                                        ctx.closePath();
                                    }
                                }                          
                                this.timesHolder.drawing = performance.now() - drawStart;
                            
                            }
                        }

                        if (DataRepository.getTriggerRaisedInformation()) {                                    
                            //console.log("Trigger index", e);
                            //console.log("X Values", JSManager.getRingBufferMapHist().get("x2000000").buffer);

                            let triggerChannelNum = DataRepository.getTriggerRaisedInformation().channelNumber;
                            let bufferVals = JSManager.getRingBufferMapHist().get(JSManager.getBufferXConst() + DataRepository.getChannelArray().get(triggerChannelNum + 1).channelSettings.sampRate.toString());

                            //let triggerValue = JSManager.getRingBufferMapHist().get(JSManager.getBufferXConst() + DataRepository.getChannelArray().get(triggerChannelNum + 1).channelSettings.sampRate.toString()).buffer[e.firstIndex];

                            //let bufferCapacity = bufferVals.capacity;
                                                                   
                                                                       
                            let bufferLength = bufferVals.length;
                            let bufferCapacity = bufferVals.capacity;
                            let bufferPointer = bufferVals.pointer;
                            /*let bufferCapacity = JSManager.getRingBufferMapHist().get("x2000000").capacity;
                            let bufferLength = JSManager.getRingBufferMapHist().get("x2000000").length;
                            let bufferPointer = JSManager.getRingBufferMapHist().get("x2000000").pointer;*/

                            let triggerRealIndex;
                            //console.log("X",bufferLength, bufferCapacity);
                            //console.log("Buffer",bufferCapacity, bufferLength, bufferPointer);
                            if (bufferCapacity != bufferLength && bufferLength > bufferPointer) {
                                triggerRealIndex = (DataRepository.getTriggerRaisedInformation().firstIndex + bufferCapacity) % bufferCapacity;
                            } else {
                                triggerRealIndex = (DataRepository.getTriggerRaisedInformation().firstIndex + bufferCapacity) % bufferCapacity;
                            } 

                            //let triggerValue = JSManager.getRingBufferMapHist().get("x2000000").buffer[triggerRealIndex];
                            let triggerValue = JSManager.getRingBufferMapHist().get(JSManager.getBufferXConst() + DataRepository.getChannelArray().get(triggerChannelNum + 1).channelSettings.sampRate.toString()).buffer[triggerRealIndex];
                            //console.log("Trigger",triggerRealIndex, triggerValue);
                            let x = canv.width - (k_x*triggerValue + d_x);
                            
                            ctx.beginPath();
                            ctx.lineWidth = "2";
                            //ctx.strokeStyle = "green"; // Green path
                            ctx.strokeStyle = this.triggerPointColors;
                            ctx.fillStyle = this.triggerPointColors;
                            ctx.moveTo(x,0);
                            ctx.lineTo(x,canv.height);
                            ctx.stroke();
                            ctx.closePath;
                            ctx.beginPath();

                            if (x < 0) {
                                //canvas_arrow(ctx, 50, 30, 10, 30);
                                this.canvas_triangle(ctx, 10, 30, 30, 40, 20);
                            } else {
                                if (x > canv.width) {
                                    //canvas_arrow(ctx, canv.width - 50, 30, canv.width - 10 , 30);
                                    this.canvas_triangle(ctx, canv.width - 10, 30, canv.width - 30, 40, 20);
                                }
                            }
                            ctx.stroke();// Draw it

                            ctx.closePath;
                            //console.log(x);                                    
                        }

                        if (this.isCanvasCleared) {
                            this._clearOsciCanvas();
                            this.isCanvasCleared = false;
                        } 
                                
                        if(DaUserData.getExperimentalTestanimation()){
                            if(DataRepository.getyAxisPropertieChanged()){ 
                                DataRepository.setyAxisPropertieChanged(false);
                            }
            
                            if(DataRepository.getxAxisPropertieChanged()){
                                if(!this.firsttimedrawing){
                                    DataRepository.setxAxisPropertieChanged(false);
                                }
                                else this.firsttimedrawing = false;
                            }

                            if(DataRepository.getGridChanged()){
                                DataRepository.setGridChanged(false);
                            }
                        }
                        
                        this.xAxisScalingValueBefore = xAxisScalingValue;

                        if (JSManager.getOneShotAck) {
                            JSManager.setOneShotAck(false);
                        }
                        
                        ctx.restore();                
                    }

                    this.timeOfLastUpdate = performance.now();

                    this.frameRequest = window.requestAnimationFrame(this.testAnimation.bind(this));

                    if (DataRepository.getCursorSettings().drawingHandler) { //if drawing is stopped
                        //canvas drawing
                        this._redrawCursorCanvas();
                    }
                } else {
                    this.clearCanvas();
                    this.frameRequest = window.requestAnimationFrame(this.testAnimation.bind(this));
                }

                this.timesHolder.endtime = performance.now() - this.timesHolder.startTime;
                localStorage.setItem("timesArr", JSON.stringify(this.timesHolder));
            }    
        }
    }
}
window.customElements.define(LasalRuntimeSigDaGraphs.is, LasalRuntimeSigDaGraphs);
