<template>
<!-- <q-page padding >  :class="{greyedout: !connected}" > -->
<q-page padding >
<q-list class="">
<q-item class="">
  <q-item-section side>
    <q-btn :disabled="!connected" color="secondary" round @click="send" icon="send">
      <q-tooltip>
        Click to send this command and payload to the sever
      </q-tooltip>
    </q-btn>
  </q-item-section>
  <q-item-section >
    <q-item-label>Command</q-item-label>
    <q-select
        v-model="cmd"
        :options="commands"
        label="Choose An Available Command to Send"
        emit-value
      ></q-select>
  </q-item-section>
</q-item>

<q-item><div class="col">Property</div>:<div class="col">Value</div></q-item>
<q-item><q-input  class="col" readonly v-model="key[0]" />:<q-input dense class="col" v-model="value[0]" /></q-item>
<q-item><q-input class="col" label="a custom property in payload" v-model="key[1]" />:<q-input class="col" v-model="value[2]" /></q-item>
</q-list>
<q-btn :class="switches[0]" @click="toggle(1)" label="Switch 1"><q-tooltip>Click to Toggle Switch</q-tooltip></q-btn>
<q-btn :class="switches[1]" @click="toggle(2)" label="Switch 2"><q-tooltip>Click to Toggle Switch</q-tooltip></q-btn>
<q-btn :class="switches[2]" @click="toggle(3)" label="Switch 3"><q-tooltip>Click to Toggle Switch</q-tooltip></q-btn>
<q-btn :class="switches[3]" @click="toggle(4)" label="Switch 4"><q-tooltip>Click to Toggle Switch</q-tooltip></q-btn>
<q-list class="response">
<q-input  v-model="packet" readonly  label="Sending Packet:" />
<q-input  v-model="res" readonly label="Socket/Server Response Packet" />
<q-input  v-model="pushed" readonly type="textarea" label="A Packet Pushed from Socket/Server:" />
</q-list>
<div class="row">
<q-btn  size="40px" class="col q-px-xl q-py-xs" @click.left.exact="connect"  @click.shift.left.exact="disconnect" :color="online">
<q-tooltip>click to (re)connect, shift click to disconnect</q-tooltip>
Socket: {{ connection }}
</q-btn>
<div class="col">
  <q-input  v-model="initTimeout" readonly  label="Initial Connect Timeout" />
  <q-select
      v-model="statusLevel"
      :options="statusOptions"
      label="Choose Minimum Level to Dislay"
      emit-value
      map-options
    ></q-select>
</div>
<div class="col">
    Status Log: (filter level {{ statusLevel }})
    <q-scroll-area style="height: 200px">
      <div v-for="(item, index) in filteredStatusLines" :key="index" class="caption q-py-sm">
      <q-badge class="shadow-1">
        {{ item._count }}
      </q-badge>
      <q-badge :color="status(item, 'color') || 'brown'" class="shadow-1">
        {{ status(item,'name') || 'status' }}
      </q-badge>
      <q-badge v-if="item.success" color="positive" class="shadow-1">
        {{ 'success' }}
      </q-badge>
      {{ item.msg }}
      </div>
    </q-scroll-area>
  </div>
  <div class="col">

  </div>

</div>
</q-page>
</template>
<script>
import btc from 'better-try-catch'

// import {status} from './utils'
const statusLevels = {
  10: { color: 'black', name: 'trace' },
  20: { color: 'indigo', name: 'debug' },
  30: { color: 'info', name: 'info' },
  40: { color: 'warning', name: 'warning' },
  50: { color: 'red-3', name: 'error' },
  60: { color: 'negative', name: 'fatal' }
}

