function applyRole(role) {
    global.wssocket.send("{\"action\":\"applyNodeRole\",\"role\":\"" + role
        + "\",\"pubKey\":\"" + global.sm2Key.publicKey + "\"}");
}

function WSHandler(event) {
    // console.log(event);
    let data = event.data;
    try {
        let obj = JSON.parse(data);
        switch (obj.action) {
            case "onSessionID":
                onSessionID(obj);
                break;
            case "onLogin":
                onLogin(obj);
                break;
            case "onListProjects":
                onListProjects(obj);
                break;
            case "onListProject":
                onListProject(obj);
                break;
            case "onRenameFile":
                onRenameFile(obj);
                break;
            case "onDeleteFile":
                onDeleteFile(obj);
                break;
            case "onStartContract":
                onStartContract(obj);
                break;
            case "onStartContractAsDebug":
                onStartContractAsDebug(obj);
                break;
            case "onListContractProcess":
                onListContractProcess(obj);
                break;
            case "onKillContractProcess":
                onKillContractProcess(obj);
                break;
            case "onKillAllContract":
                onKillAllContract(obj);
                break;
            case "onQueryContractInstanceDOI":
                onQueryContractInstanceDOI(obj);
                break;
            case "onQueryContractInstanceInfoByDOI":
                onQueryContractInstanceInfoByDOI(obj);
                break;
            case "onImportContractInstanceCodeByDOI":
                onImportContractInstanceCodeByDOI(obj);
                break;
            case "onExecuteResult":
                onExecuteResult(obj);
                break;
            case 'onOutputStream':
                displayOutput(obj);
                break;
            case 'onListFile':
                onListFile(obj);
                break;
            case 'onSaveFile':
                onSaveFile(obj);
                break;
            case 'onUploadFile':
                onUploadFile(obj);
                break;
            case 'onHashResult':
                onHashResult(obj);
                break;
            case 'onStaticVerifyResult':
                onStaticVerify(obj);
                break;
            case 'onEvaluates':
                onEvaluates(obj);
                break;
            case 'onCompile' :
                onCompile(obj);
                break;
            case 'onRegisterDOI' :
                onRegisterDOI(obj);
                break;
            case 'onStartContractTrustfullyResult':
                onStartContractTrustfullyResult(obj);
                break;
            case 'onException':
                if (obj.data.startsWith("unauthorized "))
                    handleNoPermission(obj);
                onException(obj);
                break;
            case 'onGetControlFlow':
                onGetControlFlow(obj);
                break;
            case 'onGenerateReadme':
                onGenerateReadme(obj);
                break;
            default:
                // console.log(obj);
                break;
        }
    } catch (err) {
        console.log(err);
    }
}

function displayOutput(obj) {
    console.log(obj);
    displayOutputStr(obj.data);
}

function displayOutputStr(str) {
    if (!global.outputEditor) {
        return;
    }
    let val = global.outputEditor.getValue();
    if (val.length > 0)
        val += "\n";
    val += str;
    global.outputEditor.setValue(val);
    let info = global.outputEditor.getScrollInfo();
    global.outputEditor.scrollTo(0, info.height);
}

function getControlWsUrl(host) {
    let prefix = "ws://";
    if (document.location.href.startsWith("https")) {
        prefix = "wss://";
    }
    let path = document.location.pathname.lastIndexOf("/");
    path = document.location.pathname.substr(0, path + 1);
    if (path.indexOf("SCIDE") < 0)
        path += "SCIDE/";
    path += "SCExecutor";
    return prefix + host + path;
}

function initWSocket() {
    console.log("[nodecenterManagement.js] initWSocket : ");
    let host = document.location.host;
    let url = getControlWsUrl(host);
    // console.log("connect ws:" + url);
    global.wssocket = createWssocket(url, function () {
        getSession();
        myToast("提示", "正在登录");
    }, WSHandler);
}

function getSession() {
    global.wssocket.send("{\"action\":\"getSessionID\"}");
}

// ====== wsHandler
function onSessionID(data) {
    global.session = data.session;
    const loginParam = {
        action: "login",
        pubKey: global.sm2Key.publicKey,
        signature: sm2.doSignature(global.session, global.sm2Key.privateKey,{hash:true,der:true})
    };
    global.wssocket.send(JSON.stringify(loginParam));
}

function onLogin(data) {
    // var param = {};
    pubkeyDialogVue.myRole = data.data;
    listFiles();
    listContracts();
    //param.action = "getNodeRole";
    //global.wssocket.send(JSON.stringify(param));
}

function onRenameFile(data) {
    myToast("重命名", data.data);
    if (data.data === "success") {
        listFiles();
    }
}

function onEvaluates(data) {
    // console.log("++++++++++++++++++++" + data);
}

