const protocal = {
    protocol: 'json',
    version: 1,
}

const MessageType = {
    /** Indicates the message is an Invocation message and implements the {@link InvocationMessage} interface. */
    Invocation: 1,
    /** Indicates the message is a StreamItem message and implements the {@link StreamItemMessage} interface. */
    StreamItem: 2,
    /** Indicates the message is a Completion message and implements the {@link CompletionMessage} interface. */
    Completion: 3,
    /** Indicates the message is a Stream Invocation message and implements the {@link StreamInvocationMessage} interface. */
    StreamInvocation: 4,
    /** Indicates the message is a Cancel Invocation message and implements the {@link CancelInvocationMessage} interface. */
    CancelInvocation: 5,
    /** Indicates the message is a Ping message and implements the {@link PingMessage} interface. */
    Ping: 6,
    /** Indicates the message is a Close message and implements the {@link CloseMessage} interface. */
    Close: 7,
}

export class HubConnection {

    // 构造函数
    constructor() {
        this.connection = {}
        this.openStatus = false
        this.invocationId = 0
    }

    // 创建链接
    connectSocket(option = {}) {
        if (this.connection != null && this.openStatus) {
            return
        }

        this.connection = uni.connectSocket({
            ...option,
            success: () => {
                console.log('建立连接成功')
            },
            fail: () => {
                console.log('建立连接失败')
            },
        })
        this.onOpen(() => {
            console.log('连接打开')
            this.openStatus = true
            this.send(protocal)
        })
        this.onClose(() => {
            console.log('连接关闭')
            this.connection = null
            this.openStatus = false
        })
        this.onError(res => {
            console.error('连接出错：' + res.errMsg)
        })
    }

    // 监听连接打开事件
    onOpen(callback) {
        this.connection.onOpen(res => {
            callback(res)
        })
    }

    // 监听连接关闭事件
    onClose(callback) {
        this.connection.onClose(res => {
            callback(res)
        })
    }

    // 监听连接错误事件
    onError(callback) {
        this.connection.onError(res => {
            callback(res)
        })
    }

    // 接收服务器消息事件
    onMessage(callback) {
        this.connection.onMessage(res => {
            let data = res.data.split('')
            data.length = data.length - 1

            data.forEach(item => {
                let message = JSON.parse(item)
                if (message.type === MessageType.Invocation) {
                    callback(message)
                } else if (message.type === MessageType.Completion) {
                    if (message.error) {
                        console.error(message.error)
                    }
                }
            })
        })
    }

    // 发送数据
    send(data, success, fail) {
        this.connection.send({
            data: JSON.stringify(data) + '',
            success: success,
            fail: fail,
        })
    }

    // 发送消息
    sendData(functionName) {
        let args = []
        for (let i = 1; i < arguments.length; i++) {
            args[i - 1] = arguments[i]
        }

        let data = {
            target: functionName,
            arguments: args,
            type: MessageType.Invocation,
            invocationId: this.invocationId.toString(),
        }
        this.invocationId++

        return new Promise((resolve, reject) => {
            this.connection.send({
                data: JSON.stringify(data) + '',
                success: res => {
                    resolve(res)
                },
                fail: res => {
                    reject(res)
                },
            })
        })
    }

    // 关闭连接
    close(option = {}) {
        this.connection.close({
            code: option.code || 1000,
            reason: option.reason || '客户端主动关闭',
            success: () => {
                this.openStatus = false
                console.log('主动关闭连接')
            },
            fail: res => {
                console.log('主动关闭连接失败')
                console.log(res)
            },
        })
    }
}