/*
 WebSocket.CONNECTING   0   连接正在进行中，但还未建立
 WebSocket.OPEN	        1	连接已经建立。消息可以在客户端和服务器之间传递
 WebSocket.CLOSING	    2	连接正在进行关闭握手
 WebSocket.CLOSED	    3	连接已经关闭，不能打开
 */
// 浏览器支持了ping，但不会触发ping事件，相反，浏览器会自动响应pong

var Hiwebsocket = {
    aliveFlag : 0,   // 0 dead; 1 alive
    ws : null,
    lockReconnect : false //避免重复连接
};

Hiwebsocket.heartBeat = {
    SENDTIMEOUTVALUE : 60000, //60s
    CHECKTIMEOUTVALUE : 120000, //120s
    sendTimer : 0,
    checkTimer : 0,
    heartBeatCnter : 0,
    heartBeatSeq : 0
};

Hiwebsocket.heartBeat.sendHeartBeat = function(){
    var self = this;
    DBG_ERROR("heartBeat fisrt time: heartbeat_" + this.heartBeatSeq);
    try{
        Hiwebsocket.ws.send("heartbeat_" + this.heartBeatSeq);
    }catch(e){
        DBG_ERROR("failed to send first heartbeat");
    }
    this.sendTimer = setInterval(function(){
        if(Hiwebsocket.ws){
            self.heartBeatSeq == Number.MAX_VALUE ? self.heartBeatSeq = 0 : self.heartBeatSeq++;
            Hiwebsocket.ws.send("heartbeat_" + self.heartBeatSeq);
            DBG_ERROR("heartBeat every 60s: heartbeat_" + self.heartBeatSeq);
        }
    }, this.SENDTIMEOUTVALUE);

};
Hiwebsocket.heartBeat.reset = function(){
    DBG_INFO("heartBeatCheck.reset");
    clearTimeout(this.sendTimer);
    clearTimeout(this.checkTimer);
    this.heartBeatCnter = 0;
};

Hiwebsocket.heartBeat.checkHeartBeat = function(){
    var self = this;
    this.checkTimer = setInterval(function(){
        DBG_INFO("check heartBeat every 120s, heartBeatCnter is: " + self.heartBeatCnter);
        if(self.heartBeatCnter > 0){
            DBG_INFO("still alive");
            self.heartBeatCnter = 0;
        }else{
            DBG_INFO("dead , reconnect");
            Hiwebsocket.aliveFlag = 0;
            if(Hiwebsocket.ws != null){
                DBG_ERROR("close websocket by client");
                Hiwebsocket.ws.close(); //close websocket by client
                Hiwebsocket.ws = null;
            }
            Hiwebsocket.onReconnect();
        }
    },this.CHECKTIMEOUTVALUE);
};
Hiwebsocket.heartBeat.count = function(){
    DBG_INFO("heartBeatCheck.count is: " + this.heartBeatCnter);
    this.heartBeatCnter++;
};

Hiwebsocket.initEventHandle = function(){
    var self = this;
    this.ws.onclose = function (closeEvent) {
        //如果是响应服务端的close事件，这个值为true，如果是别的原因，比如因为是底层TCP连接关闭，wasClean为false。
        DBG_ERROR("[onclose] closeEvent wasClean is: " + closeEvent.wasClean + "; code is: " + closeEvent.code + "; reason is: " + closeEvent.reason);
    };
    this.ws.onerror = function (event) {
        DBG_ERROR("[onerror] event data is: " + event.data);
        self.ws = null;
    };
    this.ws.onopen = function () {
        DBG_INFO("[onopen] readyState is: " + self.ws.readyState);
        self.ws.binaryType = "arraybuffer";
        self.aliveFlag = 1;
        self.heartBeat.reset();
        self.heartBeat.sendHeartBeat();
        self.heartBeat.checkHeartBeat();
    };
    this.ws.onmessage = function (event) {
        var content;
        if (event.data) {
            DBG_INFO("Client received a message data: " + event.data);
        }
        self.heartBeat.count();
        try{
            content = JSON.parse(event.data);
        }catch(e){
            DBG_ERROR("receive heartbeat: " +  event.data);
            return;
        }
        var decoder_str = "";
        if (content.text) {
            DBG_INFO("Client received a message text: " + content.text);
            decoder_str = Base64.decode(content.text);
            DBG_ERROR("convert msg by Base64: " + decoder_str);
        }
        self.onMessage(decoder_str); // process msg
    }
};

Hiwebsocket.createWebSocket = function(url){
    if(1 == this.aliveFlag){
        DBG_ERROR("still alive and avoid many websocket are created");  //avoid many websocket are created
        return;
    }
    try {
        DBG_INFO("[new WebSocket] url is: " + url);
        this.ws = new WebSocket(url);
        DBG_INFO("[new WebSocket] readyState is: " + this.ws.readyState);
        this.initEventHandle();
    } catch (e) {
        DBG_ERROR("failed to create WebScoket");
    }
};

Hiwebsocket.reconnect = function(url){
    DBG_INFO("hiWebSocket reconnect");
    if(this.lockReconnect){
        DBG_ERROR("hiWebSocket is trying to connect");
        return;
    }
    this.lockReconnect = true;
    setTimeout(function () {
        Hiwebsocket.createWebSocket(url);
        Hiwebsocket.lockReconnect = false;
    }, 3000);
};

Hiwebsocket.disconnect = function(){
    DBG_INFO("hiWebSocket disconnected");
    if (this.ws != null) {
        this.ws.close();
        this.ws = null;
        this.aliveFlag = 0;
        this.heartBeat.reset();
    }
};

Hiwebsocket.onMessage = function(msg){
    //The func will be overwrite
};
Hiwebsocket.onReconnect = function(){
    //The func will be overwrite
};