const CONSENSUS_TABLE = {
    0: '无',
    1: 'PBFT',
    2: 'RAFT',
    3: 'Single'
};

const RESPONSE_TYPE_TABLE = {
    0: 'ALL',
    1: 'MOST',
    2: 'FIRST'
};

function loadContractInstances(event) {
    console.log("loadContractInstances" + event);
    listContractProcess();
}

function listContractProcess(event) {
    console.log("listContractProcess" + event);
    setTimeout(function () {
        global.wssocket.send(JSON.stringify({
            action: 'listContractProcess',
            // data: event,
            // 1 << 0: INIT, 1 << 1: RUNNING, 1 << 2: HANGED, 1 << 3: KILLED, 0: ALL
            filters: global.myRole && global.myRole.indexOf('NodeManager') > -1 ? 0 : 7
        }));

        global.wssocket.send(JSON.stringify({
            action: 'listLeakContractProcess'
        }));
    }, 300);
}

function onListContractProcess1(obj) {
    console.log("+++++++++=" + obj.data.length);
    const table = JSON.parse(obj.data);
    global.contractList = table;
    drawContractInstanceStatusPie(table);
    // drawContractInstanceTimesPie(table);
    drawContractInstanceTypeTimesPie(table);
    drawConInfoTable(table);
    console.log(table);
    $("#selectContractInstance").html("");
    const x = document.getElementById("selectContractInstance");
    x.options.length = 0;
    x.add(new Option("选择...", " "));

    global.permissionNameMap = {};
    for (let i = 0; i < table.length; i++) {
        if (table[i]['contractStatus'] !== 'RUNNING') {
            continue;
        }
        let option = document.createElement("option");
        option.text = table[i].name;
        console.log(table[i].name);
        global.permissionNameMap[table[i].id] = table[i]['contractPermission'];
        // option.value=table[i].id;
        option.value = table[i].id;
        x.add(option, null);
    }
}

function drawConInfoTable(table) {
    const ciTabDiv = $("#ciTabDiv");
    if (ciTabDiv.css("height") === "0px") {
        console.log("drawConInfoTabDiv: ignore");
        return;
    }
    var dtLang = {
        "sProcessing": "处理中...",
        "lengthMenu": '显示 <select>' + '<option value="10">10</option>'
            + '<option value="50">50</option>'
            + '<option value="100">100</option>'
            + '<option value="-1">全部</option>' + '</select> 项结果',
        "sZeroRecords": "没有匹配结果",
        "sInfo": "显示第 _START_ 至 _END_ 项结果，共 _TOTAL_ 项",
        "sInfoEmpty": "显示第 0 至 0 项结果，共 0 项",
        "sInfoFiltered": "(由 _MAX_ 项结果过滤)",
        "sInfoPostFix": "",
        "sSearch": "搜索:",
        "sUrl": "",
        "sEmptyTable": "表中数据为空",
        "sLoadingRecords": "载入中...",
        "sInfoThousands": ",",
        "oPaginate": {
            "sFirst": "首页",
            "sPrevious": "上页",
            "sNext": "下页",
            "sLast": "末页"
        },
        "oAria": {
            "sSortAscending": ": 以升序排列此列",
            "sSortDescending": ": 以降序排列此列"
        }
    };
    const tableHead = `<table id='ciTabDivTab' class='table display row-border' style='word-break:keep-all;'>
<thead><tr>
<th>序号</th>
<th>ID</th>
<th>名称</th>
<th>状态</th>
<th>端口</th>
<th>类型</th>
<th>通讯</th>
<th>共识</th>
<!--<th>返回方式</th>-->
<th>次数</th>
<th>流量</th>
<th>内存</th>
<th>管理</th>
</tr>
</thead><tbody>`;
    const tableTail = "</tbody></table>";

    console.log("drawConInfoTable");
    let html = tableHead;
    for (let i = 0; i < table.length; i++) {
        html += `<tr>
<td>${i + 1}</td>
<td>${table[i].id}</td>
<td><a href='/client/bdwareclient.html?self=true&contract=${table[i].id}' target='_blank'>
${table[i].name}
</a></td>
<td>${table[i]['contractStatus']}</td>
<td>${table[i].port || '-'}</td>
<td>${table[i].type}</td>
<td>${table[i]['networkType'] ? "P2P" : "TCP"}</td>
<td>${table[i]['consensusType'] ? CONSENSUS_TABLE[table[i]['consensusType']] : '无'}</td>
<!--<td>${table[i].responseType ? RESPONSE_TYPE_TABLE[table[i].responseType] : '-'}</td>-->
<td>${table[i].times}</td>
<td>${table[i]['traffic'] || '-'}</td>
<td>${table[i].storage || '-'}</td>
<td style='padding:2px 12px 2px 12px'>
<button onclick="stopContractByID('${table[i].id}')" class="btn btn-secondary">停止</button>
</td>
</tr>`
    }
    html += tableTail;
    html = "<h5 class='card-title'>合约实例列表</h5>" + html;
    ciTabDiv.html(html);

    $("#ciTabDivTab").DataTable(
        {
            "language": dtLang,
            "rowCallback": function (row, data, displayNum, displayIndex,
                                     dataIndex) {

            },
            "headerCallback": function (thead/*, data, start, end, display*/) {
                $(thead).css("background", primaryColor);
                $(thead).css("color", "white");
                $(thead).children().css("background", primaryColor);
                $(thead).children().css("color", "white");
            },
            scrollCollapse: false,
            paging: true,
            pageLength: 10,
            order: [[0, 'desc']],
            "columnDefs": [
                {
                    "targets": 1,
                    "render": function (data/*, type, row, meta*/) {
                        if (data.length > 8)
                            return "<span title='" + data + "'>"
                                + data.substring(0, 8)
                                + "  ...</span>";
                        else
                            return data;
                    }

                },]
        });
}

