var WSHandler = function (event) {
    // console.log("[scide.js] WSHandler " + event);
    data = event.data;
    // console.log("   -->" + data);
    try {
        var obj = JSON.parse(data);
        switch (obj.action) {
            case 'ping':
            case 'poing':
                break;
            case 'onExecuteResult':
                onExecuteResult(obj);
                break;
            case 'onListContractProcess':
                onListContractProcess(obj);
                break;
            case 'onStartContract':
                onStartContract(obj);
                break;
            case 'onKillContractProcess':
                logComm(obj);
                break;
            case 'onKillAllContract':
                onKillAllContract(obj);
                break;
            case 'onOutputStream':
                displayOutput(obj);
                break;

            case 'onException':
                logException(obj);
                break;
            case 'onHashResult':
                onHashResult(obj);
                break;
            default:
                // displayOutput(obj);
                break;
        }
    } catch (err) {
        console.log(err);
    }
};// WSHandler()

var logException = function (obj) {
    global.tempobj = obj;
    $("#responseStatus").html("Exception (" + obj.executeTime + "ms)");
    displayOutput(obj);
};

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

var displayOutputStr = function (str) {
    var val = global.outputStreamEditor.getValue();
    val += "\n" + str;
    global.outputStreamEditor.setValue(val);
    var info = global.outputStreamEditor.getScrollInfo();
    global.outputStreamEditor.scrollTo(0, info.height);
};
var checkConnectStatus = function () {
    if (global.wssocket.isOpen() != 1) {
        if ($("#checkConnect").css("display") == "none") {
            $("#checkConnect").fadeIn(800);
        } else
            $("#checkConnect").fadeOut(800);
    } else {
        $("#checkConnect").css("display", "block");
        $("#checkConnect").css("background-color", "#007FFF");
    }
};
var initWSocket = function () {
    var prefix = "ws://";
    if (document.location.href.startsWith("https"))
        prefix = "wss://";
    url = prefix + document.location.host
        + (document.location.pathname.replace("scide.html", "SCExecutor"));
    // console.log(url);
    global.wssocket = createWssocket(url, function () {
        listContractProcess();
        listProjects();
    }, function (data) {
        WSHandler(data);
        FileHandler(data);
    });
    global.filewssocket = global.wssocket;

    setInterval(checkConnectStatus, 1000);
};

// ====== wsHandler
var onStartContract = function (obj) {
    console.log("onStartContract:");
    // console.log(obj);
    var result = JSON.parse(obj.data);
    $("#responseStatus").html(result.status + "  (" + obj.executeTime + "ms)");
    global.responseEditor.setValue(result.result);
    // $("#tabdiv").editableSelect('add', obj.cid);
    // $("#tabdiv").editableSelect()[0].value = obj.cid;
};
var onExecuteResult = function (obj) {
    console.log("onExecuteResult:");
    // console.log(obj);
    var data = JSON.parse(obj.data);
    $("#responseStatus").html(data.status + "  (" + obj.executeTime + "ms)");
    global.responseEditor.setValue(data.result);
    // console.log(data);
    var totalLines = global.responseEditor.lineCount();
    global.responseEditor.autoFormatRange({
        line: 0,
        ch: 0
    }, {
        line: totalLines
    });
    if (data.analysis != undefined && data.analysis.length > 0) {
        // displayOutputStr(data.analysis);
    }
};
var onListContractProcess = function (obj) {
    var data = JSON.parse(obj.data);
    global.contracts = data;
    var html = "";
    $("#tabdiv").editableSelect('clear');
    // $("#tabdiv").html("");
    global.contractName2ID = {};
    for (var i = 0; i < data.length; i++) {
        $("#tabdiv").editableSelect('add', data[i].name);
        global.contractName2ID[data[i].name] = data[i].id;
        // $("#tabdiv").append(
        // $("<option></option>").attr("value", data[i].id).text(
        // data[i].id));
    }
    if (data.length > 0)
        $("#tabdiv").editableSelect()[0].value = data[0].name;
    // $("#tabdiv").selectmenu("refresh");
    // $("#tabdiv").html(html);
    // $("yourid/class here").append($("<option></option>").attr("value",
    // youroption-value).text(youroption-text));

};
var onSaveƒe = function (obj) {
    alert("Save file:" + obj.data);
};
var onKillAllContract = function (obj) {
    customAlert(obj.data);
};
var onHashResult = function (obj) {
    $("#hashResult").html("刚刚操作的数链指纹:" + obj.data);
};
// ====== wsHandler done!
var switchContract = function (off) {
    // var contract = global.contracts[off];
    // global.scriptEditor.setValue(contract.script);
    // $("#tabdiv")[0].value = contract.id;
    var pingObj = {};
    pingObj.action = "connectTo";

    pingObj.name = $("#tabdiv")[0].value;
    pingObj.id = global.contractName2ID[pingObj.name];
    global.wssocket.send(JSON.stringify(pingObj));
}
var countChar = function (str, c) {
    var ret = 0;
    for (var i = 0; i < str.length; i++) {
        if (str.charAt(i) == c)
            ret++;
    }
    return ret;
}
var generateOld = function () {
    $.ajax({
        url: "./SCManager?action=generatePrivateKey",
        dataType: "json"
    }).done(function (result) {
        if (result.status) {
            localStorage.setItem("PrivKey", result.data);
            alert("Key successfully generated!");
            initRest();
        }
    });
}

