<template>
  <el-container>
    <el-header height="220">
      <h3>Docker 容器列表</h3>
      <el-row style="margin-top: 10px">
        <span>
          <span v-if="wsConnectStatus" style="color: green; margin: 5px">WebSocket 已连接</span>
          <span v-if="!wsConnectStatus" style="color: red; margin: 5px">WebSocket 未连接</span>
        </span>
        <el-select
          v-model="env"
          size="mini"
          placeholder="环境"
          style="margin-left: 5px"
          @change="onSelectChange"
        >
          <el-option
            v-for="(item, index) in envList"
            :key="index"
            :label="item.label"
            :value="item.value"
          />
        </el-select>
        <el-select
          v-model="machine"
          size="mini"
          placeholder="机器"
          style="margin-left: 5px"
          @change="onSelectChange1"
        >
          <el-option
            v-for="(item, index) in machineList"
            :key="index"
            :label="item.label"
            :value="item.value"
          />
        </el-select>
        <el-button size="mini" type="warning" icon="el-icon-refresh" style="margin-left: 5px" @click="onRefresh">刷新</el-button>
        <el-button size="mini" type="warning" icon="el-icon-files" style="margin-left: 5px" @click="onGetImages">镜像列表</el-button>
      </el-row>
    </el-header>
    <el-main>
      <el-table
        :data="dataList"
        border
        height="480"
        style="width: 100%"
      >
        <el-table-column
          prop="name"
          label="容器名"
        />
        <el-table-column
          prop="status"
          label="状态"
        />
        <el-table-column
          prop="createdAt"
          label="创建时间"
        />
        <el-table-column
          prop="repoTag"
          label="依赖镜像"
        />
        <el-table-column
          fixed="right"
          label="操作"
          width="210"
        >
          <template slot-scope="scope">
            <el-button
              size="mini"
              type="danger"
              @click="handleDelete(scope.$index, scope.row)"
            >删除</el-button>
          </template>
        </el-table-column>
      </el-table>
    </el-main>

    <el-dialog
      title="镜像列表"
      append-to-body
      :visible.sync="showImageDialog"
      width="70%"
      center
    >
      <template>
        <el-select
          v-model="queryInfo.type"
          size="mini"
          style="margin-left: 5px"
        >
          <el-option label="关键字匹配" value="1" />
          <el-option label="前缀匹配" value="2" />
        </el-select>
        <el-input
          v-model="queryInfo.keyword"
          size="mini"
          style="width: 20%; padding: 3px"
          clearable
          placeholder="标题"
        />
        <el-button size="mini" type="success" icon="el-icon-search" style="margin-left: 5px" @click="onGetImages">查询</el-button>
        <el-table
          ref="multipleTable"
          :data="dataList1"
          border
          height="480"
          style="margin-left: 5px; width: 100%"
          @selection-change="handleSelectionChange"
        >
          <el-table-column
            type="selection"
          />
          <el-table-column
            prop="repoTag"
            label="镜像标签"
          />
          <el-table-column
            prop="createdAt"
            label="创建时间"
          />
          <el-table-column
            prop="totalContainers"
            label="使用的容器数量"
          />
        </el-table>
        <el-button size="mini" type="success" icon="el-icon-minus" style="margin: 5px" @click="toggleSelection()">取消已选择</el-button>
        <el-button size="mini" type="success" icon="el-icon-delete" style="margin: 5px" @click="deleteSelection()">删除已选择</el-button>
      </template>
    </el-dialog>
  </el-container>
</template>

<script>
import { getEnvList, getMachineSessions } from '@/api/devops'