function stopContractByID(contractID) {
    $("#dialogBodyDiv").html("是否停止合约，ContractID：" + contractID);
    showDialog("请确认", function () {
        global.wssocket.send(JSON.stringify({
            action: 'killContractProcess',
            requestID: new Date().getTime().toString(),
            id: contractID
        }));
    });
}

function drawContractInstanceStatusPie(table) {
    const ciStatusPieDiv = $("#ciStatusPieDiv")
    if (ciStatusPieDiv.css("height") === "0px") {
        console.log("drawContractInstanceStatusPie: ignore");
        return;
    }
    $(ciStatusPieDiv).html(
        "<div class='col-12' id='ciStatusPieDivCanv' style='width:100%; min-height: 150px; padding: 0;'></div>");
    const result = {};
    for (let i = 0; i < table.length; i++) {
        const obj = table[i];
        if (!result[obj['contractStatus']]) {
            result[obj['contractStatus']] = 1;
        } else
            result[obj['contractStatus']]++;
    }
    global.result = result;
    const dataList = [];
    const valDataList = [];
    for (const key in result) {
        dataList.push(key);
        valDataList.push({
            name: key,
            value: result[key]
        });
    }

    const myChart = echarts.init($("#ciStatusPieDivCanv")[0], 'walden');
    const option222 = {
        tooltip: {
            trigger: 'item',
            formatter: '{a} <br/>{b}: {c} ({d}%)'
        },
        legend: {
            orient: 'vertical',
            left: 10,
            data: dataList
        },
        series: [{
            name: '合约实例状态',
            type: 'pie',
            radius: ['50%', '70%'],
            avoidLabelOverlap: false,
            label: {
                normal: {
                    show: false,
                    position: 'center'
                },
                emphasis: {
                    show: true,
                    textStyle: {
                        fontSize: '15',
                        fontWeight: 'bold'
                    }
                }
            },
            labelLine: {
                normal: {
                    show: false
                }
            },
            data: valDataList
        }]
    };
    myChart.setOption(option222);
}

function drawContractInstanceTimesPie(table) {
    const ciTimesPieDiv = $("#ciTimesPieDiv");
    if (ciTimesPieDiv.css("height") === "0px") {
        console.log("drawContractInstanceTimesPie: ignore");
        return;
    }
    ciTimesPieDiv.html(
        "<div class='col-12' id='ciTimesPieDivCanv' style='width:100%; min-height: 150px; padding: 0;'></div>");
    const result = {};
    for (let i = 0; i < table.length; i++) {
        const obj = table[i];
        result[obj.name] = obj.times;
    }
    global.result = result;
    const dataList = [];
    const valDataList = [];
    for (const key in result) {
        dataList.push(key);
        valDataList.push({
            name: key,
            value: result[key]
        });
    }

    const myChart = echarts.init($("#ciTimesPieDivCanv")[0], 'walden');

    const option222 = {
        tooltip: {
            trigger: 'item',
            formatter: '{a} <br/>{b}: {c} ({d}%)'
        },
        legend: {
            orient: 'vertical',
            left: 10,
            data: dataList
        },
        series: [{
            name: '实例调用次数',
            type: 'pie',
            radius: ['50%', '70%'],
            avoidLabelOverlap: false,
            label: {
                normal: {
                    show: false,
                    position: 'center'
                },
                emphasis: {
                    show: true,
                    textStyle: {
                        fontSize: '15',
                        fontWeight: 'bold'
                    }
                }
            },
            labelLine: {
                normal: {
                    show: false
                }
            },
            data: valDataList
        }]
    };
    myChart.setOption(option222);
}