var generate = function () {
    localStorage.setItem("PrivKey", JSON.stringify(sm2.generateKeyPairHex()));
    global.privKey = localStorage.getItem("PrivKey");
}

var initGlobal = function () {
    window.global = {};
    global.privKey = localStorage.getItem("PrivKey");
    if (global.privKey == undefined || global.privKey == null
        || global.privKey.length < 100 || !global.privKey.startsWith("{")) {
        generate();
        initRest();
    } else
        initRest();
    global.privKey = JSON.parse(global.privKey);

}
var initRest = function () {
    global.scriptEditor = CodeMirror.fromTextArea($("#contractArea")[0], {
        matchBrackets: true,
        autoCloseBrackets: true,
        lineNumbers: true,
        height: "auto",
        mode: "application/ld+json",
        lineWrapping: true
    });
    global.responseEditor = CodeMirror.fromTextArea($("#responseArea")[0], {
        matchBrackets: true,
        autoCloseBrackets: true,
        lineNumbers: true,
        mode: "application/ld+json",
        lineWrapping: true
    });
    global.outputStreamEditor = CodeMirror.fromTextArea(
        $("#outputStreamArea")[0], {
            matchBrackets: true,
            autoCloseBrackets: true,
            lineNumbers: true,
            mode: "application/ld+json",
            lineWrapping: true
        });
    global.argEditor = CodeMirror.fromTextArea($("#argArea")[0], {
        matchBrackets: true,
        autoCloseBrackets: true,
        lineNumbers: true,
        mode: "application/ld+json",
        lineWrapping: true,
        height: "auto"
    });

    $('#tabdiv').editableSelect({
        filter: false
    });
    $("#tabdiv").on('select.editable-select', function (e) {
        // console.log("=====");
        // console.log(e);
        // console.log(e.target.value);
        // TODO;
        switchContract();
        // switchContract
    });

    //

    $('#tabdiv').addClass("ui-selectmenu-button");
    $('#tabdiv').addClass("ui-selectmenu-button-closedn");
    $('#tabdiv').addClass("ui-corner-all");
    $('#tabdiv').addClass("ui-button");
    $('#tabdiv').addClass("ui-widget");

};
// var onUploadNext = function() {
// var request = {};
// request.action = "startContract";
// request.owner = global.privKey;
// request.isPartial = false;
// request.contractid = $("#tabdiv")[0].value;
// request.path = $(".ui-tabs-active").find("a").html();
// request.script = global.toSend;
// if (request.script.length > 1024) {
// global.toSend = request.script.substr(1024);
// request.script = request.script.substr(0, 1024);
// request.isPartial = true;
// } else {
// global.toSend = "";
// }
// console.log("Upload nextPart:");
// console.log(JSON.stringify(request));
// global.wssocket.send(JSON.stringify(request));
// };