export default {
  data () {
    return {
      cmd: 'switch/toggle',
      connected: false,
      commands: [
        {
          label: 'turn a switch on',
          value: 'switch/on',
          description: 'turn on something',
          icon: 'mdi:lightbulb'
        },
        {
          label: 'turn a switch off',
          value: 'switch/off',
          description: 'turn off something',
          icon: 'lightbulb-off'
        },
        {
          label: 'toggle a switch',
          value: 'switch/toggle',
          description: 'turn off something',
          icon: 'mdi:lightbulb'
        },
        {
          label: 'ack',
          value: 'ack',
          description: 'send ack packet',
          icon: 'no'
        }
      ],
      packet: '',
      res: '',
      key: ['id', 'sender'],
      value: [1, 'websocket client'],
      pushed: '',
      switches: ['off', 'off', 'off', 'off'],
      statusLines: [],
      statusCount: 0,
      statusLevel: 30,
      statusOptions: [],
      name: 'test-client',
      initTimeout: 30
    }
  },
  computed: {
    online () {
      if (this.connected) return 'positive'
      else return 'warning'
    },
    connection () {
      if (this.connected) return 'Connected'
      else return 'Offline'
    },
    filteredStatusLines () {
      return this.statusLines.filter(item => { return item.level >= this.statusLevel })
    }
  },
  methods: {
    async connect () {
      this.statusClear()
      let [err, res] = await btc(this.$socket.connect)({ initTimeout: this.initTimeout * 1000, name: this.name })
      if (err) {
        this.$q.notify({
          color: 'negative',
          message: err.msg
        })
        this.connected = false
      } else {
        this.$q.notify({ color: 'positive', message: res })
        // this.$socket.listen()
        this.connected = true
      }
    },
    async disconnect () {
      await this.$socket.disconnect()
      this.clear()
      this.connected = false
    },
    async send (packet) {
      this.clear()
      if (!packet.cmd) {
        packet = {
          cmd: this.cmd,
          [this.key[0]]: this.value[0],
          [this.key[1]]: this.value[1]
        }
      }
      this.packet = JSON.stringify(packet)
      let [err, res] = await btc(this.$socket.send)(packet)
      if (err) {
        this.$q.notify({
          color: 'negative',
          message: `Error packet send, ${err}`
        })
      } else {
        delete res._header
      }
      // display on UI
      this.res = JSON.stringify(res)
    },
    clear () {
      this.pushed = ''
      this.res = ''
      this.packet = ''
    },
    async toggle (id) {
      let packet = { cmd: 'switch/toggle', id: id, state: this.switches[id - 1] }
      await this.send(packet)
    },
    status (item, prop) {
      return statusLevels[item.level] ? statusLevels[item.level][prop] : item[prop] || ''
    },
    statusClear () {
      this.statusLines = []
      this.statusCount = 0
    },
    _statusHandler (packet) {
      // converts level name to number, unknown level converted to 'info' 30
      // console.log(packet.level, packet.msg)
      if (typeof packet.level === 'string') {
        packet.level = Number(Object.keys(statusLevels).find(key => { return statusLevels[key].name === packet.level })) || 30
      }
      if (packet._clear) this.statusClear()
      // if (this.statusLines.length) {
      //   if (packet.level === 10 && this.statusLines[0].level === 10) this.statusLines.shift()
      // }
      // if (this.statusLines.length) {
      //   if (packet.level === this.statusLines[0].level && packet.msg === this.statusLines[0].msg) this.statusLines.shift()
      // }
      let previous = this.statusLines.findIndex(line => { return (line.level === packet.level && line.msg === packet.msg) })
      if (previous > -1) this.statusLines.splice(previous, 1)
      packet._count = ++this.statusCount
      this.statusLines.unshift(packet)
      if (this.statusLines > 20) this.statusLines.pop()
      if (packet.connected != null) this.connected = packet.connected
      if (packet.success === 'success') this.$q.notify({ color: 'positive', message: packet.msg })
    },
    _pushedHandler (packet) {
      // don't mutate the packet just in case
      let pushed = Object.assign({}, packet)
      delete pushed._header
      this.pushed = JSON.stringify(pushed) // display on UI
      if (packet.cmd === 'switch/status') {
        this.switches[packet.id - 1] = packet.state
      }
    }
  },
  async mounted () {
    Object.keys(statusLevels).forEach(level => {
      this.statusOptions.push(
        {
          label: statusLevels[level].name,
          value: Number(level)
        }
      )
    })
    window.addEventListener('unload', this.disconnect)
    this.clear()
    this.$socket.on('status', this._statusHandler.bind(this))
    this.$socket.on('pushed', this._pushedHandler.bind(this))
    await this.connect()
  },
  beforeDestroy () {
    window.removeEventListener('unload', this.disconnect)
  }
}
</script>

<style lang="stylus">

.on
    background $positive

.off
    background grey

</style>
