import { Message } from 'element-ui'
import {
  subscribe,
  publish
} from '@/utils/mqtt'

const cache = new Map()
let listening = false

export function watch ({ productId, id }, cb, expired) {
  if (!listening) {
    subscribe('+/+/screenshot/reply', onMessage)
    listening = true
  }
  let inst = cache.get(id)
  if (inst) {
    inst.cb = cb
  } else {
    cache.set(id, inst = createInst(productId, id, cb))
  }
  if (retry(inst, expired)) {
    screenshot(id, true)
  } else {
    cb(inst)
  }
}

function retry (inst, expired = 30000) {
  if (!inst) {
    return false
  }
  if (inst.waiting && inst.timestamp + 10000 >= Date.now()) {
    return false
  }
  if (inst.base64 && inst.timestamp + expired >= Date.now()) {
    return false
  }
  return true
}

export function unwatch (deviceId) {
  const inst = cache.get(deviceId)
  if (inst) {
    inst.cb = null
  }
}

export function screenshot (deviceId, silence) {
  const inst = cache.get(deviceId)
  if (inst) {
    inst.waiting = true
    inst.timestamp = Date.now()
    inst.base64 = null
    publish(`${inst.productId}/${inst.deviceId}/screenshot/ask`, JSON.stringify({ timestamp: inst.timestamp })).then(
      () => {
        startTimer(inst)
      },
      () => {
        inst.waiting = false
        if (!silence) {
          Message({
            type: 'warning',
            message: '正在连接，请稍后再试'
          })
        }
      }
    ).finally(() => {
      emit(inst)
    })
  }
}

function createInst (productId, deviceId, cb) {
  return {
    productId,
    deviceId,
    cb,
    timer: -1,
    waiting: false,
    timestamp: Date.now(),
    base64: null
  }
}

function startTimer (inst) {
  clearTimeout(inst.timer)
  inst.timer = setTimeout(() => {
    inst.waiting = false
    emit(inst)
  }, 20000)
}

function emit (inst) {
  inst.cb && inst.cb(inst)
}

function onMessage (topic, message) {
  const result = /^(\d+)\/(\d+)\/screenshot\/reply$/.exec(topic)
  if (result) {
    const inst = cache.get(result[2])
    if (inst) {
      clearTimeout(inst.timer)
      inst.waiting = false
      inst.timestamp = Date.now()
      inst.base64 = `data:image/jpeg;base64,${message.replace(/\s/g, '')}`
      emit(inst)
    }
  }
}

export function remove (deviceId) {
  const inst = cache.get(deviceId)
  if (inst) {
    clearTimeout(inst.timer)
    inst.waiting = false
    inst.base64 = null
    emit(inst)
  }
}