var startContract = function () {
    var request = {};
    request.action = "startContract";
    // TODO should be pubkey
    request.owner = global.privKey.publicKey;
    request.requestID = new Date().getTime() + "";
    // TODO ignore contractid
    request.contractid = $("#tabdiv")[0].value;
    request.script = global.scriptEditor.getValue();
    request.path = $(".ui-tabs-active").find("a").html();
    localStorage.setItem("persisStatus", JSON.stringify(request));
    if (request.path.startsWith("/")) {
        request.signature = sm2.doSignature("Fixed|" + request.path + "|"
            + global.privKey.publicKey, global.privKey.privateKey);
        request.script = "empty";
    } else
        request.signature = sm2.doSignature("Fixed|" + request.script + "|"
            + global.privKey.publicKey, global.privKey.privateKey);

    // console.log("path=" + request.path);

    // console.log("[scide.js] startContract() contractid = "
    // 		+ $("#tabdiv")[0].value);
    global.wssocket.send(JSON.stringify(request));
};
var executeContractWithDynamicResult = function () {
    var request = {};
    request.action = "executeContract";
    request.requestID = new Date().getTime() + "";
    request.contractID = $("#tabdiv")[0].value;
    request.arg = global.argEditor.getValue();
    request.privKey = global.privKey;
    request.withDyanmicAnalysis = true;
    localStorage.setItem("persisArg", JSON.stringify(request));
    global.wssocket.send(JSON.stringify(request));
};
var executeContract = function () {
    var request = {};
    request.action = "executeContract";
    request.requestID = new Date().getTime() + "";
    request.contractID = $("#tabdiv")[0].value;
    request.arg = global.argEditor.getValue();
    request.pubkey = global.privKey.publicKey;
    // contractID + "|" + action + "|" + arg + "|" + requester;
    var localArg = JSON.parse(request.arg);
    request.signature = sm2.doSignature(request.contractID + "|"
        + localArg.action + "|" + localArg.arg + "|"
        + global.privKey.publicKey, global.privKey.privateKey);
    localStorage.setItem("persisArg", JSON.stringify(request));
    global.wssocket.send(JSON.stringify(request));
};

function listContractProcess() {
    global.wssocket.send(JSON.stringify({
        action: 'listContractProcess',
        filters: 2
    }));
}

var killContractProcess = function () {
    var request = {};
    request.action = "killContractProcess";
    request.requestID = new Date().getTime() + "";
    request.name = $("#tabdiv")[0].value;
    request.id = global.contractName2ID[request.name];
    global.wssocket.send(JSON.stringify(request));
};
var staticVerify = function () {
    var request = {};
    request.action = "staticVerifyContract";
    // TODO should be pubkey
    request.owner = global.privKey;
    request.isPartial = false;
    // TODO ignore contractid
    request.contractid = $("#tabdiv")[0].value;
    request.script = global.scriptEditor.getValue();
    request.path = $(".ui-tabs-active").find("a").html();
    localStorage.setItem("persisStatus", JSON.stringify(request));
    if (request.path.startsWith("/"))
        request.script = "empty";
    /*
     * if (request.script.length > 1024) { global.toSend =
     * request.script.substr(1024); request.script = request.script.substr(0,
     * 1024); request.isPartial = true; }
     */
    global.wssocket.send(JSON.stringify(request));
};
var downloadContract = function () {
    if (global.lastClickedProjectId == undefined)
        global.lastClickedProjectId = 0;
    var projectName = global.projects[global.lastClickedProjectId];
    var url = window.location.href.replace("/scide.html",
        "/CMManager?action=downloadContract&projectName=");
    url += projectName;
    window.open(url);

};
var killAllContract = function () {
    var request = {};
    request.action = "killAllContract";
    global.wssocket.send(JSON.stringify(request));
};

