const net  = require("net");
const { resolve } = require("path");
const { TelnetSocket } = require("telnet-stream");



module.exports = class TelnetSenderGRBL{

    /*  urlGRBL:  URL für den GCode Empfänger (MicroController, GRBL)
     *  xAxisGrbl: Welche Achse soll ausgelesen werden? Welche Achse ist die GRBL-X-Achse
     *  yAxisGrbl: ...
     *  zAxisGrbl: ... 
     */
    constructor(urlGRBL = "grblesp.local", maxSpeedF = 5000, xAxisGrbl = "x", yAxisGrbl = "y", zAxisGrbl = "z", aAxisGrbl = null, bAxisGrbl = null, cAxisGrbl = null, eAxisGrbl = null){

        var socket = null;
        this.tSocket = null;
        this.receiver = null;

        this.urlGRBLstr = urlGRBL;
        this.xAxisGrbl = xAxisGrbl;
        this.yAxisGrbl = yAxisGrbl;
        this.zAxisGrbl = zAxisGrbl;
        this.aAxisGrbl = aAxisGrbl;
        this.bAxisGrbl = bAxisGrbl;
        this.cAxisGrbl = cAxisGrbl;
        this.eAxisGrbl = eAxisGrbl;
        


        new Promise((resolve, reject) => {
            socket = net.createConnection({port: 23, host: urlGRBL},() => {
                resolve(socket);
            })
            .on('error', reject);
        }).then( connection => {
            connection.on('data', data => {
                //console.log("data from " + urlGRBL + " is: " + data);
                //if(this.receiver && this.receiver != null){
                //  this.receiver.send(buffer);
                // }
            });
        }, error => {   
            console.log("Telnet Connection Error on " + urlGRBL + ": " + error.toString());
            this.tSocket = null;
        }); 
        

        if(socket != null){
            this.tSocket = new TelnetSocket(socket);
       
            this.tSocket.on("close", function () {
                console.log("Telnet Closed " + urlGRBL);
                this.tSocket = null;
            }); 
        }

    }
    
    

    moveTo(mOld, mNew){

        // The Hand-Turn is not 1:1 to the Hand-Lift °     
        var factorTurnLift = 1.2;

        // The Hand-Open is not 1:1 to the Hand-Turn 
        var factorOpenTurn = 1.92;

        // Hand-Open in mm
        var handOpenInMM = 1.0

        var data = "G1" 

        if(this.xAxisGrbl == "x"){
            data += " x" + (mNew.x).toFixed(2).toString();
        }
        if(this.xAxisGrbl == "y"){
            data += " x" + (mNew.y * 180 / Math.PI).toFixed(2).toString();
        }
        if(this.xAxisGrbl == "z"){
            data += " x" + ((mNew.z * 180 / Math.PI) - (mNew.y * 180 / Math.PI) ).toFixed(2).toString();
        }
        if(this.xAxisGrbl == "a"){
            // This is the case for the Ellbow, when the Motor is connected to the X-Port of the FluidNC
            data += " x" + (mNew.a * 180 / Math.PI).toFixed(2).toString();
        }
        if(this.xAxisGrbl == "b"){ 
            data += " x" + (mNew.b * 180 / Math.PI+(mNew.z * 180 / Math.PI) - (mNew.y * 180 / Math.PI)).toFixed(2).toString();
        }
        if(this.xAxisGrbl == "c"){
            // Runs correctly, substracts the "b" axis, uses the "c" axis to send to the x-Motor wich is in this case the hand-twist
            data += " x" + ((-1)*mNew.b * 180 / Math.PI + (mNew.c * 180 / Math.PI) ).toFixed(2).toString();
        }
        if(this.xAxisGrbl == "e"){
            //This is the case for the Hand, when the Open-Close Motor is connected to the X-Port of FluidNC
            var handUpDown = mNew.b * 180 * factorTurnLift / Math.PI ;
            var handTurn =   mNew.c*180/Math.PI  ;
            data += " x" + ((-1.0*(-1.0*(handUpDown) + handTurn) + mNew.e*handOpenInMM)).toFixed(2).toString();
        }

        

        if(this.yAxisGrbl == "x"){
            data += " y" + (mNew.x ).toFixed(2).toString();
        }
        if(this.yAxisGrbl == "y"){
            data += " y" + (mNew.y * 180 / Math.PI).toFixed(2).toString();
        }
        if(this.yAxisGrbl == "z"){
            data += " y" + ((mNew.z * 180 / Math.PI) - (mNew.y * 180 / Math.PI) ).toFixed(2).toString();
        }
        if(this.yAxisGrbl == "a"){
            data += " y" + (mNew.a * 180 / Math.PI).toFixed(2).toString();
        }
        if(this.yAxisGrbl == "b"){
            data += " y" + (mNew.b * 180 / Math.PI+(mNew.z * 180 / Math.PI) - (mNew.y * 180 / Math.PI)).toFixed(2).toString();
        }
        if(this.yAxisGrbl == "c"){
            // This is the case if the hand-rotation-turner is connected to the FluidNC-Y
            var handUpDown = (mNew.b * 180 / Math.PI ) * factorTurnLift;
            var handTurn =  ( mNew.c*180/Math.PI ) ;
            data += " y" + (-1.0*(handUpDown) + handTurn).toFixed(2).toString();
        }
        if(this.yAxisGrbl == "e"){
            data += " y" + (mNew.e * 180 / Math.PI).toFixed(2).toString();
        }


        if(this.zAxisGrbl == "x"){
            data += " z" + (mNew.x).toFixed(2).toString();
        }
        if(this.zAxisGrbl == "y"){
            data += " z" + (mNew.y * 180 / Math.PI).toFixed(2).toString();
        }
        if(this.zAxisGrbl == "z"){
            data += " z" + ((mNew.z * 180 / Math.PI)  - (mNew.y * 180 / Math.PI) ).toFixed(2).toString();
        }
        if(this.zAxisGrbl == "a"){
            data += " z" + (mNew.a * 180 / Math.PI).toFixed(2).toString();
        }
        if(this.zAxisGrbl == "b"){
            // This is the case of the Hand, when the Up-Down-Motor is connected to the FluidNC-Z
            data += " z" +  ( mNew.b * 180 / Math.PI ).toFixed(2).toString();
        }
        if(this.zAxisGrbl == "c"){
            data += " z" + (mNew.c * 180 / Math.PI + (mNew.b * 180 / Math.PI) + (mNew.z * 180 / Math.PI) - (mNew.y * 180 / Math.PI)).toFixed(2).toString();
        }
        if(this.zAxisGrbl == "e"){
        
            data += " z" + (mNew.e * 180 / Math.PI).toFixed(2).toString();
        }


             
        if(this.aAxisGrbl == "x"){
            data += " a" + (mNew.y * 180 / Math.PI).toFixed(2).toString();
        }
        if(this.aAxisGrbl == "y"){
            data += " a" + (mNew.y * 180 / Math.PI).toFixed(2).toString();
        }
        if(this.aAxisGrbl == "z"){
            data += " a" + ((mNew.z * 180 / Math.PI)  - (mNew.y * 180 / Math.PI) ).toFixed(2).toString();
        }
        if(this.aAxisGrbl == "a"){
            data += " a" + (mNew.a * 180 / Math.PI).toFixed(2).toString();
        }
        if(this.aAxisGrbl == "b"){
            data += " a" +  (mNew.b * 180 / Math.PI+(mNew.z * 180 / Math.PI) - (mNew.y * 180 / Math.PI)).toFixed(2).toString();
        }
        if(this.aAxisGrbl == "c"){
            data += " a" + (mNew.c * 180 / Math.PI + (mNew.b * 180 / Math.PI) + (mNew.z * 180 / Math.PI) - (mNew.y * 180 / Math.PI)).toFixed(2).toString();
        }
        if(this.aAxisGrbl == "e"){
            // ToDo Mai 2024
            data += " a" + (mNew.e * 180 / Math.PI).toFixed(2).toString();
        }
    
        


        if(this.bAxisGrbl == "x"){
            data += " b" + (mNew.x).toFixed(2).toString();
        }
        if(this.bAxisGrbl == "y"){
            data += " b" + (mNew.y * 180 / Math.PI).toFixed(2).toString();
        }
        if(this.bAxisGrbl == "z"){
            data += " b" + ((mNew.z * 180 / Math.PI)  - (mNew.y * 180 / Math.PI) ).toFixed(2).toString();
        }
        if(this.bAxisGrbl == "a"){
            data += " b" + (mNew.a * 180 / Math.PI).toFixed(2).toString();
        }
        if(this.bAxisGrbl == "b"){
            data += " b" + (mNew.b * 180 / Math.PI).toFixed(2).toString();
        }
        if(this.bAxisGrbl == "c"){
            data += " b" + (mNew.c * 180 / Math.PI + (mNew.b * 180 / Math.PI) + (mNew.z * 180 / Math.PI) - (mNew.y * 180 / Math.PI)).toFixed(2).toString();
        }
        if(this.bAxisGrbl == "e"){
            data += " b" + (mNew.e * 180 / Math.PI).toFixed(2).toString();
        }

        data += " f"+(maxSpeedF.toFixed(2).toString())


        console.log("" + this.urlGRBLstr + " receives: " + data.toString("utf-8"))
    
        if(this.tSocket && data.toString("utf-8").length > 3){
            this.tSocket.write( data.toString("utf-8") + "\r\n"); 
        }
    } 
}