<!--
#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements.  See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License.  You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
-->

<template>
  <div class="app-container">
    <div class="filter-container">
      <el-button
        class="filter-item"
        style="margin-left: 10px;"
        type="primary"
        icon="el-icon-edit"
        @click="handleCreate"
      >
        {{ $t('table.add') }}
      </el-button>
    </div>

    <el-table
      :key="tableKey"
      v-loading="listLoading"
      :data="tableData"
      :span-method="objectSpanMethod"
      border
      fit
      highlight-current-row
      style="width: 100%;"
      @sort-change="sortChange"
    >
      <el-table-column
        v-for="(item, index) of tableKeys"
        :key="index"
        :label="item.key"
        :prop="item.key"
        :width="item.width"
        :class-name="item.align === 'left' ? '' : 'status-col'"
        header-align="center"
      >
        <template v-if="item.key === 'nodes'">
          <el-table-column
            label="IP/HOST"
            width="150"
            prop="ip"
            class-name="status-col"
          />

          <el-table-column
            label="Port"
            width="150"
            prop="port"
            class-name="status-col"
          />

          <el-table-column
            label="Weights"
            width="150"
            prop="weights"
            class-name="status-col"
          />
        </template>
      </el-table-column>
      <el-table-column
        :label="$t('table.actions')"
        align="center"
        class-name="fixed-width"
      >
        <template slot-scope="{row}">
          <el-button
            type="primary"
            size="mini"
            @click="handleToEdit(row)"
          >
            {{ $t('table.edit') }}
          </el-button>

          <el-button
            size="mini"
            type="danger"
            @click="handleRemove(row)"
          >
            {{ $t('table.delete') }}
          </el-button>
        </template>
      </el-table-column>
    </el-table>
  </div>
</template>

<script lang="ts">
import { Component, Vue } from 'vue-property-decorator'
import { Form } from 'element-ui'

import Pagination from '../../../components/Pagination/index.vue'

import { getUpstreamList, removeUpstream } from '../../../api/schema/upstream'

@Component({
  name: 'UpstreamList',
  components: {
    Pagination
  }
})
export default class extends Vue {
  private tableKey = 0
  private list = []
  private total = 0
  private listLoading = true
  private listQuery = {
    page: 1,
    limit: 20,
    importance: undefined,
    title: undefined,
    type: undefined,
    sort: '+id'
  }

  private tableData: any[] = []
  private tableKeys: any[] = []
  private spanArr: any[] = []
  private position = 0

  created() {
    this.getList()
  }

  private async getList() {
    this.listLoading = true

    this.tableKeys = [
      {
        key: 'id',
        width: 80
      }, {
        key: 'description',
        width: 300,
        align: 'left'
      }, {
        key: 'type',
        width: 120
      }, {
        key: 'nodes',
        width: 'auto'
      }, {
        key: 'other',
        width: 'auto'
      }
    ]

    let { node: { nodes = [] } } = await getUpstreamList() as any
    nodes = [...nodes].map((item: any) => {
      const id = item.key.match(/\/([a-zA-Z0-9-_]+)$/)[1]
      const fakeId = id
      const type = item.value.type
      const desc = item.value.desc

      return {
        id: fakeId,
        realId: id,
        type,
        nodes: item.value.nodes,
        other: JSON.stringify(item.value.k8s_deployment_info || {}),
        description: desc
      }
    })

    let tableData: any[] = []
    const arr = nodes.forEach((item: any) => {
      if (!item.nodes) {
        tableData = tableData.concat(item)
        return
      }
      Object.entries(item.nodes || {}).forEach(([ipWithPort, weights]) => {
        // 释放 nodes
        item.nodes = {}
        tableData = tableData.concat({
          ...item,
          ip: ipWithPort.split(':')[0],
          port: ipWithPort.split(':')[1],
          weights
        })
      })
    })

    tableData.sort((a, b) => b.id - a.id)

    this.tableData = tableData
    this.rowspan(0, 'id')
    this.rowspan(1, 'description')
    this.rowspan(2, 'type')
    this.rowspan(3, 'other')

    this.total = nodes.length

    setTimeout(() => {
      this.listLoading = false
    }, 0.5 * 1000)
  }

  private handleFilter() {
    this.listQuery.page = 1
    this.getList()
  }

  private handleRemove(row: any) {
    this.$confirm(`Do you want to remove upstream ${row.id}?`, 'Warning', {
      confirmButtonText: 'Confirm',
      cancelButtonText: 'Cancel',
      type: 'warning'
    })
      .then(async() => {
        await removeUpstream(row.realId)
        this.getList()
        this.$message.success(`Remove upstream ${row.id} successfully!`)
      })
  }

  private sortChange(data: any) {
    const { prop, order } = data
    if (prop === 'id') {
      this.sortByID(order)
    }
  }

  private sortByID(order: string) {
    if (order === 'ascending') {
      this.listQuery.sort = '+id'
    } else {
      this.listQuery.sort = '-id'
    }
    this.handleFilter()
  }

  private handleCreate() {
    this.$router.push({
      name: 'SchemaUpstreamCreate'
    })
  }

  private handleToEdit(row: any) {
    this.$router.push({
      name: 'SchemaUpstreamEdit',
      params: {
        id: row.realId
      }
    })
  }

  private rowspan(idx: number, prop: any) {
    this.spanArr[idx] = []
    this.position = 0
    this.tableData.forEach((item, index) => {
      if (index === 0) {
        this.spanArr[idx].push(1)
        this.position = 0
      } else {
        if (this.tableData[index][prop] === this.tableData[index - 1][prop]) {
          this.spanArr[idx][this.position] += 1
          this.spanArr[idx].push(0)
        } else {
          this.spanArr[idx].push(1)
          this.position = index
        }
      }
    })
  }

  private objectSpanMethod({ row, column, rowIndex, columnIndex }: any) {
    if (columnIndex === 6) {
      return {
        rowspan: this.spanArr[0][rowIndex],
        colspan: this.spanArr[0][rowIndex] > 0 ? 1 : 0
      }
    }

    if (columnIndex < 3) {
      return {
        rowspan: this.spanArr[0][rowIndex],
        colspan: this.spanArr[0][rowIndex] > 0 ? 1 : 0
      }
    }
  }
}
</script>
