
/*********************************************************************
 **
 **   server/appx-client-localos.js - Client local OS interface
 **
 **   This module contains code to process local OS requests
 **
 *********************************************************************/

// what_str =  "@(#)Appx $Header: /src/cvs/appxHtml5/server/appx-client-localos.js,v 1.45 2016/06/15 19:29:11 jnelson Exp $";
function appxIsLocalReady() {
    return (localos_session && localos_session.ws.readyState == 1)
}

//File Message Handler
//SENDING A File from the SERVER to the CLIENT(client receive)
//Server is telling client to save a file locally
function appxsendfilehandler(x) {
    if (appxIsLocalReady()) {
        switch (x.messagepart) {
            case -1:
                var msgfilenamedata = [];
                var filepath = appx_session.currsendfile.filename;
                appxClearStatusMsgText();
                appxSetStatusText("Saving File...");
                appx_session.currsendfile.filedata = [];
                setTimeout(function () {
                    //send client file path length
                    var ms = {
                        cmd: 'appxmessage',
                        args: [0, 0, 0, filepath.length],
                        handler: 'appxsendfilehandler',
                        data: null
                    };
                    appx_session.ws.send(JSON.stringify(ms));
                    //send client file path
                    for (var vi = 0; vi < filepath.length; vi++) {
                        msgfilenamedata.push(filepath.charCodeAt(vi));
                    }
                    var ms = {
                        cmd: 'appxmessage',
                        args: msgfilenamedata,
                        handler: 'appxsendfilehandler',
                        data: null
                    };
                    appx_session.ws.send(JSON.stringify(ms));
                    //send client status EOF
                    var ms = {
                        cmd: 'appxmessage',
                        args: [3, 1],
                        handler: 'appxsendfilehandler',
                        data: null
                    };
                    appx_session.ws.send(JSON.stringify(ms));
                    appxClearStatusMsgText();
                    appxSetStatusText("File Download Complete...");
                    setTimeout(function () {
			if($("#appx-status-msg").html() === "File Download Complete..."){
                            appxClearStatusMsgText();
			}
                    }, 1000);
                }, appx_session.currsendfile.blocksreceived * 1); //end setTimeout

                break;
            case 3:
                appx_session.currsendfile.filename = x.data.filename;
                appx_session.currsendfile.guid = Math.floor((Math.random() * 1000000) + 1);
                appx_session.currsendfile.filedatareceived = 0;
                appx_session.currsendfile.blocksreceived = 0;
                appx_session.currsendfile.datalengthneeded = x.data.datalength;
                if (appx_session.currsendfile.filename.indexOf("$(") > -1) {
                    appx_session.currsendfile.filename = appx_session.parseOption(appx_session.currsendfile.filename);
                }
                else {
                    appx_session.currsendfile.filename = appx_session.currsendfile.filename;
                }
                if (appx_session.currsendfile.filename.indexOf("/") == -1 && appx_session.currsendfile.filename.indexOf("\\") == -1) {
                    appx_session.currsendfile.filename = appx_session.parseOption("$(userHome)" + appx_session.fileseparatorchar + appx_session.currsendfile.filename);
                }
                appxClearStatusMsgText();
                appxSetStatusText("Creating File:  " + appx_session.currsendfile.filename);
                appx_session.currsendfile.filecreated = false;
                CreateFile(appx_session.currsendfile);
                setTimeout(function () {
                    //send client status for filename
                    var ms = {
                        cmd: 'appxmessage',
                        args: [3, 1],
                        handler: 'appxsendfilehandler',
                        data: null
                    };
                    appx_session.ws.send(JSON.stringify(ms));
                }, 1000);
                break;
            case 5:
		 appx_session.currsendfile.blocksreceived += 1;
                 appx_session.currsendfile.filedatareceived += x.data.length;
                 appxClearStatusMsgText();
                 appxSetStatusText("File Downloading... Received:  " + appx_session.currsendfile.filedatareceived + " Bytes of " + appx_session.currsendfile.datalengthneeded.toString() + " Needed");
		 
		 AppendFile(x.data);
                 break;

             default:
                 //append data to file via local connector
                 break;
        }
    }
    else {
        //send client status EOF
	if (x.messagepart != -1){
	    var ms = {
		cmd: 'appxmessage',
		args: [0, 0],
		handler: 'appxsendfilehandler',
		data: null
            };
            appx_session.ws.send(JSON.stringify(ms));
	}
    }
}

