import WebSocketService from '@/domain/services/WebSocketService.js'
import {WebSocket, Server} from 'mock-socket'
import DeviceStateSocketApi from '@/api/websocketApis/DeviceStateSocketApi'
import AlarmService from '@/domain/services/AlarmService.js'
import Vue from "vue";
import {
  WS_CONFORM_INIT, WS_CONFORM, WS_CONFORM_SUCCESS,
  WS_CLEAR_INIT, WS_CLEAR, WS_CLEAR_SUCCESS,
  DEVICE_COLLECTION, LINK_COLLECTION, TOPOLOGY_COLLECTION,
  WS_DISCOVER, WS_DISCOVER_SUCCESS,
  WS_RECOVER_INIT, WS_RECOVER, WS_RECOVER_SUCCESS,
  PANIC_MSG
} from "../../../../mock/websocket/wsAlarmServiceMock";
import {
  ALARM_CLEAR_STATUS_ENUM,
  ALARM_COMFIRM_STATUS_ENUM,
  DISCOVER_STATUS_ENUM
} from "../../../../../src/utils/constantCollection";
import HelperUtil from "../../../../../src/utils/HelperUtil";
import LinkService from "../../../../../src/domain/services/LinkService";

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

  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 === '5') {
          socket.send(JSON.stringify(WS_CONFORM))
          console.log('server is sending message:', WS_CONFORM)
        } else if (msg === '6') {
          socket.send(JSON.stringify(WS_CLEAR))
          console.log('server is sending message:', WS_CLEAR)
        } else if (msg === '7') {
          socket.send(JSON.stringify(WS_DISCOVER))
          console.log('server is sending message:', WS_DISCOVER)
        } else if (msg === '8') {
          socket.send(JSON.stringify(WS_RECOVER))
          console.log('server is sending message:', WS_RECOVER)
        } else {
          socket.send(JSON.stringify(PANIC_MSG))
          console.log('server is panic')
        }
      })
    })
    websocketSvc = WebSocketService(DeviceStateSocketApi, {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 AlarmConform', function (done) {
    const WAIT_FINISH_TIME = 100
    const WAIT_RECEIVE_MSG_TIME = 50

    // subscribe message bark
    let barkMessages = WS_CONFORM_INIT

    websocketSvc.subscribe(DeviceStateSocketApi.MsgType.CONFIRM_ALARM, barkMessages, (returnObject) => {
      for (var i = 0; i < returnObject.length; i++) {
        Vue.set(barkMessages[returnObject[i]],"alarmStatus",ALARM_COMFIRM_STATUS_ENUM);
      }
    });

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

    // 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).to.deep.equal(WS_CONFORM_SUCCESS)
    }, WAIT_RECEIVE_MSG_TIME)

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

  it('should AlarmClear', function (done) {
    const WAIT_FINISH_TIME = 100
    const WAIT_RECEIVE_MSG_TIME = 50

    // subscribe message bark
    let barkMessages = WS_CLEAR_INIT
    websocketSvc.subscribe(DeviceStateSocketApi.MsgType.CLEAR_ALARM, barkMessages, (returnObject) => {
      for (var i = 0; i < returnObject.length; i++) {
        Vue.set(barkMessages[returnObject[i]],"alarmStatus",ALARM_CLEAR_STATUS_ENUM);
      }
    });

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

    // 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).to.deep.equal(WS_CLEAR_SUCCESS)
    }, WAIT_RECEIVE_MSG_TIME)

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

  it('should FindAlarm', function (done) {
    const WAIT_FINISH_TIME = 100
    const WAIT_RECEIVE_MSG_TIME = 50

    // subscribe message bark
    let barkMessages = {}
    websocketSvc.subscribe(DeviceStateSocketApi.MsgType.ADD_ALARM, barkMessages, (returnObject) => {
      // 将 新增对象 中添加 deviceName 字段名
      for (var deviceKey in DEVICE_COLLECTION) {
        if (returnObject.deviceKey === deviceKey) {
          Vue.set(returnObject, "deviceName", DEVICE_COLLECTION[deviceKey].deviceName);
          break;
        }
      }
      // 将新建对象添加到 alarmList 中
      Vue.set(barkMessages, returnObject.alarmKey, returnObject);
      // 将告警设备的状态更新到设备结点上
      // Note: 设备信息显示最高级告警信息
      AlarmService.updateDeviceAndTopologyAndServerStatus(barkMessages, DEVICE_COLLECTION, TOPOLOGY_COLLECTION);
      for(var linkKey in LINK_COLLECTION){
        if(LINK_COLLECTION[linkKey].startDeviceKey === returnObject.deviceKey || LINK_COLLECTION[linkKey].endDeviceKey === returnObject.deviceKey){
          LinkService.updateLinkStatusByAlarmCause(LINK_COLLECTION,DEVICE_COLLECTION,barkMessages,LINK_COLLECTION[linkKey]);
        }
      }
    });

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

    // 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).to.deep.equal(WS_DISCOVER_SUCCESS)
    }, WAIT_RECEIVE_MSG_TIME)

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

  it('should RecoverAlarm', function (done) {
    const WAIT_FINISH_TIME = 100
    const WAIT_RECEIVE_MSG_TIME = 50

    // subscribe message bark
    let barkMessages = WS_RECOVER_INIT
    websocketSvc.subscribe(DeviceStateSocketApi.MsgType.RECOVER_ALARM, barkMessages, (returnObject) => {
      Vue.delete(barkMessages, returnObject.alarmKey);
      AlarmService.updateDeviceAndTopologyAndServerStatus(barkMessages, DEVICE_COLLECTION, TOPOLOGY_COLLECTION);
      for(var linkKey in LINK_COLLECTION){
        if(LINK_COLLECTION[linkKey].startDeviceKey === returnObject.deviceKey || LINK_COLLECTION[linkKey].endDeviceKey === returnObject.deviceKey){
          LinkService.updateLinkStatusByAlarmCause(LINK_COLLECTION,DEVICE_COLLECTION,barkMessages,LINK_COLLECTION[linkKey]);
        }
      }
    });

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

    // 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).to.deep.equal(WS_RECOVER_SUCCESS)
    }, WAIT_RECEIVE_MSG_TIME)

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

