import WebSocketService from '@/domain/services/WebSocketService.js'
import { WebSocket, Server } from 'mock-socket'
import DeviceStateSocketApi from '@/api/websocketApis/DeviceStateSocketApi'
import Vue from "vue";

describe('ElineWebSocketService', () => {
  const fakeURL = 'ws://localhost:8080'
  var mockServer = null
  var websocketSvc = null
  const WS_ADD = {
    "objectOption":0,
    "objectType":6,
    "returnObject":{
      "ccmInterval":1,
      "cosId":3,
      "elineStatus":"SUBMITTED",
      "encapsulationType":1,
      "end1DeviceId":"of:0000001e080c900c",
      "end1DevicePort":1,
      "end2DeviceId":"",
      "end2DevicePort":0,
      "isDualHomed":1,
      "l2AccessType":1,
      "limitedBandwidth":1000,
      "oamInfo":1,
      "protectionMode":0,
      "qosProfile":"Default",
      "reversion":1,
      "serviceName":"service-1",
      "serviceSubnetID":"",
      "serviceTypeID":"",
      "startDeviceId":"of:0000001e080e180b",
      "startDevicePort":1,
      "startTime":"",
      "vlanAccess":0,
      "vlanRangeEnd":12,
      "vlanRangeStart":2,
      "vlanSet":"",
      "vpnId":"service-1",
      "wtr":2
    }
  }

  const WS_ADD_SUCCESS={"service-1":
      {
        "ccmInterval":1,
        "cosId":3,
        "elineStatus":"SUBMITTED",
        "encapsulationType":1,
        "end1DeviceId":"of:0000001e080c900c",
        "end1DevicePort":1,
        "end2DeviceId":"",
        "end2DevicePort":0,
        "isDualHomed":1,
        "l2AccessType":1,
        "limitedBandwidth":1000,
        "oamInfo":1,
        "protectionMode":0,
        "qosProfile":"Default",
        "reversion":1,
        "serviceName":"service-1",
        "serviceSubnetID":"",
        "serviceTypeID":"",
        "startDeviceId":"of:0000001e080e180b",
        "startDevicePort":1,
        "startTime":"",
        "vlanAccess":0,
        "vlanRangeEnd":12,
        "vlanRangeStart":2,
        "vlanSet":"",
        "vpnId":"service-1",
        "wtr":2
      }
  }

  const WS_MODIFY_INIT={"service-1":
      {
        "ccmInterval":1,
        "cosId":3,
        "elineStatus":"SUBMITTED",
        "encapsulationType":1,
        "end1DeviceId":"of:0000001e080c900c",
        "end1DevicePort":1,
        "end2DeviceId":"",
        "end2DevicePort":0,
        "isDualHomed":1,
        "l2AccessType":1,
        "limitedBandwidth":1000,
        "oamInfo":1,
        "protectionMode":0,
        "qosProfile":"Default",
        "reversion":1,
        "serviceName":"service-1",
        "serviceSubnetID":"",
        "serviceTypeID":"",
        "startDeviceId":"of:0000001e080e180b",
        "startDevicePort":1,
        "startTime":"",
        "vlanAccess":0,
        "vlanRangeEnd":12,
        "vlanRangeStart":2,
        "vlanSet":"",
        "vpnId":"service-1",
        "wtr":2
      }
  }

  const WS_MODIFY={
    "objectOption":2,
    "objectType":6,
    "returnObject":{
      "elineStatus":"SUCCESS","vpnId":"service-1"
    }
  }

  const WS_MODIFY_SUCCESS={"service-1":
      {
        "ccmInterval":1,
        "cosId":3,
        "elineStatus":"SUCCESS",
        "encapsulationType":1,
        "end1DeviceId":"of:0000001e080c900c",
        "end1DevicePort":1,
        "end2DeviceId":"",
        "end2DevicePort":0,
        "isDualHomed":1,
        "l2AccessType":1,
        "limitedBandwidth":1000,
        "oamInfo":1,
        "protectionMode":0,
        "qosProfile":"Default",
        "reversion":1,
        "serviceName":"service-1",
        "serviceSubnetID":"",
        "serviceTypeID":"",
        "startDeviceId":"of:0000001e080e180b",
        "startDevicePort":1,
        "startTime":"",
        "vlanAccess":0,
        "vlanRangeEnd":12,
        "vlanRangeStart":2,
        "vlanSet":"",
        "vpnId":"service-1",
        "wtr":2
      }
  }
  const WS_DELETE_INIT={"service-1":
      {
        "ccmInterval":1,
        "cosId":3,
        "elineStatus":"SUBMITTED",
        "encapsulationType":1,
        "end1DeviceId":"of:0000001e080c900c",
        "end1DevicePort":1,
        "end2DeviceId":"",
        "end2DevicePort":0,
        "isDualHomed":1,
        "l2AccessType":1,
        "limitedBandwidth":1000,
        "oamInfo":1,
        "protectionMode":0,
        "qosProfile":"Default",
        "reversion":1,
        "serviceName":"service-1",
        "serviceSubnetID":"",
        "serviceTypeID":"",
        "startDeviceId":"of:0000001e080e180b",
        "startDevicePort":1,
        "startTime":"",
        "vlanAccess":0,
        "vlanRangeEnd":12,
        "vlanRangeStart":2,
        "vlanSet":"",
        "vpnId":"service-1",
        "wtr":2
      }
  }
  const WS_DELETE={
    "objectOption":1,
    "objectType":6,
    "returnObject":"service-1"
  }
  const WS_DELETE_SUCCESS = {}

  const PANIC_MSG = {
    objectOption:-1,
    objectType:-1,
    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 === '0') {
          socket.send(JSON.stringify(WS_ADD))
          console.log('server is sending message:', WS_ADD)
        } else if(msg === '1'){
          socket.send(JSON.stringify(WS_DELETE))
          console.log('server is sending message:', WS_DELETE)
        }else if(msg === '2'){
          socket.send(JSON.stringify(WS_MODIFY))
          console.log('server is sending message:', WS_MODIFY)
        }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 AddEline', function (done) {
    const WAIT_FINISH_TIME = 100
    const WAIT_RECEIVE_MSG_TIME = 50

    // subscribe message bark
    let barkMessages = {}
    websocketSvc.subscribe(DeviceStateSocketApi.MsgType.ADD_ELINE, barkMessages, (returnObject) => {
      Vue.set(barkMessages,returnObject.vpnId,returnObject);
    });

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

    // 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_ADD_SUCCESS)
    }, WAIT_RECEIVE_MSG_TIME)

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

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

    // subscribe message bark
    let barkMessages = WS_DELETE_INIT
    websocketSvc.subscribe(DeviceStateSocketApi.MsgType.DELETE_ELINE, barkMessages, (returnObject) => {
      Vue.delete(barkMessages,returnObject);
    });

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

    // 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_DELETE_SUCCESS)
    }, WAIT_RECEIVE_MSG_TIME)

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

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

    // subscribe message bark
    let barkMessages = WS_MODIFY_INIT
    websocketSvc.subscribe(DeviceStateSocketApi.MsgType.MODIFY_ELINE, barkMessages, (returnObject) => {
      barkMessages[returnObject.vpnId].elineStatus = returnObject.elineStatus;
    });

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

    // 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_MODIFY_SUCCESS)
    }, 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)
  // })
})
