<!--
  ~ 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="global-history">
    <div class="global-history-searchbar">
      <div class="searchbar-items">
        <div class="searchbar-item">
          <label class="label">{{$t('message.linkis.jobId')}}</label>
          <InputNumber
            v-model="searchBar.id"
            :placeholder="$t('message.linkis.formItems.id.placeholder')"
            style="width:100px;"
            :min="1"
          ></InputNumber>
        </div>
        <div v-if="isAdminModel" class="searchbar-item">
          <label class="label">{{$t('message.linkis.userName')}}</label>
          <Input
            :maxlength="50"
            v-model="searchBar.proxyUser"
            :placeholder="$t('message.linkis.searchName')"
            style="width:60px;"
          />
        </div>
        <div class="searchbar-item">
          <label class="label">{{$t('message.linkis.formItems.date.label')}}</label>
          <DatePicker
            :transfer="true"
            class="datepicker"
            :options="shortcutOpt"
            v-model="searchBar.shortcut"
            type="daterange"
            placement="bottom-start"
            format="yyyy-MM-dd"
            :placeholder="$t('message.linkis.formItems.date.placeholder')"
            style="width: 160px"
            :editable="false"
          />
        </div>
        <div class="searchbar-item">
          <label class="label">{{$t('message.linkis.formItems.creator.label')}}</label>
          <Input
            :maxlength="50"
            v-model.trim="searchBar.creator"
            :placeholder="$t('message.linkis.formItems.creator.placeholder')"
            style="width:80px;"
          />
        </div>
        <div class="searchbar-item">
          <label class="label">{{$t('message.linkis.formItems.engine.label')}}</label>
          <Select v-model="searchBar.engine" style="width: 70px">
            <Option v-for="(item) in getEngineTypes" :label="item === 'all' ? $t('message.linkis.engineTypes.all'): item" :value="item" :key="item" />
          </Select>
        </div>
        <div class="searchbar-item">
          <label class="label">{{$t('message.linkis.formItems.status.label')}}</label>
          <Select v-model="searchBar.status" style="width: 70px">
            <Option
              v-for="(item) in statusType"
              :label="item.label"
              :value="item.value"
              :key="item.value"
            />
          </Select>
        </div>
        <Form v-show="showAdvance" class="global-history-searchbar" :model="searchBar" inline>
          <FormItem prop="instance" :label="$t('message.linkis.formItems.instance.label')">
            <Input
              v-model="searchBar.instance"
              :placeholder="$t('message.linkis.formItems.instance.placeholder')"
              style="width:150px;"
            />
          </FormItem>
        </Form>
      </div>
      <div class="search-btns">
        <Button
          class="search-btn"
          type="primary"
          @click="search"
          style="margin-right: 10px;"
        >{{ $t('message.linkis.search') }}</Button>
        <Button
          class="search-btn"
          type="warning"
          @click="reset"
          style="margin-right: 10px;"
        >{{ $t('message.linkis.clearSearch') }}</Button>
        <Button class="search-btn" type="error" @click="stop" style="margin-right: 10px;">{{$t('message.linkis.stop')}}</Button>
        <Button
          class="search-btn"
          type="primary"
          @click="switchAdmin"
          v-show="isLogAdmin || isHistoryAdmin"
          style="margin-right: 10px;"
        >{{ isAdminModel ? $t('message.linkis.generalView') : $t('message.linkis.manageView') }}</Button>
        <Button
          class="search-btn"
          type="primary"
          @click="clickAdvance"
        >{{ showAdvance ? $t('message.linkis.hideAdvancedSearch') :  $t('message.linkis.showAdvancedSearch') }}</Button>
      </div>
    </div>
    <div class="global-history-table" :style="{width: '100%', 'height': moduleHeight +'px'}">
      <Icon v-show="isLoading" type="ios-loading" size="30" class="global-history-loading" />
      <history-table
        v-if="!isLoading"
        :columns="column"
        :data="list"
        :height="moduleHeight"
        :no-data-text="$t('message.linkis.noDataText')"
        border
        stripe
        @checkall="checkChange"
        @select-change="selectChange"
      />
    </div>
    <div class="global-history-page">
      <Page
        :total="pageSetting.total"
        :page-size="pageSetting.pageSize"
        :current="pageSetting.current"
        size="small"
        show-total
        show-elevator
        :prev-text="$t('message.linkis.previousPage')" :next-text="$t('message.linkis.nextPage')"
        @on-change="changePage"
      />
    </div>
  </div>
