<template>
  <div class="app-container">
    <el-button
      type="primary"
      @click="handleCreateRole"
    >
      {{ $t('permission.createRole') }}
    </el-button>

    <el-table
      :data="rolesList"
      stripe
      style="width: 100%;margin-top:30px;"
      border
    >
      <el-table-column
        align="center"
        label="角色key"
        prop="key"
      >
      </el-table-column>
      <el-table-column
        align="center"
        label="角色名"
        prop="name"
      >
      </el-table-column>
      <el-table-column
          align="center"
          label="权限"
          prop="permissions"
          :formatter="formatPermissionCol"
      >
      </el-table-column>
      <el-table-column
        align="header-center"
        label="备注"
        prop="comment"
      >
      </el-table-column>
      <el-table-column
        align="center"
        label="操作"
      >
        <template slot-scope="scope">
          <el-button
            type="primary"
            size="small"
            @click="handleEdit(scope)"
          >
            {{ $t('permission.editPermission') }}
          </el-button>
          <el-button
            type="danger"
            size="small"
            @click="handleDelete(scope)"
          >
            {{ $t('permission.delete') }}
          </el-button>
        </template>
      </el-table-column>
    </el-table>

    <el-dialog
      :visible.sync="dialogVisible"
      :title="dialogType==='edit'?'Edit Role':'New Role'"
    >
      <el-form
        :model="role"
        label-width="80px"
        label-position="left"
      >
        <el-form-item label="角色key">
          <el-input
              :readonly="dialogType==='edit'"
              v-model="role.key"
              placeholder="角色key"
          />
        </el-form-item>
        <el-form-item label="角色名">
          <el-input
            v-model="role.name"
            placeholder="角色名"
          />
        </el-form-item>
        <el-form-item label="操作" prop="permissions">
          <el-select
              v-model="role.permissions"
              multiple
              filterable
              :filter-method = "filterPermission"
              allow-create
              default-first-option
              style="width: 60%"
              @change="permissionChange"
              placeholder="请选择权限">
            <el-option
                v-for="item in filterPermissions"
                :key="item.id"
                :label="item.label"
                :value="item.id">
              <span style="float: left">{{ item.label }}</span>
              <span style="float: right; color: #8492a6; font-size: 13px">{{ item.id }}</span>
            </el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="备注">
          <el-input
            v-model="role.comment"
            :autosize="{minRows: 2, maxRows: 4}"
            type="textarea"
            placeholder="备注"
          />
        </el-form-item>
      </el-form>
      <div style="text-align:right;">
        <el-button
          type="danger"
          @click="dialogVisible=false"
        >
          {{ $t('permission.cancel') }}
        </el-button>
        <el-button
          type="primary"
          @click="confirmRole"
        >
          {{ $t('permission.confirm') }}
        </el-button>
      </div>
    </el-dialog>
  </div>
</template>

<script lang="ts">
import { cloneDeep } from 'lodash'
import { Component, Vue } from 'vue-property-decorator'
import { deleteRole, getRoles, saveRole } from '@/api/roles'
import TagInput from '@/components/TagInput/index.vue'
import { getPermissions } from '@/api/permissions'

export interface IRole {
  key: string
  name: string
  comment: string
  permissions: string[]
}

export interface IPermission {
  id: string
  label: string
}

const defaultRole: IRole = {
  key: '',
  name: '',
  comment: '',
  permissions: []
}

@Component({
  name: 'RoleSystem',
  components: {
    TagInput
  }
})
export default class extends Vue {
  private role = Object.assign({}, defaultRole)
  private rolesList: IRole[] = []
  private dialogVisible = false
  private dialogType = 'new'
  private checkStrictly = false
  private permissions: IPermission[] = []
  private filterPermissions: IPermission[] = []

  async created() {
    await this.getRoles()
    await this.getRemotePermissions()
  }

  private async getRoles() {
    const { data } = await getRoles({ /* Your params here */ })
    this.rolesList = data
  }

  private handleCreateRole() {
    this.role = Object.assign({}, defaultRole)

    this.dialogType = 'new'
    this.dialogVisible = true
  }

  private handleEdit(scope: any) {
    this.dialogType = 'edit'
    this.dialogVisible = true
    this.checkStrictly = true
    this.role = cloneDeep(scope.row)
  }

  private handleDelete(scope: any) {
    const { $index, row } = scope
    this.$confirm('Confirm to remove the role?', 'Warning', {
      confirmButtonText: 'Confirm',
      cancelButtonText: 'Cancel',
      type: 'warning'
    })
      .then(async() => {
        await deleteRole(row.key)
        this.rolesList.splice($index, 1)
        this.$message({
          type: 'success',
          message: 'Deleted!'
        })
      })
      .catch(err => { console.error(err) })
  }

  private async confirmRole() {
    const isEdit = this.dialogType === 'edit'
    await saveRole(this.role)

    if (isEdit) {
      for (let index = 0; index < this.rolesList.length; index++) {
        if (this.rolesList[index].key === this.role.key) {
          this.rolesList.splice(index, 1, Object.assign({}, this.role))
          break
        }
      }
    } else {
      this.rolesList.push(this.role)
    }

    const { permissions, key, name } = this.role
    this.dialogVisible = false
    this.$notify({
      title: 'Success',
      dangerouslyUseHTMLString: true,
      message: `
          <div>Role Key: ${key}</div>
          <div>Role Name: ${name}</div>
          <div>Description: ${permissions}</div>
        `,
      type: 'success'
    })
  }

  private async getRemotePermissions() {
    const { data } = await getPermissions()
    for (const sub of data) {
      for (const c of sub.children) {
        this.permissions.push({
          id: c.id,
          label: `${sub.label}:${c.label}`
        })
      }
    }
    this.filterPermission()
  }

  private filterPermission(val?: string) {
    if (val) {
      this.filterPermissions = this.permissions.filter(data => {
        return data.id.indexOf(val) >= 0 || data.label.indexOf(val) >= 0
      })
    } else {
      this.filterPermissions = [...this.permissions]
    }
  }

  private formatPermissionCol(row: number, column: number, cellValue: string[]) {
    const results: string[] = []
    for (const p of cellValue) {
      const data: IPermission | undefined = this.permissions.find(o => o.id === p)
      if (data) {
        results.push(data.label)
      } else {
        results.push(p)
      }
    }
    return results.join(',')
  }

  private permissionChange(vals: string[]) {
    if (vals.length > 0) {
      const lastVal = this.role.permissions[this.role.permissions.length - 1]
      if (!/^([a-zA-Z0-9*]:[a-zA-Z0-9*]|\*)$/.test(lastVal)) {
        this.role.permissions.pop()
        this.$message({
          type: 'error',
          message: '权限的格式错误, 比如 app:read, app:*'
        })
      }
    }
  }
}
</script>