function changeContractInstance(obj) {
    let i;
    console.log(obj);
    global.contractInstance = obj;

    console.log(typeof (obj));
    showPermissionList(global.contractInstance);

    let contract;
    for (i = 0; i < global.contractList.length; i++) {
        if (global.contractList[i].id === obj) {
            contract = global.contractList[i];
            global.instance = contract;
            global.instanceName = contract.name;
            global.instanceSequencing = contract.type;
            global.useP2P = contract.useP2P;
            listMemoryFiles(contract.name);
            getSyncType(contract.name);
            break;
        }
    }

    $("#selectContractFunction").html("");
    const x = document.getElementById("selectContractFunction");
    x.options.length = 0;
    x.add(new Option("选择方法...", " "));
    console.log("contract ", contract);
    for (i = 0; i < contract['exportedFunctions'].length; i++) {
        const option = document.createElement("option");
        option.text = contract['exportedFunctions'][i].functionName;
        option.value = contract['exportedFunctions'][i].functionName;
        x.add(option, null);
    }
}

function changeMemoryFiles(obj) {
    console.log(obj);
    global.memoryFile = obj;
}

function executeContractWithDynamicResult() {
    const argDiv = $("#arg")[0]
    console.log("executeContractWithDynamicResult");
    const request = {};
    request.action = "executeContract";
    request.requestID = new Date().getTime() + "";
    request.contractName = global.contractInstance;
    request.sequencing = global.instanceSequencing;
    request.useP2P = global.useP2P;
    request.isDebug = executeContractAsDebug.checked;
    const operation = $("#selectContractFunction")[0].value;
    if (operation === " " && !operation) {
        myToast("执行合约", "请选择合约方法！");
        return;
    }
    request.arg = `{"action":"${operation}","arg":"${argDiv.value}"}`;
    request.pubkey = global.sm2Key.publicKey;
    request.withDyanmicAnalysis = true;
    request.signature = sm2.doSignature(
        `${request.contractID}|${operation}|${argDiv.value}|${global.sm2Key.publicKey}`,
        global.sm2Key.privateKey,
        {hash: true, der: true});
    localStorage.setItem("persisArg", JSON.stringify(request));
    global.wssocket.send(JSON.stringify(request));
}

function executeContract() {
    const argDiv = $('#arg')[0];
    const request = {};
    request.action = "executeContract";
    request.requestID = new Date().getTime() + "";
    request.contractID = global.contractInstance;
    const operation = $("#selectContractFunction")[0].value;
    if (operation === " " && !operation) {
        myToast("执行合约", "请选择合约方法！");
        return;
    }
    request.operation = operation;
    request.arg = argDiv.value;
    request.pubkey = global.sm2Key.publicKey;
    request.isDebug = executeContractAsDebug.checked;
    console.log(request.arg);
    const gasLimit = $('#gasLimit').val()/1;
    var toSign = request.contractID + "|"
                        + request.operation + "|" + arg ;
    if (gasLimit>0){
      request.gasLimit = gasLimit;
      toSign+= "|" + gasLimit;
    }
    toSign+= "|" + global.sm2Key.publicKey;
    request.signature = sm2.doSignature(
        toSign,
        global.sm2Key.privateKey,
        {hash: true, der: true});
    localStorage.setItem("persisArg", JSON.stringify(request));
    global.wssocket.send(JSON.stringify(request));
}

function onExecuteResult(obj) {
    console.log("onExecuteResult obj.data", obj.data);
    try {
        const result = obj;
        let styleTail = "<br>字符串格式";
        $("#responseStatus").html("执行状态:" + result.status);
        if (result['analysis']) {
            $("#responseArea")[0].value = "执行结果:" + result.result + "\n动态分析结果:"
                + result['analysis'];
        } else {
            if (result.result instanceof Object) {
                $("#responseArea")[0].value = JSON.stringify(result.result);
                styleTail = "<br>JSON格式";
            } else
                $("#responseArea")[0].value = result.result;
        }
        $("#responseID").html(`请求ID:${obj['responseID']}`);
        var gasInfo="";
        if (obj.executionGas!=undefined && obj.executionGas>0)
          gasInfo="<br>"+obj.executionGas+"gas";
        $("#responseTime").html(`响应时间:${obj['executeTime']}ms${gasInfo}${styleTail}`);
    } catch (e) {
        $("#responseStatus").html("执行状态：Failed");
        $("#responseArea")[0].value = obj.data;
        $("#responseID").html(`请求ID：${obj['responseID']}`);
        $("#responseTime").html(`响应时间：${obj['executeTime']}ms`);
    }
}