// SET CLIPBOARD Handler
function appxsetclipboardhandler(x) {
    var clipboardobj = x.data;
    if (appxIsLocalReady()) {
        console.log("Setting Clipboard Data:  " + clipboardobj.data);
        ms = {
            cmd: 'setclipboard',
            args: [clipboardobj.data],
            handler: 'localos_setclipboard_handler',
            data: null
        };
        localos_session.ws.send(JSON.stringify(ms));
    }
    else {
        alert("You must have access to your local OS to set the clipboard:  " + clipboardobj.data);
    }
}

// GET CLIPBOARD Handler
function appxgetclipboardhandler(x) {
    if (appxIsLocalReady()) {
        ms = {
            cmd: 'getclipboard',
            args: ["getclipboard"],
            handler: 'localos_exeoscmd_handler',
            data: null
        };
        localos_session.ws.send(JSON.stringify(ms));
    }
    else {
        var ms = {
            cmd: 'appxclipboard',
            args: [""],
            handler: 'appxsendfilehandler',
            data: null
        };
        appx_session.ws.send(JSON.stringify(ms));
        alert("You must have access to your local OS to display this file:  " + urlString);
    }
}

function buildOpenCommand(fileToOpen) {
    var arg = "";
    var cshell = appx_session.getRawProp("commandShell");

    if (cshell && cshell.length > 0) {
        arg += cshell + appx_session.parseOption(urlString.substring(9));
    }
    else {
        if (appx_session.globals["os"].indexOf("Win") > -1) {
            arg += 'powershell -Command "& {start-process \'' + fileToOpen.replace('/"/g', "").trim() + '\'}"';
        }
        else if (appx_session.globals["os"].indexOf("Mac") > -1) {
            arg += 'open ' + fileToOpen;
        }
        else {
            arg += 'xdg-open ' + fileToOpen;
        }
    }
    return arg;
}

function buildOpenCommandDos(fileToOpen) {
    var arg = "";
    var cshell = appx_session.getRawProp("commandShell");
    if (fileToOpen.indexOf("/H") > -1){
	fileToOpen = fileToOpen.replace(/\/h /i,"/b ");
    }
        if (fileToOpen.indexOf("/W") > -1){
	fileToOpen = fileToOpen.replace(/\/w /i,"/WAIT ");
    }

    if (cshell && cshell.length > 0) {
        arg += cshell + appx_session.parseOption(urlString.substring(9));
    }
    else {
        if (appx_session.globals["os"].indexOf("Win") > -1) {
	    arg += ("start \"\" " + fileToOpen);
        }
        else if (appx_session.globals["os"].indexOf("Mac") > -1) {
            arg += 'open ' + fileToOpen;
        }
        else {
            arg += 'xdg-open ' + fileToOpen;
        }
    }
    return arg;
}


