import WebSocketService from '@/domain/services/WebSocketService.js'
import { WebSocket, Server } from 'mock-socket'
import ListenerUtil from '@/utils/ListenerUtil'

// First define a mock websocket api
let MockSocketApi = {
  MsgType: {
    BARK: 'dog:bark',
    BITE: 'dog:bite',
    SWIM: 'dog:swim'
  },
  /**
   * 获取消息类型
   * @param message 消息
   * @returns {string} 类型字符串 'objectType:objectOption'
   */
  getMessageType: function (message) {
    return String(message.objectType) + ':' + String(message.objectOption)
  },
  /**
   * 获取消息数据
   * @param message 消息
   * @returns {Object} 消息数据
   */
  getMessageData: function (message) {
    return message.returnObject
  }
}

// 增加创建消息监听器的方法
var emptyListenerRegistry = ListenerUtil.parseListenerRegistry(MockSocketApi.MsgType)
MockSocketApi.createMessageListenerRegistry = function () {
  return Object.assign({}, emptyListenerRegistry)
}

describe('WebSocketService', () => {
  const fakeURL = 'ws://localhost:8080'
  var mockServer = null
  var websocketSvc = null

  const BARK_MSG = {
    objectType: 'dog',
    objectOption: 'bark',
    returnObject: 'won won won...'
  }

  const PANIC_MSG = {returnObject: 'I am panic!'}

  before(function () {
    // 设置WebSocket为mock-socket提供的WebSocket，以便能够使用假数据测试
    global.WebSocket = WebSocket
  })

  after(function () {
    // 恢复WebSocket为jsdom提供的WebSocket对象
    global.WebSocket = window.WebSocket
  })

  beforeEach(function () {
    mockServer = new Server(fakeURL)
    mockServer.on('connection', function (socket) {
      console.log('server connected')
      socket.on('message', function (data) {
        let msg = JSON.parse(data)
        console.log('server try to respond to', msg)
        if (msg === 'bark') {
          socket.send(JSON.stringify(BARK_MSG))
          console.log('server is sending message:', BARK_MSG)
        } else {
          socket.send(JSON.stringify(PANIC_MSG))
          console.log('server is panic')
        }
      })
    })
    websocketSvc = WebSocketService(MockSocketApi, {URL: fakeURL})
  })

  it('should open', function (done) {
    const WAIT_FINISH_TIME = 100
    const WAIT_SOCKE_OPEN_TIME = 50

    websocketSvc.open()
    expect(websocketSvc.isConnecting()).to.be.true

    setTimeout(() => {
      expect(websocketSvc.isOpen()).to.be.true
    }, WAIT_SOCKE_OPEN_TIME)

    // 延迟结束本测试
    setTimeout(() => {
      mockServer.stop(done)
    }, WAIT_FINISH_TIME)
  })

  it('should send message and receive subscribed message', function (done) {
    const WAIT_FINISH_TIME = 100
    const WAIT_RECEIVE_MSG_TIME = 50

    // subscribe message bark
    let barkMessages = []
    websocketSvc.subscribe(MockSocketApi.MsgType.BARK, barkMessages, function (barkMsg) {
      barkMessages.push(barkMsg)
    })

    // socket打开时发送消息
    websocketSvc.subscribeToOpen(this, function () {
      websocketSvc.send('bark')
    })

    // open the socket and send bark to receive bark message
    websocketSvc.open()

    setTimeout(() => {
      expect(barkMessages).to.have.lengthOf(1)
      console.log('client received message: ', barkMessages[0])
      expect(barkMessages[0]).to.deep.equal(BARK_MSG.returnObject)
    }, WAIT_RECEIVE_MSG_TIME)

    // 延迟结束本测试
    setTimeout(() => {
      mockServer.stop(done)
    }, WAIT_FINISH_TIME)
  })

  // it('should handle unknown message', function (done) {
  //   const WAIT_FINISH_TIME = 100
  //   const WAIT_RECEIVE_MSG_TIME = 50
  //
  //   // subscribe message bark
  //   let unknownMsgs = []
  //   websocketSvc.subscribeToUnknownMessage(unknownMsgs, function (msg) {
  //     console.log('client received an unknown message: ', msg)
  //     unknownMsgs.push(msg)
  //   })
  //
  //   // socket打开时发送消息
  //   websocketSvc.subscribeToOpen(this, function () {
  //     websocketSvc.send('roar...')
  //   })
  //
  //   // open the socket and send bark to receive bark message
  //   websocketSvc.open()
  //
  //   setTimeout(() => {
  //     expect(unknownMsgs).to.have.lengthOf(1)
  //     expect(unknownMsgs[0]).to.deep.equal(PANIC_MSG.returnObject)
  //   }, WAIT_RECEIVE_MSG_TIME)
  //
  //   // 延迟结束本测试
  //   setTimeout(() => {
  //     mockServer.stop(done)
  //   }, WAIT_FINISH_TIME)
  // })
  //
  // it('should close', function (done) {
  //   const WAIT_FINISH_TIME = 100
  //   const WAIT_SOCKE_OPEN_TIME = 20
  //   const WAIT_SOCKE_CLOSE_TIME = 50
  //
  //   websocketSvc.open()
  //
  //   setTimeout(() => {
  //     expect(websocketSvc.isOpen()).to.be.true
  //     websocketSvc.close()
  //     expect(websocketSvc.isClosing()).to.be.true
  //   }, WAIT_SOCKE_OPEN_TIME)
  //
  //   setTimeout(() => {
  //     expect(websocketSvc.isClosed()).to.be.true
  //   }, WAIT_SOCKE_CLOSE_TIME)
  //
  //   // 延迟结束本测试
  //   setTimeout(() => {
  //     mockServer.stop(done)
  //   }, WAIT_FINISH_TIME)
  // })
})