var customAlert = function (message, title) {
    if (!title)
        title = 'Alert';

    if (!message)
        message = 'No Message to Display.';

    $('<div></div>').html(message).dialog({
        title: title,
        resizable: false,
        modal: true,
        buttons: {
            'Ok': function () {
                $(this).dialog('close');
            }
        }
    });
}
var init = function () {
    console.log("init:");
    initGlobal();
    initWSocket();
    var req = localStorage.getItem("persisStatus");
    // console.log(req);
    req = JSON.parse(req);
    if (req != undefined) {
        //	$("#tabdiv")[0].value = req.contractid;
        //global.scriptEditor.setValue(req.script);
    }

    var req2 = localStorage.getItem("persisArg");
    req2 = JSON.parse(req2);
    if (req2 != undefined && req2.arg != undefined) {
        global.argEditor.setValue(req2.arg);
    }
    initHello();
};
var getRequestParameters = function () {
    var arr = (location.search || "").replace(/^\?/, '').split("&");
    var params = {};
    for (var i = 0; i < arr.length; i++) {
        var data = arr[i].split("=");
        if (data.length == 2) {
            params[data[0]] = data[1];
        }
    }
    return params;
};
var getTemplate1 = function (name, list, expiredDate) {
    var tem = "contract _cname {\n  \t//数据清洗逻辑\n    function deleteKeys(result,list){\n\t\tfor (var key in list)\n  \t\t\tdelete result[list[key]];\n  \t\tfor (var key in result){\n  \t\t\tif (typeof result[key] == 'object'){\n  \t\t\t\tdeleteKeys(result[key],list);\t\n\t\t\t}\n\t\t}\n  \t\treturn JSON.stringify(result);\n\t}\n\n  \texport function filter(arg){\n  \t\tvar result = JSON.parse(arg);\n\t\tvar list = _list;\n  \t\tlist = list.split(\",\");\n  \t\treturn deleteKeys(result,list);\n\t}\n\t//数据处理逻辑\n\tfunction handle(obj){\n    \n    }\n\texport function get(arg){\n      if (new Date().getTime()<_expiredDate)\n        return \"Permission Denied\";\n\t\tvar result = YancloudUtil.httpGet(arg);\n        result = JSON.parse(result);\n      \tif (result.resposeCode==200){\n  \t\t\treturn handle(filter(result.response));\n        } else { return result; }\n\t}\n}";
    tem = tem.replace("_cname", name);
    tem = tem.replace("_list", JSON.stringify(list));
    tem = tem.replace("_expiredDate", expiredDate);
    return tem;
};
var getTemplate2 = function (name, list, expiredDate) {
    var tem = "contract _cname {\n    //数据清洗逻辑\n  \tfunction inVal(key,list){\n\t\tfor (var i=0;i<list.length;i++)\n  \t\t\tif (list[i]==key) return true;\n  \t\treturn false;\n\t}\n  \tfunction reserveKeys(result,list){\n  \t\tvar ret = {};\n\t\tvar hasVal = false;\n  \t\tfor (var key in result){\n  \t\t\tif (inVal(key,list)) {\n  \t\t\t\tret[key] = result[key];\n              \thasVal = true;\n\t\t\t}\n          \tvar isObject =( typeof result[key] == 'object');\n            if (isObject){\n\t\t\t\tvar val = reserveKeys(result[key],list);\n          \t\tif (val!=undefined) {\n          \t\t\tret[key] = val;\n          \t\t\thasVal = true;\n        \t\t}\n\t\t\t} \n\t\n\t\t}\n\t\tif (hasVal)\n  \t\t\treturn ret;\n\t\telse\treturn undefined;\n\t}\n  \tfunction filter(arg){\n  \t\tvar result = JSON.parse(arg);\n\t\tvar list = _list;\n  \t\tlist = list.split(\",\");\n  \t\treturn reserveKeys(result,list);\n\t}\n    function handle(obj){\n      return JSON.stringify(obj);\n    }\n    //数据处理逻辑\n\texport function get(arg){\n\t\tif (new Date().getTime()<_expiredDate)\n          return \"Permission Denied\";\n        var result = YancloudUtil.httpGet(arg);\n        result = JSON.parse(result);\n      \tif (result.resposeCode==200){\n  \t\t     var ret =  filter(result.response);\n            handle(ret);\n        } else { return result; }\n\t}\n}";
    tem = tem.replace("_cname", name);
    tem = tem.replace("_list", JSON.stringify(list));
    tem = tem.replace("_expiredDate", expiredDate);
    return tem;
};
var initHello = function () {
    var param = getRequestParameters();
    var type = parseInt(param["type"]);
    var template;
    switch (type) {
        case 1:
            template = getTemplate1(param["name"], decodeURI(param["list"]),
                param["expiredDate"]);
            break;
        case 2:
            template = getTemplate2(param["name"], decodeURI(param["list"]),
                param["expiredDate"]);
            break;
        case 3:
            var contractID = param["contractID"];
            $.ajax({
                url: "./SCManager?action=getCodeByID&contractID=" + contractID,
                dataType: "json"
            }).done(function (result) {
                global.fileContentMap.set(contractID, result.data);
                addTab({
                    "title": contractID
                });
            });
            return;
        default:
            return;
    }
    global.scriptEditor.setValue(template);
};