function onHashResult(obj) {
    $("#hashResult").html("数链指纹:" + obj.data);
}

function drawCPTable(table) {
    console.log("drawCPTable");
    global.contractprocess = table.data;
    if ($("#ciTabDiv").css("height") === "0px") {
        console.log("drawCPTableDiv: ignore");
        return;
    }
    var dtLang = {
        "sProcessing": "处理中...",
        "lengthMenu": '显示 <select>' + '<option value="10">10</option>'
            + '<option value="50">50</option>'
            + '<option value="100">100</option>'
            + '<option value="-1">全部</option>' + '</select> 项结果',
        "sZeroRecords": "没有匹配结果",
        "sInfo": "显示第 _START_ 至 _END_ 项结果，共 _TOTAL_ 项",
        "sInfoEmpty": "显示第 0 至 0 项结果，共 0 项",
        "sInfoFiltered": "(由 _MAX_ 项结果过滤)",
        "sInfoPostFix": "",
        "sSearch": "搜索:",
        "sUrl": "",
        "sEmptyTable": "表中数据为空",
        "sLoadingRecords": "载入中...",
        "sInfoThousands": ",",
        "oPaginate": {
            "sFirst": "首页",
            "sPrevious": "上页",
            "sNext": "下页",
            "sLast": "末页"
        },
        "oAria": {
            "sSortAscending": ": 以升序排列此列",
            "sSortDescending": ": 以降序排列此列"
        }
    };
    const tableHead = `<table id='cpTabDivTab' class='table display row-border'>
<thead><tr>
<th>序号</th>
<th>PID</th>
<th>是否泄漏</th>
<th>启动时间</th>
<th>CPUUser</th>
<th>CPUSyss</th>
<th>resident</th>
<th>memory</th>
<th>管理</th>
</tr></thead><tbody>`;
    const tableTail = "</tbody></table>";
    table = table.data;
    console.log("drawConInfoTable");
    let html = tableHead;
    for (let i = 0; i < table.length; i++) {
        html += `<tr>
<td>${i + 1}</td>
<td>${table[i].pid}</td>
<td>${table[i]['isLeak']}</td>
<td>${new Date(table[i]['cpuStart']).toLocaleString()}/td>
<td>${table[i]['cpuTotal']}</td>
<td>${table[i]['cpuSys']}</td>
<td>${(table[i]['resident'] / (1024 * 1024)).toFixed(2)}MB</td>
<td>${(table[i]['memsize'] / (1024 * 1024)).toFixed(2)}MB</td>
<td style='padding:2px 12px 2px 12px'>
<button onclick="stopContractByPID('${table[i].pid}')" class='btn btn-secondary'>停止</button>
</td>
</tr>`
    }
    html += tableTail;
    html = `<h5 class='card-title'>合约进程列表</h5>${html}`;
    $("#cpTabDiv").html(html);

    $("#cpTabDivTab").DataTable(
        {
            "language": dtLang,
            "rowCallback": function (row, data, displayNum, displayIndex,
                                     dataIndex) {

            },
            "headerCallback": function (thead/*, data, start, end, display*/) {
                $(thead).css("background", primaryColor);
                $(thead).css("color", "white");
                $(thead).children().css("background", primaryColor);
                $(thead).children().css("color", "white");
            },
            scrollCollapse: false,
            paging: true,
            pageLength: 10,
            order: [[0, 'desc']],
            "columnDefs": [
                {
                    "targets": 1,
                    "render": function (data/*, type, row, meta*/) {
                        if (data.length > 10)
//                                return "<span title='" + data + "'>"
//                                        + data.substring(0, 10)
//                                        + "  ...</span>";
                            return data;
                        else
                            return data;
                    }

                },]
        });
}

function stopContractByPID(pid) {
    $("#dialogBodyDiv").html("是否停止PID:" + pid);
    showDialog("请确认", function () {
        global.wssocket.send(JSON.stringify({
            action: 'killProcessByPID',
            pid: pid
        }));
        global.wssocket.send(JSON.stringify({
            action: 'listLeakContractProcess'
        }));
    });
}