function onDeleteFile(data) {
    myToast("删除文件", data.data);
    if (data.data === "success") {
        listFiles();
    }
}

function onStartContract(data) {
    // console.log(data);
    const result = JSON.parse(data.data);
    /*	if (result.isInsnLimit) {
            global.withEvaluatesAnalysis = true;
            $("#dialogBodyDiv").text("此合约在执行时会消耗gas,请在执行前进行预估，根据预估值给出相应的值，建议给出的值大于预估值");
            showDialog("部署合约成功", function() {
            });
        }*/
    startResult.innerText = result.status + "(" + data.executeTime + "ms" + ")";
    if (result.status !== "Success") {
        let body = "<div class='input-group mb-3'>";
        body += " <textarea id='onStartContractFailedContent' class='form-control' style='min-height:300px' ></textarea>";
        body += " </div>";
        $("#dialogBodyDiv").html(body);
        $("#onStartContractFailedContent")[0].value = result.result
        showDialog("部署合约失败", function () {
        });
    }
}

function onStartContractAsDebug(data) {
    // console.log(data);
    const result = JSON.parse(data.data);
    /*	if (result.isInsnLimit) {
            global.withEvaluatesAnalysis = true;
            $("#dialogBodyDiv").text("此合约在执行时会消耗gas,请在执行前进行预估，根据预估值给出相应的值，建议给出的值大于预估值");
            showDialog("部署合约成功", function() {
            });
        }*/
    startResult.innerText = result.status + "(" + data.executeTime + "ms" + ")";
    if (result.status !== "Success") {
        let body = "<div class='input-group mb-3'>";
        body += " <textarea id='onStartContractFailedContent' class='form-control' style='min-height:300px' ></textarea>";
        body += " </div>";
        $("#dialogBodyDiv").html(body);
        $("#onStartContractFailedContent")[0].value = result.result
        showDialog("部署合约失败", function () {
        });
    }
}

function onKillContractProcess(data) {
    // console.log(data);
    if (data.data === "success") {
        listContracts();
    }
    stopResult.innerText = data.data + "(" + data.executeTime + "ms" + ")";
}

function onKillAllContract(data) {
    let body = "<div class='input-group mb-3'>";
    body += " <textarea id='onStartContractFailedContent' class='form-control' style='min-height:100px' ></textarea>";
    body += " </div>";
    $("#dialogBodyDiv").html(body);
    $("#onStartContractFailedContent")[0].value = data.data
    showDialog("停止全部合约", function () {
    });
}

function onQueryContractInstanceDOI(data) {
    // console.log(data);
    stopResult.innerText = data.data;
}

function initContractInstanceInfoArea() {
    if (!global.contractInstanceInfoEditor) {
        global.contractInstanceInfoEditor = CodeMirror.fromTextArea(
            $("#contractInstanceInfoArea")[0], {
                matchBrackets: true,
                autoCloseBrackets: true,
                lineNumbers: true,
                mode: "application/ld+json",
                lineWrapping: true
            });
        global.contractInstanceInfoEditor.setSize("height", "200px");
    }
}

function onQueryContractInstanceInfoByDOI(data) {
    initContractInstanceInfoArea();
    // console.log(data);
    $("#contractInstanceInfoTitle")
        .html(" (" + data.executeTime + "ms)");

    global.contractInstanceInfoEditor.setValue(data.data);
    let totalLines = global.contractInstanceInfoEditor.lineCount();

    global.contractInstanceInfoEditor.autoFormatRange({
        line: 0,
        ch: 0
    }, {
        line: totalLines
    });
}

function onImportContractInstanceCodeByDOI(data) {
    initContractInstanceInfoArea();
    // console.log(data);
    $("#contractInstanceInfoTitle")
        .html(" (" + data.executeTime + "ms)");

    global.contractInstanceInfoEditor.setValue(data.data);
    let totalLines = global.contractInstanceInfoEditor.lineCount();

    global.contractInstanceInfoEditor.autoFormatRange({
        line: 0,
        ch: 0
    }, {
        line: totalLines
    });

    global.wssocket.send("{\"action\":\"listProjects\",\"isPrivate\":true}");
}


function onListContractProcess(data) {
    // console.log(data);

    mainVue.contracts = [];
    var list = JSON.parse(data.data);
    for (var i=0;i<list.length;i++){
      if (list[i].contractStatus != "KILLED"){
        mainVue.contracts.push(list[i]);
      }
    }
    selectedContract.value = 0;
    selectContractToExecute();
}

function onSaveFile(data) {
    myToast("保存文件", data.data);
}

function onUploadFile(obj) {
    if (obj.data === "success")
        uploadInternal();
}