// LOAD URL Handler
function appxloadurlhandler(x) {
    var cmd = x.data;
    var ms = {};
    var urlString = cmd.trim();
    var waitfor = false;
    var shellCmd = null;
    //  Will we need to wait for execution to complete?
    try {
        var urllen = urlString.toLowerCase().trim().length;
        if (urlString.toLowerCase().substring(0, 2).indexOf("/w") > -1 || urlString.toLowerCase().substring(urllen - 2, urllen).indexOf("/w") > -1) {
            urlString = cmd.replace("/w", "").trim();
            waitfor = true;
        }
        if (appx_session.globals["os"].indexOf("Win") && urlString.substring(0, 1).indexOf("@") > -1)
            urlString = urlString;
        if (urlString.substring(0, 1).indexOf("@") > -1) {
            try {
                ms = {
                    cmd: 'execoscmd',
                    args: [urlString],
                    handler: 'localos_exeoscmd_handler',
                    data: null
                };
                if (appxIsLocalReady()) {
                    localos_session.ws.send(JSON.stringify(ms));
                }
                else {
                    alert("You must have access to your local OS to run this command:  " + urlString);
                }
            }
            catch (e) {
                console.log("CharView.loadUrl(" + urlString.substring(1) + "): Run Failed");
                console.log("Run Failure Exception = " + e);
		console.log(e.stack);
            }
        }
        else if (urlString.indexOf("$print:") > -1) {
            try {
                var prtcmd = appx_session.parseOption(urlString.substring(7).trim());
                if (appx_session.globals["os"].indexOf("Win") > -1) {
                    if (prtcmd.indexOf(".txt") > -1) {
                        ms = {
                            cmd: 'execoscmd',
                            args: ['\"' + appx_session.local_environment.currentworkingdirectory + '\\bin\\winprint.exe\" ' + prtcmd],
                            handler: 'localos_exeoscmd_handler',
                            data: null
                        };
                    }
                    else {
                        if (prtcmd.indexOf(".cfg") > -1) {
                            prtcmd = prtcmd.substring(prtcmd.indexOf(".cfg"), prtcmd.length);
                            prtcmd = prtcmd.replace(/\"/g, "\'");
                            prtcmd = prtcmd.replace("\.cfg' ", "")
                        }
                        ms = {
                            cmd: 'execoscmd',
                            args: ['powershell -Command "& {start-process \"' + prtcmd + '\" -Verb Print}"'],
                            handler: 'localos_exeoscmd_handler',
                            data: null
                        };
                    }
                }
                else {
                    //linux and mac
                    ms = {
                        cmd: 'execoscmd',
                        args: ['\"' + appx_session.local_environment.currentworkingdirectory + '/bin/appx_print\" ' + prtcmd],
                        handler: 'localos_exeoscmd_handler',
                        data: null
                    };
                }
                if (appxIsLocalReady()) {
                    localos_session.ws.send(JSON.stringify(ms));
                }
                else {
                    alert("You must have access to your local OS to print files:  " + urlString);
                }
            }
            catch (e) {
                console.log("CharView.loadUrl(" + urlString.substring(1) + "): Run Failed");
                console.log("Run Failure Exception = " + e);
		console.log(e.stack);
            }
        }
        else if (urlString.indexOf("$printSetup:") > -1) {
            console.log("FIXME - newInstance() called");
            ms = {
                cmd: 'execoscmd',
                args: [appx_session.parseOption("$(cacheRoot)") + "\\print-dialog.exe"],
                handler: 'localos_exeoscmd_handler',
                data: null
            };
            if (appxIsLocalReady()) {
                localos_session.ws.send(JSON.stringify(ms));
            }
            else {
                alert("local os not available...");
            }
        }
        else if (urlString.indexOf("$display:") > -1) {
            ms = {
                cmd: 'execoscmd',
                args: [buildOpenCommand(appx_session.parseOption(urlString.substring(9)))],
                handler: 'localos_exeoscmd_handler',
                data: null
            };
            if (appxIsLocalReady()) {
                localos_session.ws.send(JSON.stringify(ms));
            }
            else {
                alert("You must have access to your local OS to display this file:  " + urlString);
            }
        }
        else if (urlString.indexOf("$beep:") > -1) {
            console.log("FIXME - beep() called");
            var a = $('<embed height="50" width="100" src="'+appxClientRoot+'/assets/ohoh.wav">').appendTo("body").hide();
            setTimeout(function () {
                $(a).remove();
            }, 1500);
        }
        else if (urlString.indexOf("$play:") > -1) {
            console.log("FIXME - playSample() called");
            ms = {
                cmd: 'execoscmd',
                args: [buildOpenCommand(appx_session.parseOption(urlString.substring(6)))],
                handler: 'localos_exeoscmd_handler',
                data: null
            };
            if (appxIsLocalReady()) {
                localos_session.ws.send(JSON.stringify(ms));
            }
            else {
                alert("You must have access to your local OS to play media files:  " + urlString);
            }
        }
        else if (urlString.indexOf("$setprop:") > -1) {
            var prop = urlString.substring(9, urlString.length).split("=");
            appx_session.setPropEx(prop[0].trim(), prop[1], false);

        }
        else if (urlString.indexOf("$newsession:") > -1) {
            var propspairs = urlString.substring(12, urlString.length).trim().split(" ");
            var sessionflags = {};
            for (var i = 0; i < propspairs.length; i++) {
                var kv = propspairs[i].split("=");
		if( kv[0] != "" )
		    sessionflags[kv[0].replace("-", "")] = kv[1].replace(/"/g, ''); // "
            }

            var startup_info = {};
            sendappxnewsession(appx_session.host, appx_session.port, appx_session.user, appx_session.password, appx_session.screenrows, appx_session.screencols, sessionflags) // "
        }else if (urlString.indexOf("$(pushAndOpen)") > -1){
	    /*If we push a file to the client that we want displayed in the browser
	    **then we open a new tab and let the browser display the file*/
	    var url = appx_session.appxCacheUrl + "/getFile/" + urlString.replace("$(","").replace(")","");
	    var winOpen = window.open(url, "_blank");
	    
        }else {
	    var runString = [];
		runString[0] = "";
            if (shellCmd) {
                runString[0] = shellCmd;
            }
            runString[1] = urlString;
            try {
                ms = {
                    cmd: 'execoscmd',
                    args: [buildOpenCommandDos(appx_session.parseOption(runString[1]))],
                    handler: 'localos_exeoscmd_handler',
                    data: null
                };
                if (appxIsLocalReady()) {
                    localos_session.ws.send(JSON.stringify(ms));
                }
                else {
                    if (urlString.indexOf("http") < 0) {
                        urlString = "http://" + urlString;
                    }
                    window.open(urlString, "_blank", "toolbar=yes, scrollbars=yes, resizable=yes, location=yes, menubar=yes, status=yes, titlebar=yes, channelmode=yes, top=50, left=50, width=" + $(window).width() * .8 + ", height=" + $(window).height() * .8 + "");
                }
            }
            catch (e) {
                console.log("CharView.loadUrl(" + runString[0] + " " + urlString + "): Run Failed");
                console.log("Run Failure Exception = " + e);
		console.log(e.stack);
            }
        }
    }
    catch (e) {
        console.log("appxloadurlhandler(" + urlString + "): Bad URL, e="+e);
	console.log(e.stack);
    }
}

//SENDING A File from the CLIENT to the SERVER(server receive)
//Server is telling client to grab a file and send it
function appxreceivefilehandler(x) {
    var url = x.data;
    if (url.length > 0) {
        appx_session.currrecfile = {};
        appx_session.currrecfile.filename = url;
        var ms = {
            cmd: 'openfile',
            args: [url],
            handler: 'localopenfile',
            data: null
        };
        localos_session.ws.send(JSON.stringify(ms));
    }
    else {
        if ($(".appxfiledialog").length == 0) {
            var fd = $("<div>").addClass("appxfiledialog").css({
                "z-index": 200000
            });
            $(fd).append("<input id='fileopener' type='file'>");
            $(fd).append($("<input id='submitfile' type='submit'>").click(function () {
                appxReadBlob();
            }));
            $("body").append(fd);
            $.each($(".appxfiledialog"), function (i, el) {
                $(el).dialog({
                    open: function (event, ui) {
                        $(this).parent().css({
                            "z-index": 200000
                        });
                        $(this).css({
                            "z-index": 200000
                        });
                    }
                });
                $(el).dialog("open");
            });
        }
        else {
            $("#fileopener").val("");
            $(".appxfiledialog").dialog("open");
        }
    }
}

function appxReadBlob(opt_startByte, opt_stopByte) {
    var files = document.getElementById('fileopener').files;
    if (!files.length) {
        alert('Please select a file!');
        return;
    }
    var file = files[0];
    var start = 0;
    var stop = file.size - 1;
    var reader = new FileReader();
    var filebytes = null;
    // If we use onloadend, we need to check the readyState.
    reader.onloadend = function (evt) {
        if (evt.target.readyState == FileReader.DONE) { // DONE == 2
            filebytes = evt.target.result;
            sendfiledatatoserver(file, filebytes);
        }
    };

    if (file.slice) {
        var blob = file.slice();
    }
    else if (file.webkitSlice) {
        var blob = file.webkitSlice();
    }
    else if (file.mozSlice) {
        var blob = file.mozSlice();
    }
    reader.readAsArrayBuffer(blob);
    $(".appxfiledialog").dialog("close");
}

function sendfiledatatoserver(file, filebytes) {
    try {
        //send status
        appxClearStatusMsgText();
        appxSetStatusText("Uploading File...");
        var ms = {
            cmd: 'appxmessage',
            args: [3, 1],
            handler: 'appxreceivefilehandler',
            data: null
        };
        appx_session.ws.send(JSON.stringify(ms));
        var argarry = [];
        //send length of file Uint32
        filelength = new Uint32Array(1);
        filelength[0] = parseInt(file.size);
        var bitarry = new Uint8Array(filelength.buffer);
        var ai = bitarry.length - 1;
        for (var i = 0; i < bitarry.length; i++) {
            argarry[ai] = bitarry[i];
            ai--;
        }
        var ms = {
            cmd: 'appxmessage',
            args: argarry,
            handler: 'appxreceivefilehandler',
            data: null
        };
        appx_session.ws.send(JSON.stringify(ms));
        var filebytearray = new Uint8Array(filebytes);
        argarry = [];
        bitarry = new Uint8Array(filebytearray.buffer);
        for (var i = 0; i < bitarry.length; i++) {
            argarry[i] = bitarry[i];
        }
        //send bytes 2048 at a time
        for (var i = 0; i * 2048 < argarry.length; i++) {
            var chunk = argarry.slice(i * 2048, i * 2048 + 2048);
            //send chunk length
            //send length of file Uint32
            chunklength = new Uint32Array(1);
            chunklength[0] = chunk.length;
            var chunklenarry = [];
            bitarry = new Uint8Array(chunklength.buffer);
            ai = bitarry.length - 1;
            for (var c = 0; c < bitarry.length; c++) {
                chunklenarry[ai] = bitarry[c];
                ai--;
            }
            var ms = {
                cmd: 'appxmessage',
                args: chunklenarry,
                handler: 'appxreceivefilehandler',
                data: null
            };
            appx_session.ws.send(JSON.stringify(ms));
            //send chunk
            var ms = {
                cmd: 'appxfileuploadmessage',
                args: chunk,
                handler: 'appxreceivefilehandler',
                data: {
                    "i": i * 2048,
                    "length": argarry.length
                }
            };
            appx_session.ws.send(JSON.stringify(ms));
            appxClearStatusMsgText();
            appxSetStatusText("Uploading File...  Bytes Sent:  " + (i * 2048).toString());
        }
        //send null for EOF
        var ms = {
            cmd: 'appxmessage',
            args: [0, 0, 0, 0],
            handler: 'appxreceivefilehandler',
            data: null
        };
        appx_session.ws.send(JSON.stringify(ms));
        //send Filename Length
        //FIXME - File names can be over 255 chars, this won't work if so
        var ms = {
            cmd: 'appxmessage',
            args: [0, 0, 0, file.name.length],
            handler: 'appxreceivefilehandler',
            data: null
        };
        appx_session.ws.send(JSON.stringify(ms));
        //send File Name
        var lfn = [];
        for (var fna = 0; fna < file.name.length; fna++) {
            lfn.push(file.name.charCodeAt(fna));
        }
        var ms = {
            cmd: 'appxmessage',
            args: lfn,
            handler: 'appxreceivefilehandler',
            data: null
        };
        appx_session.ws.send(JSON.stringify(ms));
        //send client status
        var ms = {
            cmd: 'appxmessage',
            args: [3, 1],
            handler: 'appxreceivefilehandler',
            data: null
        };
        appx_session.ws.send(JSON.stringify(ms));
    }
    catch (e) {
        console.log(e);
	console.log(e.stack);
    }
}

function appxfileuploadprogresshandler(data) {
    var fi = data;
    if (fi.data.i < fi.data.length - 2048) {
        appxClearStatusMsgText();
        appxSetStatusText("Uploading File...  " + (fi.data.i).toString() + " Bytes of " + fi.data.length.toString() + " Sent");
        console.log("Uploading File...  Bytes Sent:  " + (fi.data.i).toString());
    }
    else {
        appxClearStatusMsgText();
        appxSetStatusText("File Upload Complete...");
    }
}

function CreateFile(file) {
    //create file on localos_session
    var ms = {
        cmd: 'createfile',
        args: [file],
        handler: 'localfilecreate',
        data: null
    };
    localos_session.ws.send(JSON.stringify(ms));
}
var msgCount = 0;
function AppendFile(data) {
    if (data.length > 0) {
        var filecopy = {};
        filecopy.filename = appx_session.currsendfile.filename;
        filecopy.filedata = data;
	filecopy.count = ++msgCount;
        //create file on localos_session
        var ms = {
            cmd: 'appendfile',
            args: [filecopy],
            handler: 'localfileappend',
            data: null
        };
        localos_session.ws.send(JSON.stringify(ms));
    }
}

function localos_create_file_handler(data) {
    appx_session.currsendfile.filecreated = true;
}

function localos_append_file_handler(data) {}
