var defaultEvent = {}
var proto = {}

function uuidv4() {
return ([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g, c =>
    (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)
);
}

var api = {
    token: "",
    roomToken: "",
    event: null,
    ws: null,

    init(token, event) {
        this.token = token
        this.event = event || defaultEvent 

        protobuf.load("/static/game.proto", function (err, root) {
            if (err)
                throw err;

            proto.Ping = root.lookupType("Ping");
            proto.JoinRoom = root.lookupType("JoinRoom");
            proto.LeaveRoom = root.lookupType("LeaveRoom");
            proto.CreateRoom = root.lookupType("CreateRoom");
            proto.Connect = root.lookupType("Connect");
            proto.Disconnect = root.lookupType("Disconnect");
            proto.Ready = root.lookupType("Ready");

            proto.UnReady = root.lookupType("UnReady");
            proto.Start = root.lookupType("Start");
            proto.ChooseMaster = root.lookupType("ChooseMaster");
            proto.ChooseMasterFinish = root.lookupType("ChooseMasterFinish");
            proto.ChooseMul = root.lookupType("ChooseMul");
            proto.ChooseMulFinish = root.lookupType("ChooseMulFinish");
            proto.Open = root.lookupType("Open");
            proto.OpenFinish = root.lookupType("OpenFinish");
            proto.GameInit = root.lookupType("GameInit");
            proto.MsgResp = root.lookupType("MsgResp");
                                    
            proto.NotifyTypeEnum = root.lookupEnum("NotifyTypeEnum");

            console.log(proto)
        })
    },

    startWS() {
        //debug_auth 是调试，其他用之前的模式
        //const connectStr = "wss://nn.daxia.dev/connect?debug_auth=ucqrjnhiyHfuUrmR"
        const connectStr = "ws://localhost:18879/connect?debug_auth=ucqrjnhiyHfuUrmR"
        var ws = new WebSocket(connectStr);
        this.ws = ws;

        var token = this.token

        ws.onmessage = async (evt) => {
            console.log("ok:", evt)
            var received_msg = evt.data;
            var buffer = await received_msg.arrayBuffer()

            var array = new Uint8Array(buffer);
            var arrayLen = array.length;

            var dataType = array[0]
            var eventType = array[1]
            var data = array.subarray(2)

            if (dataType != 0) {
                console.log("TODO:需要处理压缩和解密====")
                data = decrypt("sBWBAyOaGqkuEhCw", "sBWBAyOaGqkuEhCw", array.subarray(1))
                eventType = data[0]

                data = data.subarray(1)
                console.log("data==>", data)
            }

            console.log("data type:", dataType)
            console.log("event type:", eventType)
            console.log("data:", data, " len:", data.length)
                        
            var decodedMessage = printMsg(eventType, data)
            if(this.event){
                this.event(eventType, decodedMessage)
            }
        }

        ws.onopen = () => {
            // Web Socket 已连接上，使用 send() 方法发送数据                
            let msg = { "type": "connect", "once": 123, "token": token }
            ws.send(JSON.stringify(msg));

            setInterval(() => {
                let msg = { "type": "ping" }
                ws.send(JSON.stringify(msg));
            }, 5000)
        };

        ws.onclose = function () {
            // 关闭 websocket
            console.log("连接已关闭...");
        };
    },

    joinRoom(roomID, chairID) {
        var guid = uuidv4();
        console.log("guid:", guid)

        let msg = {
            "type": "perform",
            "version": "1.0.0",
            "name": "room/join",
            "body": {
                "room_id": roomID,
                "chair_id": chairID,
            },
            "once": guid
        }

        console.log("join room:", msg)
        msg.body = JSON.stringify(msg.body)
        this.ws.send(JSON.stringify(msg))
    },

    leaveRoom() {
        var guid = uuidv4();
        let msg = {
            "type": "perform",
            "version": "1.0.0",
            "name": "room/leave",
            "body": {
            },
            "once": guid
        }

        msg.body = JSON.stringify(msg.body)
        this.ws.send(JSON.stringify(msg))
    },

    createRoom(roomType, passwd) {
        var guid = uuidv4();
        let msg = {
            "type": "perform",
            "version": "1.0.0",
            "name": "room/create",
            "body": {
                "passwd": passwd,
                "room_type": roomType,
            },
            "once": guid
        }

        msg.body = JSON.stringify(msg.body)
        this.ws.send(JSON.stringify(msg))
    },

    ready() {
        var guid = uuidv4();

        console.log("ready")
        let msg = {
            "type": "perform",
            "version": "1.0.0",
            "name": "qznn/ready",
            "body": {
            },
            "once": guid
        }

        msg.body = JSON.stringify(msg.body)
        this.ws.send(JSON.stringify(msg))
    },
    unready() {
        var guid = uuidv4();

        console.log("unready")
        let msg = {
            "type": "perform",
            "version": "1.0.0",
            "name": "qznn/unready",
            "body": {
            },
            "once": guid
        }

        msg.body = JSON.stringify(msg.body)
        this.ws.send(JSON.stringify(msg))
    },

    chooseMaster() {
        var guid = uuidv4();

        console.log("chooseMaster")
        let msg = {
            "type": "perform",
            "version": "1.0.0",
            "name": "qznn/choose_master",
            "body": {
                "mul": 1,
            },
            "once": guid
        }

        msg.body = JSON.stringify(msg.body)
        this.ws.send(JSON.stringify(msg))
    },

    chooseMul() {
        var guid = uuidv4();

        console.log("choose_mul")
        let msg = {
            "type": "perform",
            "version": "1.0.0",
            "name": "qznn/choose_mul",
            "body": {
                "mul": 1,
            },
            "once": guid
        }

        msg.body = JSON.stringify(msg.body)
        this.ws.send(JSON.stringify(msg))
    },

    open() {
        var guid = uuidv4();

        console.log("open")
        let msg = {
            "type": "perform",
            "version": "1.0.0",
            "name": "qznn/open",
            "body": {
            },
            "once": guid
        }

        msg.body = JSON.stringify(msg.body)
        this.ws.send(JSON.stringify(msg))
    }
}

function printMsg(eventType, data) {
    var decodedMessage = null;
    try {
        switch (eventType) {
            case proto.NotifyTypeEnum.values['NotifyTypePing']:
                decodedMessage = proto.Ping.decode(data);
                break;
            case proto.NotifyTypeEnum.values['NotifyTypeConnect']:
                decodedMessage = proto.Connect.decode(data);
                break;
            case proto.NotifyTypeEnum.values['NotifyTypeDisconnect']:
                decodedMessage = proto.Disconnect.decode(data);
                break;
            case proto.NotifyTypeEnum.values['NotifyTypeJoinRoom']:
                decodedMessage = proto.JoinRoom.decode(data);
                break;
            case proto.NotifyTypeEnum.values['NotifyTypeLeaveRoom']:
                decodedMessage = proto.LeaveRoom.decode(data);
                break;
            case proto.NotifyTypeEnum.values['NotifyTypeCreateRoom']:
                decodedMessage = proto.CreateRoom.decode(data);
                break;
            case proto.NotifyTypeEnum.values['NotifyTypeReady']:
                decodedMessage = proto.Ready.decode(data);
                break;
            case proto.NotifyTypeEnum.values['NotifyTypeUnReady']:
                decodedMessage = proto.UnReady.decode(data);
                break;
            case proto.NotifyTypeEnum.values['NotifyTypeStart']:
                decodedMessage = proto.Start.decode(data);
                break;
            case proto.NotifyTypeEnum.values['NotifyTypeChooseMaster']:
                decodedMessage = proto.ChooseMaster.decode(data);
                break;
            case proto.NotifyTypeEnum.values['NotifyTypeChooseMasterFinish']:
                decodedMessage = proto.ChooseMasterFinish.decode(data);
                break;
            case proto.NotifyTypeEnum.values['NotifyTypeChooseMul']:
                decodedMessage = proto.ChooseMul.decode(data);
                break;
            case proto.NotifyTypeEnum.values['NotifyTypeChooseMulFinish']:
                decodedMessage = proto.ChooseMulFinish.decode(data);
                break;
            case proto.NotifyTypeEnum.values['NotifyTypeOpen']:
                decodedMessage = proto.Open.decode(data);
                break;
            case proto.NotifyTypeEnum.values['NotifyTypeOpenFinish']:
                decodedMessage = proto.OpenFinish.decode(data);
                break;                
            case proto.NotifyTypeEnum.values['NotifyTypeGameInit']:
                decodedMessage = proto.GameInit.decode(data);
                break;
            case proto.NotifyTypeEnum.values['NotifyTypeMsgResp']:
                decodedMessage = proto.MsgResp.decode(data);
                break;
            default:
                throw ("没找到类型:", eventType)
        }
    } catch (e) {
        console.log("err:", e)
        return
    }

    console.log("decode msg", Date().toLocaleString(), "==>", decodedMessage)
    return decodedMessage
}

export default api