function initResponseAndOutputArea() {
    if (!global.responseEditor) {
        setTimeout(function () {
            global.responseEditor = CodeMirror.fromTextArea(
                $("#responseArea")[0], {
                    matchBrackets: true,
                    autoCloseBrackets: true,
                    lineNumbers: true,
                    mode: "application/ld+json",
                    lineWrapping: true
                });
            global.responseEditor.setSize("height", "200px");

            global.outputEditor = CodeMirror.fromTextArea(
                $("#outputStreamArea")[0], {
                    matchBrackets: true,
                    autoCloseBrackets: true,
                    lineNumbers: true,
                    mode: "application/ld+json",
                    lineWrapping: true
                });
            global.outputEditor.setSize("height", "200px");

        }, 200);
    }
}

function onExecuteResult(obj) {

    const data = obj;
    $("#executeResultTitle")
        .html(data.status + "  (" + obj.executeTime + "ms) 未知格式");
    if (data.result instanceof Object){
        $("#executeResultTitle")
            .html(data.status + "  (" + obj.executeTime + "ms) JSON格式");
        global.responseEditor.setValue(JSON.stringify(data.result));
    } else if (typeof data.result == 'string'){
        $("#executeResultTitle")
            .html(data.status + "  (" + obj.executeTime + "ms) 字符串格式");
        global.responseEditor.setValue(data.result);
    } else {
        if (typeof data.result == 'number') {
            $("#executeResultTitle")
                .html(data.status + "  (" + obj.executeTime + "ms) 数值格式");
        } else if (typeof data.result == 'boolean') {
            $("#executeResultTitle")
                .html(data.status + "  (" + obj.executeTime + "ms) 布尔型格式");
        }
        global.responseEditor.setValue(data.result.toString());
    }

    // console.log(data);
    const totalLines = global.responseEditor.lineCount();

    global.responseEditor.autoFormatRange({
        line: 0,
        ch: 0
    }, {
        line: totalLines
    });
    if (data.analysis && data.analysis.length > 0) {
        // displayOutputStr(data.analysis);
    }
}

function onGenerateReadme(obj) {
    // console.log(obj.data);
    myToast("生成文档结果",obj.data);
}

function onHashResult(obj) {
    $("#hashDisplayDiv").html("溯源指纹:" + obj.data);
}

function onException(obj) {
    if (obj.data.startsWith("unauthorised action")) {
        let action = obj.data.replace("unauthorised action ", "");
        switch (action) {
            case "listContractProcess":
                mainVue.contracts = [];
                alertNoPermission("listContractProcess无授权，请申请ContractProvider权限", "提示");

                break;
            case "listProjects":
                mainVue.projects = [];
                $("#publicprojectAccordion").html("");
                $("#privateprojectAccordion").html("");
                alertNoPermission("listProjects无授权，请申请ContractProvider权限", "提示");
                break;
            default:
                alertNoPermission(action + "无权限", "提示");
        }
    }
}

function alertNoPermission(message, title) {
    const nopSpan = $("#nopermissionSpan");
    if (nopSpan.length > 0) {
        // console.log(message + " status:" + $("#dialog")[0].getAttribute("class"));
        nopSpan.append("<br/>" + message);
    } else {
        let body = "<div class='row'><div class='col-sm-12'><span id='nopermissionSpan'>";
        body += message;
        body += "</span></div></div>";
        $("#dialogBodyDiv").html(body);
        showDialog("提示", function () {
            $("#dialogBodyDiv").html("");
        });
    }
}

// ====== wsHandler done!
function myToast(title, msg) {
    toastVue.toastTitle = title;
    toastVue.toastMessage = msg;
    $("#alertDiv").toast("show");
}

function generate() {
    let key = sm2.generateKeyPairHex();
    global.sm2Key = key;
    localStorage.setItem("PrivKey", JSON.stringify(key));
}

function showDialog(title, cb, cancelcb) {
    $("#dialogTitleH5").html(title);
    $("#dialogConfimBtn").off("click").on("click", cb);
    $("#dialogCloseBtn").off("click").on("click", cancelcb);
    $("#dialog").modal("show");
}

function init() {
    console.log("[nodecenterManagement.js] init : ");
    initVue();
    initGlobal();
    initWSocket();
    $('[data-toggle="tooltip"]').tooltip();
    const scriptEditor = $("#scriptEditor");
    const height = scriptEditor.css("height");
    global.scriptEditor = CodeMirror.fromTextArea(scriptEditor[0], {
        matchBrackets: true,
        autoCloseBrackets: true,
        lineNumbers: true,
        mode: "application/ld+json",
        lineWrapping: true
    });
    global.scriptEditor.setSize("height", height);

}

function getRequestParameters() {
    let arr = (location.search || "").replace(/^\?/, '').split("&");
    let params = {};
    for (let sd of arr) {
        let data = sd.split("=");
        if (data.length === 2) {
            params[data[0]] = data[1];
        }
    }
    return params;
}