export default {
  name: 'Docker',
  data() {
    return {
      env: 'test',
      envList: [],
      machine: '',
      machineList: [],
      queryInfo: {
        type: '1',
        keyword: ''
      },
      multipleSelection: [],
      dataList: [],
      dockerContainerList: [],
      showImageDialog: false,
      dataList1: [],
      wsClient: null,
      wsConnectStatus: false,
      wsReconnectLock: false
    }
  },
  created() {
    document.title = 'Docker 列表'

    getEnvList().then(resp => {
      if (resp.code === 0) {
        this.env = resp.data.userEnv
        this.envList = resp.data.envList
        this.getMachineList(this.env)
      } else {
        this.$message.error(resp.msg)
      }
    }).catch(error => {
      this.$message.error(error.message)
    })
    this.initWebSocket()
  },
  methods: {
    getMachineList(env) {
      getMachineSessions(env).then(resp => {
        if (resp.code === 0) {
          this.machineList = resp.data
        } else {
          this.$message.error(resp.msg)
        }
      }).catch(error => {
        this.$message.error(error.message)
      })
    },
    handleSelectionChange(val) {
      this.multipleSelection = val
    },
    toggleSelection(rows) {
      if (rows) {
        rows.forEach(row => {
          this.$refs.multipleTable.toggleRowSelection(row)
        })
      } else {
        this.$refs.multipleTable.clearSelection()
      }
    },
    deleteSelection() {
      if (this.multipleSelection.length === 0) {
        this.$message.warning('请先选择要删除的项')
        return
      }

      const imageIds = []
      for (const item of this.multipleSelection) {
        imageIds.push(item.imageId)
      }
      this.$confirm('确定要删除选择的镜像?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        const formData = new FormData()
        formData.append('imageIds', imageIds)

        const jsonPayload = {}
        jsonPayload.machineId = this.machine
        jsonPayload.ops = 'imageRm'
        jsonPayload.payload = imageIds
        this.sendMessage(JSON.stringify(jsonPayload))
      }).catch(() => {
        this.$message({
          type: 'info',
          message: '已取消'
        })
      })
    },
    handleDelete(index, row) {
      this.$confirm('确定要删除选择的容器?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        const formData = new FormData()
        formData.append('opsType', 3)
        formData.append('containerId', row.containerId)

        const containerIds = []
        containerIds.push(row.containerId)
        const jsonPayload = {}
        jsonPayload.machineId = this.machine
        jsonPayload.ops = 'containerRm'
        jsonPayload.payload = containerIds
        this.sendMessage(JSON.stringify(jsonPayload))
      }).catch(() => {
        this.$message({
          type: 'info',
          message: '已取消'
        })
      })
    },
    onRefresh() {
      const jsonPayload = {}
      jsonPayload.machineId = this.machine
      jsonPayload.ops = 'containerList'
      this.sendMessage(JSON.stringify(jsonPayload))
    },
    onGetImages() {
      const jsonPayload = {}
      jsonPayload.machineId = this.machine
      jsonPayload.ops = 'imageList'
      jsonPayload.dockerQuery = this.queryInfo
      this.sendMessage(JSON.stringify(jsonPayload))
      this.showImageDialog = true
    },
    onSelectChange() {
      this.machine = ''
      this.getMachineList(this.env)
    },
    onSelectChange1() {
      if (!this.wsConnectStatus) {
        this.$message.warning('websocket 未连接')
        return
      }

      const jsonPayload = {}
      jsonPayload.machineId = this.machine
      jsonPayload.ops = 'containerList'
      this.sendMessage(JSON.stringify(jsonPayload))
    },
    // ****************************************************************************************************************
    // WebSocket相关
    // ****************************************************************************************************************
    getUrl() {
      const protocol = location.protocol
      const hostname = location.hostname
      const port = location.port
      let prefix
      if (protocol === 'https:') {
        if (port === '' || port === 443) {
          prefix = 'wss://' + hostname
        } else {
          prefix = 'wss://' + hostname + ':' + port
        }
      } else {
        if (port === '' || port === 80) {
          prefix = 'ws://' + hostname
        } else {
          prefix = 'ws://' + hostname + ':' + port
        }
      }

      var token = '0123456789'
      var params = 'token=' + token
      return prefix + '/bgws/frontend?' + params
    },
    initWebSocket() {
      if ('WebSocket' in window) {
        const wsUrl = this.getUrl()
        console.log(wsUrl)
        this.wsClient = new WebSocket(wsUrl)
        const that = this
        this.wsClient.onopen = function() {
          that.setOnline()
        }
        this.wsClient.onclose = function() {
          that.setOffline()
          that.reconnect()
        }
        this.wsClient.onerror = function() {
          that.setOffline()
          console.log('websocket connection error...')
          that.reconnect()
        }
        this.wsClient.onmessage = function(evt) {
          const message = JSON.parse(evt.data)
          that.processMessage(message)
        }
      } else {
        // 浏览器不支持 WebSocket
        this.$message.error('您的浏览器不支持 WebSocket!')
      }
    },
    setOnline() {
      this.wsConnectStatus = true
    },
    setOffline() {
      this.wsConnectStatus = false
    },
    reconnect() {
      if (this.wsReconnectLock) return
      this.wsReconnectLock = true
      const that = this
      setTimeout(function() {
        console.log('websocket reconnecting...')
        that.initWebSocket()
        that.wsReconnectLock = false
      }, 5000)
    },
    sendMessage(message) {
      this.wsClient.send(message)
    },
    processMessage(message) {
      const ops = message.ops
      if (ops === 'containerList') {
        this.dataList = []
        this.dataList = message.resultList
      } else if (ops === 'imageList') {
        this.dataList1 = []
        this.dataList1 = message.resultList
      } else {
        console.log(message)
      }
    }
  }
}
</script>

<style>
</style>