</template>
<script>
import storage from '@/common/helper/storage'
import table from '@/components/virtualTable'
import mixin from '@/common/service/mixin'
import api from '@/common/service/api'
export default {
  name: 'GlobalHistory',
  components: {
    historyTable: table.historyTable
  },
  mixins: [mixin],
  data() {
    const today = new Date(new Date().toLocaleDateString())
    return {
      list: [],
      column: [],
      getEngineTypes: [],
      isLoading: false,
      showAdvance: false,
      pageSetting: {
        total: 0,
        pageSize: 50,
        current: 1
      },
      searchBar: {
        id: null,
        proxyUser: '',
        creator: '',
        engine: 'all',
        status: '',
        shortcut: [today, today]
      },
      inputType: 'number',
      shortcutOpt: {
        shortcuts: [
          {
            text: this.$t('message.linkis.shortcuts.week'),
            value() {
              const end = new Date()
              const start = new Date()
              start.setTime(start.getTime() - 3600 * 1000 * 24 * 7)
              return [start, end]
            }
          },
          {
            text: this.$t('message.linkis.shortcuts.month'),
            value() {
              const end = new Date()
              const start = new Date()
              start.setTime(start.getTime() - 3600 * 1000 * 24 * 30)
              return [start, end]
            }
          },
          {
            text: this.$t('message.linkis.shortcuts.threeMonths'),
            value() {
              const end = new Date()
              const start = new Date()
              start.setTime(start.getTime() - 3600 * 1000 * 24 * 90)
              return [start, end]
            }
          }
        ]
      },
      statusType: [
        {
          label: this.$t('message.linkis.statusType.all'),
          value: 'all'
        },
        {
          label: this.$t('message.linkis.statusType.inited'),
          value: 'Inited'
        },
        {
          label: this.$t('message.linkis.statusType.running'),
          value: 'Running'
        },
        {
          label: this.$t('message.linkis.statusType.succeed'),
          value: 'Succeed'
        },
        {
          label: this.$t('message.linkis.statusType.cancelled'),
          value: 'Cancelled'
        },
        {
          label: this.$t('message.linkis.statusType.failed'),
          value: 'Failed'
        },
        {
          label: this.$t('message.linkis.statusType.scheduled'),
          value: 'Scheduled'
        },
        {
          label: this.$t('message.linkis.statusType.timeout'),
          value: 'Timeout'
        }
      ],
      engineTypes: [
        {
          label: this.$t('message.linkis.engineTypes.all'),
          value: 'all'
        },
        {
          label: 'spark',
          value: 'spark'
        },
        {
          label: 'hive',
          value: 'hive'
        },
        {
          label: 'pipeline',
          value: 'pipeline'
        },
        {
          label: 'python',
          value: 'python'
        },
        {
          label: 'flowexecution',
          value: 'flowexecution'
        },
        {
          label: 'appjoint',
          value: 'appjoint'
        },
        {
          label: 'shell',
          value: 'shell'
        }
      ],
      isLogAdmin: false,
      isHistoryAdmin: false,
      isAdminModel: false,
      moduleHeight: 300
    }
  },
  async created() {
    // Get whether it is a historical administrator(获取是否是历史管理员权限)
    await api.fetch('/jobhistory/governanceStationAdmin', 'get').then(res => {
      this.isLogAdmin = res.admin
      this.isHistoryAdmin = res.historyAdmin
    })
    await api.fetch('/configuration/engineType', 'get').then(res => {
      this.getEngineTypes = ['all', ...res.engineType]
    })
  },
  mounted() {
    this.init()
    this.moduleHeight = this.$parent.$el.clientHeight - 220
    // Monitor window changes and get browser width and height(监听窗口变化，获取浏览器宽高)
    window.addEventListener('resize', this.getHeight)
  },
  beforeDestroy() {
    // Monitor window changes and get browser width and height(监听窗口变化，获取浏览器宽高)
    storage.set('last-admin-model', this.isAdminModel)
    // storage.set('last-searchbar-status', this.searchBar)
    window.removeEventListener('resize', this.getHeight)
  },
  beforeRouteEnter(to, from, next) {
    if(from.name !== 'viewHistory') {
      sessionStorage.removeItem('last-admin-model');
      sessionStorage.removeItem('last-searchbar-status');
      sessionStorage.removeItem('last-pageSetting-status');
      sessionStorage.removeItem('last-searchbar-advance');
    }
    next();
  },
  activated() {
    this.init()
  },
  methods: {
    getHeight() {
      this.moduleHeight = this.$parent.$el.clientHeight - 228
      if(this.showAdvance) {
        this.moduleHeight -= 42
      }
    },
    clickAdvance() {
      this.showAdvance = !this.showAdvance
      this.getHeight()
    },
    init() {
      let isAdminModel = storage.get('last-admin-model')
      const lastSearch = storage.get('last-searchbar-status')
      const lastPage = storage.get('last-pageSetting-status')
      this.showAdvance = storage.get('last-searchbar-advance')
      this.getHeight()
      if (lastSearch) {
        if (lastSearch.shortcut[0] && lastSearch.shortcut[1]) {
          lastSearch.shortcut = [new Date(lastSearch.shortcut[0]), new Date(lastSearch.shortcut[1])]
        } else {
          const today = new Date(new Date().toLocaleDateString())
          lastSearch.shortcut = [today, today]
        }
        this.searchBar = lastSearch
      }
      if (lastPage) {
        this.pageSetting = lastPage
      }
      if (isAdminModel) {
        this.switchAdmin()
      } else {
        this.search()
      }
      storage.remove('last-pageSetting-status')
    },
    convertTimes(runningTime) {
      const time = Math.floor(runningTime / 1000)
      if (time < 0) {
        return `0${this.$t('message.linkis.time.second')}`
      } else if (time < 60) {
        return `${time}${this.$t('message.linkis.time.second')}`
      } else if (time < 3600) {
        return `${(time / 60).toPrecision(2)}${this.$t(
          'message.linkis.time.minute'
        )}`
      } else if (time < 86400) {
        return `${(time / 3600).toPrecision(2)}${this.$t(
          'message.linkis.time.hour'
        )}`
      }
      return `${(time / 86400).toPrecision(2)}${this.$t(
        'message.linkis.time.day'
      )}`
    },
    // Click to view historical details log and return results(点击查看历史详情日志和返回结果)
    async viewHistory(params) {
      let sourceJson = params.row.sourceJson
      if (typeof sourceJson === 'string') {
        try {
          sourceJson = JSON.parse(sourceJson)
        } catch (error) {
          window.console.log(sourceJson)
        }
      }
      let fileName = ''
      if (sourceJson && sourceJson.scriptPath) {
        fileName = sourceJson.scriptPath.split('/').pop()
      }
      if (sourceJson && sourceJson.nodeName) {
        fileName = sourceJson.nodeName
      }
      const query =  {
        taskID: params.row.taskID,
        execID: params.row.strongerExecId,
        status: params.row.status,
        fileName,
        engineInstance: params.row.engineInstance,
      }
      if (this.isAdminModel) {
        query.proxyUser = params.row.executeUser
      }
      storage.set('last-searchbar-status', this.searchBar)
      storage.set('last-pageSetting-status', this.pageSetting)
      storage.set('last-searchbar-advance', this.showAdvance)
      // Jump to view the history details page(跳转查看历史详情页面)
      this.$router.push({
        path: '/console/viewHistory',
        query
      })
    },

    getParams(page) {
      const startDate = this.searchBar.shortcut[0] ? new Date(this.searchBar.shortcut[0].setHours(0, 0, 0, 0)) : this.searchBar.shortcut[0]
      const endDate = this.searchBar.shortcut[1] ? new Date(this.searchBar.shortcut[1].setHours(23, 59, 59, 0)): this.searchBar.shortcut[1]
      const params = {
        taskID: this.searchBar.id,
        creator: this.searchBar.creator,
        executeApplicationName: this.searchBar.engine,
        status: this.searchBar.status,
        startDate: startDate && startDate.getTime(),
        endDate: endDate && endDate.getTime(),
        pageNow: page || this.pageSetting.current,
        pageSize: this.pageSetting.pageSize,
        proxyUser: this.searchBar.proxyUser,
        isAdminView: this.isAdminModel,
        instance: this.searchBar.instance?.replace(/ /g, '') || ''
      }
      if (!this.isAdminModel) {
        delete params.proxyUser
      }
      if (this.searchBar.id) {
        delete params.creator
        delete params.executeApplicationName
        delete params.status
        delete params.startDate
        delete params.endDate
        delete params.proxyUser
        delete params.instance
      } else {
        let { engine, status, shortcut } = this.searchBar
        if (engine === 'all') {
          delete params.executeApplicationName
        }
        if (status === 'all') {
          delete params.status
        }
        if (!shortcut[0]) {
          delete params.startDate
        }
        if (!shortcut[1]) {
          delete params.endDate
        }
        delete params.taskID
      }
      return params
    },
    changePage(page) {
      this.isLoading = true
      const params = this.getParams(page)
      this.column = this.getColumns()
      api
        .fetch('/jobhistory/list', params, 'get')
        .then(rst => {
          this.isLoading = false
          this.list = this.getList(rst.tasks)
          this.pageSetting.current = page
          this.pageSetting.total = rst.totalPage
        })
        .catch(() => {
          this.isLoading = false
          this.list = []
        })
    },
    search() {
      this.isLoading = true
      const params = this.getParams()
      this.column = this.getColumns()
      api
        .fetch('/jobhistory/list', params, 'get')
        .then(rst => {
          this.pageSetting.total = rst.totalPage
          this.isLoading = false
          this.list = this.getList(rst.tasks)
        })
        .catch(() => {
          this.list = []
          this.isLoading = false
        })
    },
    getList(list) {
      const getFailedReason = item => {
        return item.errCode && item.errDesc
          ? item.errCode + item.errDesc
          : item.errCode || item.errDesc || ''
      }
      if (!this.isAdminModel) {
        return list.map(item => {
          return {
            disabled: ['Submitted', 'Inited', 'Scheduled', 'Running'].indexOf(item.status) === -1,
            taskID: item.taskID,
            strongerExecId: item.strongerExecId,
            source: item.sourceTailor,
            executionCode: item.executionCode,
            status: item.status,
            costTime: item.costTime,
            requestApplicationName: item.requestApplicationName,
            executeApplicationName: item.executeApplicationName,
            createdTime: item.createdTime,
            progress: item.progress,
            failedReason: getFailedReason(item),
            runType: item.runType,
            instance: item.instance,
            engineInstance: item.engineInstance,
          }
        })
      }
      return list.map(item => {
        return Object.assign(item, {
          disabled:
              ['Submitted', 'Inited', 'Scheduled', 'Running'].indexOf(item.status) === -1,
          failedReason: getFailedReason(item),
          source: item.sourceTailor
        })
      })
    },
    checkChange(v) {
      this.list = this.list.map(it => {
        it.checked = !it.disabled && v
        return it
      })
    },
    selectChange() {
      this.list = this.list.slice(0)
    },
    getColumns() {
      const column = [
        {
          title: '',
          key: 'checked',
          align: 'center',
          width: 60,
          renderType: 'checkbox'
        },
        {
          title: this.$t('message.linkis.tableColumns.control.title'),
          key: 'control',
          fixed: 'right',
          align: 'center',
          width: 60,
          renderType: 'button',
          renderParams: [
            {
              label: this.$t('message.linkis.tableColumns.control.label'),
              action: this.viewHistory
            }
          ]
        },
        {
          title: this.$t('message.linkis.tableColumns.taskID'),
          key: 'taskID',
          align: 'center',
          width: 90
        },
        {
          title: this.$t('message.linkis.tableColumns.fileName'),
          key: 'source',
          align: 'center',
          ellipsis: true,
          width: 170
        },
        {
          title: this.$t('message.linkis.tableColumns.executionCode'),
          key: 'executionCode',
          align: 'center',
          width: 420,
          // overflow to show(溢出以...显示)
          ellipsis: true
          // renderType: 'tooltip',
        },
        {
          title: this.$t('message.linkis.tableColumns.status'),
          key: 'status',
          align: 'center',
          width: 164,
          renderType: 'if',
          renderParams: {
            action: this.setRenderType
          }
        },
        {
          title: this.$t('message.linkis.tableColumns.costTime'),
          key: 'costTime',
          align: 'center',
          width: 100,
          renderType: 'convertTime'
        },
        {
          title: this.$t('message.linkis.tableColumns.failedReason'),
          key: 'failedReason',
          align: 'center',
          className: 'history-failed',
          width: 200,
          renderType: 'a',
          renderParams: {
            hasDoc: this.checkIfHasDoc,
            action: this.linkTo
          }
        },
        {
          title: this.$t('message.linkis.tableColumns.requestApplicationName') + ' / ' + this.$t('message.linkis.tableColumns.executeApplicationName'),
          key: 'requestApplicationName',
          align: 'center',
          width: 130,
          renderType: 'concat',
          renderParams: {
            concatKey: 'executeApplicationName'
          }

        },
        {
          title: this.$t('message.linkis.tableColumns.user'),
          key: 'umUser',
          align: 'center',
          width: 80
        },
        {
          title: this.$t('message.linkis.tableColumns.createdTime'),
          key: 'createdTime',
          align: 'center',
          width: 150,
          renderType: 'formatTime'
        }
      ]
      if (!this.isAdminModel) {
        const index = column.findIndex(item => item.key === 'umUser')
        column.splice(index, 1)
      }
      return column
    },
    reset() {
      this.searchBar = {
        id: null,
        proxyUser: '',
        creator: '',
        engine: 'all',
        status: 'all',
        shortcut: ''
      }
    },
    switchAdmin() {
      if (!this.isLoading) {
        if (this.isAdminModel) {
          this.searchBar.id = null
          this.searchBar.proxyUser = ''
        }
        this.isAdminModel = !this.isAdminModel
        this.search()
      }
    },
    linkTo(params) {
      this.$router.push({
        path: '/console/FAQ',
        query: {
          errCode: parseInt(params.row.failedReason),
          isSkip: true
        }
      })
    },
    checkIfHasDoc(params) {
      const errCodeList = [11011, 11012, 11013, 11014, 11015, 11016, 11017]
      const errCode = parseInt(params.row.failedReason)
      if (errCodeList.indexOf(errCode) !== -1) {
        return true
      }
      return false
    },
    setRenderType(params) {
      if (params.row.status === 'Running' && params.row.progress !== 0) {
        return {
          type: 'Progress',
          value: params.row.progress
        }
      } else {
        return {
          type: 'Tag',
          value: params.row.status
        }
      }
    },
    stop() {
      const selected = this.list.filter(it => it.checked)
      if (!selected.length) {
        this.$Message.warning(this.$t('message.linkis.unselect'))
        return;
      }
      this.$Modal.confirm({
        title: this.$t('message.linkis.modal.modalTitle'),
        content: this.$t('message.linkis.modal.modalDeleteTask'),
        onOk: ()=>{
          const inst = {}
          selected.forEach(it => {
            if (inst[it.instance]) {
              inst[it.instance].taskIDList.push(it.taskID)
              inst[it.instance].idList.push(it.strongerExecId)
            } else {
              inst[it.instance] = {
                taskIDList: [it.taskID],
                idList: [it.strongerExecId]
              }
            }
          })
          const p = []
          Object.keys(inst).forEach(instkey => {
            if (instkey) p.push(api.fetch(`/entrance/${inst[instkey].idList[0]}/killJobs`, { idList: inst[instkey].idList, taskIDList: inst[instkey].taskIDList }, 'post'))
          })

          Promise.all(p).then(()=> {
            this.$Message.success(this.$t('message.linkis.udf.success'));
            this.search()
          })
        }
      })
    }
  }
}
</script>
<style src="./index.scss" lang="scss"></style>
